Esempio n. 1
0
/* Return true on usable data. */
static krb5_boolean
service_tcp_read(krb5_context context, const krb5_data *realm,
                 struct conn_state *conn, struct select_state *selstate)
{
    ssize_t nread;
    int e = 0;
    struct incoming_message *in = &conn->in;

    if (in->bufsizebytes_read == 4) {
        /* Reading data.  */
        nread = SOCKET_READ(conn->fd, &in->buf[in->pos], in->n_left);
        if (nread <= 0) {
            e = nread ? SOCKET_ERRNO : ECONNRESET;
            TRACE_SENDTO_KDC_TCP_ERROR_RECV(context, &conn->addr, e);
            kill_conn(context, conn, selstate);
            return FALSE;
        }
        in->n_left -= nread;
        in->pos += nread;
        if (in->n_left <= 0)
            return TRUE;
    } else {
        /* Reading length.  */
        nread = SOCKET_READ(conn->fd, in->bufsizebytes + in->bufsizebytes_read,
                            4 - in->bufsizebytes_read);
        if (nread <= 0) {
            e = nread ? SOCKET_ERRNO : ECONNRESET;
            TRACE_SENDTO_KDC_TCP_ERROR_RECV_LEN(context, &conn->addr, e);
            kill_conn(context, conn, selstate);
            return FALSE;
        }
        in->bufsizebytes_read += nread;
        if (in->bufsizebytes_read == 4) {
            unsigned long len = load_32_be(in->bufsizebytes);
            /* Arbitrary 1M cap.  */
            if (len > 1 * 1024 * 1024) {
                kill_conn(context, conn, selstate);
                return FALSE;
            }
            in->bufsize = in->n_left = len;
            in->pos = 0;
            in->buf = malloc(len);
            if (in->buf == NULL) {
                kill_conn(context, conn, selstate);
                return FALSE;
            }
        }
    }
    return FALSE;
}
Esempio n. 2
0
/*---------------------------------------------------------------------------*/
static int readn( SOCKET fd, char *buf, int n )
{
    long nleft, nread;

    nleft = n;
    while( nleft > 0 )
    {
        nread = SOCKET_READ( fd, buf, nleft );
        if( nread < 0 )
        {
	    break;
        }
        else if( nread == 0 )
        {
	    break;
        }
        else
        {
            nleft -= nread;
            buf += nread;
        }
    }

    return (n - nleft);
}
Esempio n. 3
0
File: proc.c Progetto: Lembed/uTLS
static int special_read(struct connstruct *cn, void *buf, size_t count)
{
    int res;

    if (cn->is_ssl) {
        uint8_t *read_buf;
        if ((res = ssl_read(cn->ssl, &read_buf)) > SSL_OK) {
            memcpy(buf, read_buf, res > (int)count ? count : res);
        }
    } else {
        res = SOCKET_READ(cn->networkdesc, buf, count);
    }

    return res;
}
Esempio n. 4
0
// Read a line of input from the socket.
//
static int mod_email_sock_readline(SOCKET sock, UTF8 *buffer, int maxlen)
{
    buffer[0] = '\0';

    if (IS_INVALID_SOCKET(sock))
    {
        return 0;
    }

    fd_set read_fds;
    FD_ZERO(&read_fds);
    FD_SET(sock, &read_fds);

    // Wait up to 1 second.
    //
    struct timeval tv;
    tv.tv_sec  = 1;
    tv.tv_usec = 0;

    // Check for data before giving up.
    //
    if (IS_SOCKET_ERROR(select(static_cast<int>(sock+1), &read_fds, NULL, NULL, &tv)))
    {
        return 0;
    }

    if (!FD_ISSET(sock, &read_fds))
    {
        return 0;
    }

    bool done = false;
    bool possible_close = false;
    int  pos = 0;

    while (  !done
          && pos < maxlen)
    {
        UTF8 getme[2];

        int numread = SOCKET_READ(sock, (char *)&getme[0], 1, 0);
        if (  IS_SOCKET_ERROR(numread)
           || 0 == numread)
        {
            if (possible_close)
            {
                done = true;
            }
            else
            {
                FD_ZERO(&read_fds);
                FD_SET(sock, &read_fds);

                // Wait up to 1 second.
                //
                tv.tv_sec  = 1;
                tv.tv_usec = 0;

                // Check for data before giving up.
                //
                if (IS_SOCKET_ERROR(select(static_cast<int>(sock+1), &read_fds, NULL, NULL, &tv)))
                {
                    done = true;
                }

                if (FD_ISSET(sock, &read_fds))
                {
                    possible_close = true;
                }
            }
        }
        else
        {
            possible_close = false;
            if (getme[0] != '\n')
            {
                buffer[pos++] = getme[0];
            }
            else
            {
                done = true;
            }
        }
    }
    buffer[pos] = '\0';

    return pos;
}
Esempio n. 5
0
/*
 * Some browsers use a hybrid SSLv2 "client hello" 
 */
