cscg24-guacamole

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

move-fd.c (3258B)


      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#include "move-fd.h"
     22
     23/* Required for CMSG_* macros on BSD */
     24#define __BSD_VISIBLE 1
     25
     26#include <errno.h>
     27#include <fcntl.h>
     28#include <string.h>
     29#include <sys/types.h>
     30#include <sys/socket.h>
     31#include <sys/wait.h>
     32#include <unistd.h>
     33
     34int guacd_send_fd(int sock, int fd) {
     35
     36    struct msghdr message = {0};
     37    char message_data[] = {'G'};
     38
     39    /* Assign data buffer */
     40    struct iovec io_vector[1];
     41    io_vector[0].iov_base = message_data;
     42    io_vector[0].iov_len  = sizeof(message_data);
     43    message.msg_iov    = io_vector;
     44    message.msg_iovlen = 1;
     45
     46    /* Assign ancillary data buffer */
     47    char buffer[CMSG_SPACE(sizeof(fd))] = {0};
     48    message.msg_control = buffer;
     49    message.msg_controllen = sizeof(buffer);
     50
     51    /* Set fields of control message header */
     52    struct cmsghdr* control = CMSG_FIRSTHDR(&message);
     53    control->cmsg_level = SOL_SOCKET;
     54    control->cmsg_type  = SCM_RIGHTS;
     55    control->cmsg_len   = CMSG_LEN(sizeof(fd));
     56
     57    /* Add file descriptor to message data */
     58    memcpy(CMSG_DATA(control), &fd, sizeof(fd));
     59
     60    /* Send file descriptor */
     61    return (sendmsg(sock, &message, 0) == sizeof(message_data));
     62
     63}
     64
     65int guacd_recv_fd(int sock) {
     66
     67    int fd;
     68
     69    struct msghdr message = {0};
     70    char message_data[1];
     71
     72    /* Assign data buffer */
     73    struct iovec io_vector[1];
     74    io_vector[0].iov_base = message_data;
     75    io_vector[0].iov_len  = sizeof(message_data);
     76    message.msg_iov    = io_vector;
     77    message.msg_iovlen = 1;
     78
     79
     80    /* Assign ancillary data buffer */
     81    char buffer[CMSG_SPACE(sizeof(fd))];
     82    message.msg_control = buffer;
     83    message.msg_controllen = sizeof(buffer);
     84
     85    /* Receive file descriptor */
     86    if (recvmsg(sock, &message, 0) == sizeof(message_data)) {
     87
     88        /* Validate payload */
     89        if (message_data[0] != 'G') {
     90            errno = EPROTO;
     91            return -1;
     92        }
     93
     94        /* Iterate control headers, looking for the sent file descriptor */
     95        struct cmsghdr* control;
     96        for (control = CMSG_FIRSTHDR(&message); control != NULL; control = CMSG_NXTHDR(&message, control)) {
     97
     98            /* Pull file descriptor from data */
     99            if (control->cmsg_level == SOL_SOCKET && control->cmsg_type == SCM_RIGHTS) {
    100                memcpy(&fd, CMSG_DATA(control), sizeof(fd));
    101                return fd;
    102            }
    103
    104        }
    105
    106    } /* end if recvmsg() success */
    107
    108    /* Failed to receive file descriptor */
    109    return -1;
    110
    111}
    112