cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

socket-ssl.c (4005B)


      1/*
      2 * Licensed to the Apache Software Foundation (ASF) under one
      3 * or more contributor license agreements.  See the NOTICE file
      4 * distributed with this work for additional information
      5 * regarding copyright ownership.  The ASF licenses this file
      6 * to you under the Apache License, Version 2.0 (the
      7 * "License"); you may not use this file except in compliance
      8 * with the License.  You may obtain a copy of the License at
      9 *
     10 *   http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing,
     13 * software distributed under the License is distributed on an
     14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     15 * KIND, either express or implied.  See the License for the
     16 * specific language governing permissions and limitations
     17 * under the License.
     18 */
     19
     20#include "config.h"
     21
     22#include "guacamole/mem.h"
     23#include "guacamole/error.h"
     24#include "guacamole/socket-ssl.h"
     25#include "guacamole/socket.h"
     26#include "wait-fd.h"
     27
     28#include <stdlib.h>
     29
     30#include <openssl/ssl.h>
     31
     32static ssize_t __guac_socket_ssl_read_handler(guac_socket* socket,
     33        void* buf, size_t count) {
     34
     35    /* Read from socket */
     36    guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data;
     37    int retval;
     38
     39    retval = SSL_read(data->ssl, buf, count);
     40
     41    /* Record errors in guac_error */
     42    if (retval <= 0) {
     43        guac_error = GUAC_STATUS_SEE_ERRNO;
     44        guac_error_message = "Error reading data from secure socket";
     45    }
     46
     47    return retval;
     48
     49}
     50
     51static ssize_t __guac_socket_ssl_write_handler(guac_socket* socket,
     52        const void* buf, size_t count) {
     53
     54    /* Write data to socket */
     55    guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data;
     56    int retval;
     57
     58    retval = SSL_write(data->ssl, buf, count);
     59
     60    /* Record errors in guac_error */
     61    if (retval <= 0) {
     62        guac_error = GUAC_STATUS_SEE_ERRNO;
     63        guac_error_message = "Error writing data to secure socket";
     64    }
     65
     66    return retval;
     67
     68}
     69
     70static int __guac_socket_ssl_select_handler(guac_socket* socket, int usec_timeout) {
     71
     72    guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data;
     73    int retval = guac_wait_for_fd(data->fd, usec_timeout);
     74
     75    /* Properly set guac_error */
     76    if (retval <  0) {
     77        guac_error = GUAC_STATUS_SEE_ERRNO;
     78        guac_error_message = "Error while waiting for data on secure socket";
     79    }
     80
     81    else if (retval == 0) {
     82        guac_error = GUAC_STATUS_TIMEOUT;
     83        guac_error_message = "Timeout while waiting for data on secure socket";
     84    }
     85
     86    return retval;
     87
     88}
     89
     90static int __guac_socket_ssl_free_handler(guac_socket* socket) {
     91
     92    /* Shutdown SSL */
     93    guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data;
     94    SSL_shutdown(data->ssl);
     95    SSL_free(data->ssl);
     96
     97    /* Close file descriptor */
     98    close(data->fd);
     99
    100    guac_mem_free(data);
    101    return 0;
    102}
    103
    104guac_socket* guac_socket_open_secure(SSL_CTX* context, int fd) {
    105
    106    /* Create new SSL structure */
    107    SSL* ssl = SSL_new(context);
    108    if (ssl == NULL)
    109        return NULL;
    110
    111    /* Allocate socket and associated data */
    112    guac_socket* socket = guac_socket_alloc();
    113    guac_socket_ssl_data* data = guac_mem_alloc(sizeof(guac_socket_ssl_data));
    114
    115    /* Init SSL */
    116    data->context = context;
    117    data->ssl = ssl;
    118    SSL_set_fd(data->ssl, fd);
    119
    120    /* Accept SSL connection, handle errors */
    121    if (SSL_accept(ssl) <= 0) {
    122
    123        guac_error = GUAC_STATUS_INTERNAL_ERROR;
    124        guac_error_message = "SSL accept failed";
    125
    126        guac_mem_free(data);
    127        guac_socket_free(socket);
    128        SSL_free(ssl);
    129        return NULL;
    130    }
    131
    132    /* Store file descriptor as socket data */
    133    data->fd = fd;
    134    socket->data = data;
    135
    136    /* Set read/write handlers */
    137    socket->read_handler   = __guac_socket_ssl_read_handler;
    138    socket->write_handler  = __guac_socket_ssl_write_handler;
    139    socket->select_handler = __guac_socket_ssl_select_handler;
    140    socket->free_handler   = __guac_socket_ssl_free_handler;
    141
    142    return socket;
    143
    144}
    145