int process_sslv23_client_hello(SSL *ssl)
{
    uint8_t *buf = ssl->bm_data;
    int bytes_needed = ((buf[0] & 0x7f) << 8) + buf[1];
    int version = (buf[3] << 4) + buf[4];
    int ret = SSL_OK;

    /* we have already read 3 extra bytes so far */
    int read_len = SOCKET_READ(ssl->client_fd, buf, bytes_needed-3);
    int cs_len = buf[1];
    int id_len = buf[3];
    int ch_len = buf[5];
    int i, j, offset = 8;   /* start at first cipher */
    int random_offset = 0;

    DISPLAY_BYTES(ssl, "received %d bytes", buf, read_len, read_len);
    
    /* should be v3.1 (TLSv1) or better - we'll send in v3.1 mode anyway */
    if (version < 0x31)
    {
        return SSL_ERROR_INVALID_VERSION;
    }

    add_packet(ssl, buf, read_len);

    /* connection has gone, so die */
    if (bytes_needed < 0)
    {
        return SSL_ERROR_CONN_LOST;
    }

    /* now work out what cipher suite we are going to use */
    for (j = 0; j < NUM_PROTOCOLS; j++)
    {
        for (i = 0; i < cs_len; i += 3)
        {
            if (ssl_prot_prefs[j] == buf[offset+i])
            {
                ssl->cipher = ssl_prot_prefs[j];
                goto server_hello;
            }
        }
    }

    /* ouch! protocol is not supported */
    ret = SSL_ERROR_NO_CIPHER;
    goto error;

server_hello:
    /* get the session id */
    offset += cs_len - 2;   /* we've gone 2 bytes past the end */
#ifndef CONFIG_SSL_SKELETON_MODE
    ssl->session = ssl_session_update(ssl->ssl_ctx->num_sessions,
            ssl->ssl_ctx->ssl_sessions, ssl, id_len ? &buf[offset] : NULL);
#endif

    /* get the client random data */
    offset += id_len;

    /* random can be anywhere between 16 and 32 bytes long - so it is padded
     * with 0's to the left */
    if (ch_len == 0x10)
    {
        random_offset += 0x10;
    }

    memcpy(&ssl->dc->client_random[random_offset], &buf[offset], ch_len);
    ret = send_server_hello_sequence(ssl);

error:
    return ret;
}
Esempio n. 6
0
static int
service_tcp_fd(krb5_context context, struct conn_state *conn,
               struct select_state *selstate, int ssflags)
{
    int e = 0;
    ssize_t nwritten, nread;

