Exemple #1
0
/*
 * Receive a token from a file descriptor.  Takes the file descriptor, a
 * buffer into which to store the token, a pointer into which to store the
 * flags, and the maximum token length we're willing to accept.  Returns
 * TOKEN_OK on success.  On failure, returns one of:
 *
 *     TOKEN_FAIL_SYSTEM       System call failed, errno set
 *     TOKEN_FAIL_SOCKET       Socket call failed, socket_errno set
 *     TOKEN_FAIL_INVALID      Invalid token format
 *     TOKEN_FAIL_LARGE        Token data larger than provided limit
 *     TOKEN_FAIL_EOF          Unexpected end of file
 *     TOKEN_FAIL_TIMEOUT      Timeout receiving token
 *
 * TOKEN_FAIL_SYSTEM and TOKEN_FAIL_SOCKET are the same on UNIX but different
 * on Windows.
 *
 * recv_token reads the token flags (a single byte, even though they're stored
 * into an integer, then reads the token length (as a network long), allocates
 * memory to hold the data, and then reads the token data from the file
 * descriptor.  On a successful return, the value member of the token should
 * be freed with free().
 */
enum token_status
token_recv(socket_type fd, int *flags, gss_buffer_t tok, size_t max,
           time_t timeout)
{
    OM_uint32 len;
    unsigned char char_flags;
    int err;

    if (!network_read(fd, &char_flags, 1, timeout))
        return map_socket_error(socket_errno);
    *flags = char_flags;

    if (!network_read(fd, &len, sizeof(OM_uint32), timeout))
        return map_socket_error(socket_errno);
    tok->length = ntohl(len);
    if (tok->length > max)
        return TOKEN_FAIL_LARGE;
    if (tok->length == 0) {
        tok->value = NULL;
        return TOKEN_OK;
    }

    tok->value = malloc(tok->length);
    if (tok->value == NULL)
        return TOKEN_FAIL_SYSTEM;
    if (!network_read(fd, tok->value, tok->length, timeout)) {
        err = socket_errno;
        free(tok->value);
        socket_set_errno(err);
        return map_socket_error(err);
    }
    return TOKEN_OK;
}
Exemple #2
0
/*
 * Send a token to a file descriptor.  Takes the file descriptor, the token,
 * and the flags (a single byte, even though they're passed in as an integer)
 * and writes them to the file descriptor.  Returns TOKEN_OK on success and
 * TOKEN_FAIL_SYSTEM, TOKEN_FAIL_SOCKET, or TOKEN_FAIL_TIMEOUT on an error
 * (including partial writes).
 */
enum token_status
token_send(socket_type fd, int flags, gss_buffer_t tok, time_t timeout)
{
    size_t buflen;
    char *buffer;
    bool okay;
    unsigned char char_flags = (unsigned char) flags;
    OM_uint32 len = htonl(tok->length);

    /* Send out the whole message in a single write. */
    if (tok->length > SIZE_MAX - 1 - sizeof(OM_uint32)) {
        errno = ENOMEM;
        return TOKEN_FAIL_SYSTEM;
    }
    buflen = 1 + sizeof(OM_uint32) + tok->length;
    buffer = malloc(buflen);
    if (buffer == NULL)
        return TOKEN_FAIL_SYSTEM;
    memcpy(buffer, &char_flags, 1);
    memcpy(buffer + 1, &len, sizeof(OM_uint32));
    memcpy(buffer + 1 + sizeof(OM_uint32), tok->value, tok->length);
    okay = network_write(fd, buffer, buflen, timeout);
    free(buffer);
    return okay ? TOKEN_OK : map_socket_error(socket_errno);
}