    if (!(ssflags & (SSF_READ|SSF_WRITE|SSF_EXCEPTION)))
        abort();
    switch (conn->state) {
        SOCKET_WRITEV_TEMP tmp;

    case CONNECTING:
        if (ssflags & SSF_READ) {
            /* Bad -- the KDC shouldn't be sending to us first.  */
            e = EINVAL /* ?? */;
        kill_conn:
            TRACE_SENDTO_KDC_TCP_DISCONNECT(context, conn);
            kill_conn(conn, selstate, e);
            if (e == EINVAL) {
                closesocket(conn->fd);
                conn->fd = INVALID_SOCKET;
            }
            return e == 0;
        }
        if (ssflags & SSF_EXCEPTION) {
        handle_exception:
            e = get_so_error(conn->fd);
            if (e)
                dprint("socket error on exception fd: %m", e);
            else
                dprint("no socket error info available on exception fd");
            goto kill_conn;
        }

        /*
         * Connect finished -- but did it succeed or fail?
         * UNIX sets can_write if failed.
         * Call getsockopt to see if error pending.
         *
         * (For most UNIX systems it works to just try writing the
         * first time and detect an error.  But Bill Dodd at IBM
         * reports that some version of AIX, SIGPIPE can result.)
         */
        e = get_so_error(conn->fd);
        if (e) {
            TRACE_SENDTO_KDC_TCP_ERROR_CONNECT(context, conn, e);
            dprint("socket error on write fd: %m", e);
            goto kill_conn;
        }
        conn->state = WRITING;
        goto try_writing;

    case WRITING:
        if (ssflags & SSF_READ) {
            e = E2BIG;
            /* Bad -- the KDC shouldn't be sending anything yet.  */
            goto kill_conn;
        }
        if (ssflags & SSF_EXCEPTION)
            goto handle_exception;

    try_writing:
        dprint("trying to writev %d (%d bytes) to fd %d\n",
               conn->x.out.sg_count,
               ((conn->x.out.sg_count == 2 ? SG_LEN(&conn->x.out.sgp[1]) : 0)
                + SG_LEN(&conn->x.out.sgp[0])),
               conn->fd);
        TRACE_SENDTO_KDC_TCP_SEND(context, conn);
        nwritten = SOCKET_WRITEV(conn->fd, conn->x.out.sgp,
                                 conn->x.out.sg_count, tmp);
        if (nwritten < 0) {
            e = SOCKET_ERRNO;
            TRACE_SENDTO_KDC_TCP_ERROR_SEND(context, conn, e);
            dprint("failed: %m\n", e);
            goto kill_conn;
        }
        dprint("wrote %d bytes\n", nwritten);
        while (nwritten) {
            sg_buf *sgp = conn->x.out.sgp;
            if ((size_t) nwritten < SG_LEN(sgp)) {
                SG_ADVANCE(sgp, (size_t) nwritten);
                nwritten = 0;
            } else {
                nwritten -= SG_LEN(sgp);
                conn->x.out.sgp++;
                conn->x.out.sg_count--;
                if (conn->x.out.sg_count == 0 && nwritten != 0)
                    /* Wrote more than we wanted to?  */
                    abort();
            }
        }
        if (conn->x.out.sg_count == 0) {
            /* Done writing, switch to reading.  */
            /* Don't call shutdown at this point because
             * some implementations cannot deal with half-closed connections.*/
            FD_CLR(conn->fd, &selstate->wfds);
            /* Q: How do we detect failures to send the remaining data
               to the remote side, since we're in non-blocking mode?
               Will we always get errors on the reading side?  */
            dprint("switching fd %d to READING\n", conn->fd);
            conn->state = READING;
            conn->x.in.bufsizebytes_read = 0;
            conn->x.in.bufsize = 0;
            conn->x.in.buf = 0;
            conn->x.in.pos = 0;
            conn->x.in.n_left = 0;
        }
        return 0;

    case READING:
        if (ssflags & SSF_EXCEPTION) {
            if (conn->x.in.buf) {
                free(conn->x.in.buf);
                conn->x.in.buf = 0;
            }
            goto handle_exception;
        }

        if (conn->x.in.bufsizebytes_read == 4) {
            /* Reading data.  */
            dprint("reading %d bytes of data from fd %d\n",
                   (int) conn->x.in.n_left, conn->fd);
            nread = SOCKET_READ(conn->fd, conn->x.in.pos, conn->x.in.n_left);
            if (nread <= 0) {
                e = nread ? SOCKET_ERRNO : ECONNRESET;
                free(conn->x.in.buf);
                conn->x.in.buf = 0;
                TRACE_SENDTO_KDC_TCP_ERROR_RECV(context, conn, e);
                goto kill_conn;
            }
            conn->x.in.n_left -= nread;
            conn->x.in.pos += nread;
            if (conn->x.in.n_left <= 0) {
                /* We win!  */
                return 1;
            }
        } else {
            /* Reading length.  */
            nread = SOCKET_READ(conn->fd,
                                conn->x.in.bufsizebytes + conn->x.in.bufsizebytes_read,
                                4 - conn->x.in.bufsizebytes_read);
            if (nread < 0) {
                TRACE_SENDTO_KDC_TCP_ERROR_RECV_LEN(context, conn, e);
                e = SOCKET_ERRNO;
                goto kill_conn;
            }
            conn->x.in.bufsizebytes_read += nread;
            if (conn->x.in.bufsizebytes_read == 4) {
                unsigned long len = load_32_be (conn->x.in.bufsizebytes);
                dprint("received length on fd %d is %d\n", conn->fd, (int)len);
                /* Arbitrary 1M cap.  */
                if (len > 1 * 1024 * 1024) {
                    e = E2BIG;
                    goto kill_conn;
                }
                conn->x.in.bufsize = conn->x.in.n_left = len;
                conn->x.in.buf = conn->x.in.pos = malloc(len);
                dprint("allocated %d byte buffer at %p\n", (int) len,
                       conn->x.in.buf);
                if (conn->x.in.buf == 0) {
                    /* allocation failure */
                    e = ENOMEM;
                    goto kill_conn;
                }
            }
        }
        break;

    default:
        abort();
    }
    return 0;
}