X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Ftcpip.c;h=6400e7d841b36342a2eb3f68aa83279323517c58;hp=92b3100ef07797668a7cdef014d80a897e8ea406;hb=aaf5a12c13670c9d034ecf809448201e1ef5d8de;hpb=8dc67a9430644549801c18ec7e3a725e5a4ef782 diff --git a/src/tcpip.c b/src/tcpip.c index 92b3100..6400e7d 100644 --- a/src/tcpip.c +++ b/src/tcpip.c @@ -1,22 +1,49 @@ /* - * Copyright (c) 1995-2003, Index Data + * Copyright (C) 1995-2005, Index Data ApS * See the file LICENSE for details. * - * $Id: tcpip.c,v 1.2 2004-04-28 12:10:53 adam Exp $ + * $Id: tcpip.c,v 1.17 2005-07-19 12:40:52 mike Exp $ + */ +/** + * \file tcpip.c + * \brief Implements TCP/IP + SSL COMSTACK. */ #include #include #include +#include +#include +#include +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_TIME_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif #ifdef WIN32 +#include #else -#include +#include +#include +#include +#include +#endif + +#if HAVE_SYS_SOCKET_H +#include +#endif +#if HAVE_SYS_SELECT_H +#include +#endif +#if HAVE_SYS_WAIT_H +#include #endif -#include -#include -#include #if HAVE_OPENSSL_SSL_H #include #include @@ -24,14 +51,8 @@ #include #include -#include #include -#ifdef WIN32 -#else -#include -#endif - static int tcpip_close(COMSTACK h); static int tcpip_put(COMSTACK h, char *buf, int size); static int tcpip_get(COMSTACK h, char **buf, int *bufsize); @@ -40,8 +61,8 @@ static int tcpip_more(COMSTACK h); static int tcpip_rcvconnect(COMSTACK h); static int tcpip_bind(COMSTACK h, void *address, int mode); static int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, - int (*check_ip)(void *cd, const char *a, int len, int type), - void *cd); + int (*check_ip)(void *cd, const char *a, int len, int type), + void *cd); static int tcpip_set_blocking(COMSTACK p, int blocking); #if HAVE_OPENSSL_SSL_H @@ -76,9 +97,10 @@ typedef struct tcpip_state struct sockaddr_in addr; /* returned by cs_straddr */ char buf[128]; /* returned by cs_addrstr */ #if HAVE_OPENSSL_SSL_H - SSL_CTX *ctx; - SSL_CTX *ctx_alloc; + SSL_CTX *ctx; /* current CTX. */ + SSL_CTX *ctx_alloc; /* If =ctx it is owned by CS. If 0 it is not owned */ SSL *ssl; + char cert_fname[256]; #endif } tcpip_state; @@ -112,7 +134,7 @@ static int tcpip_init (void) COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp) { COMSTACK p; - tcpip_state *state; + tcpip_state *sp; int new_socket; #ifdef WIN32 unsigned long tru = 1; @@ -122,17 +144,17 @@ COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp) return 0; if (s < 0) { - if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) - return 0; - new_socket = 1; + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return 0; + new_socket = 1; } else - new_socket = 0; + new_socket = 0; if (!(p = (struct comstack *)xmalloc(sizeof(struct comstack)))) - return 0; - if (!(state = (struct tcpip_state *)(p->cprivate = + return 0; + if (!(sp = (struct tcpip_state *)(p->cprivate = xmalloc(sizeof(tcpip_state))))) - return 0; + return 0; if (!((p->blocking = blocking)&1)) { @@ -170,19 +192,21 @@ COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp) p->event = CS_NONE; p->cerrno = 0; p->stackerr = 0; + p->user = 0; #if HAVE_OPENSSL_SSL_H - state->ctx = state->ctx_alloc = 0; - state->ssl = 0; + sp->ctx = sp->ctx_alloc = 0; + sp->ssl = 0; + strcpy(sp->cert_fname, "yaz.pem"); #endif - state->altbuf = 0; - state->altsize = state->altlen = 0; - state->towrite = state->written = -1; + sp->altbuf = 0; + sp->altsize = sp->altlen = 0; + sp->towrite = sp->written = -1; if (protocol == PROTO_WAIS) - state->complete = completeWAIS; + sp->complete = completeWAIS; else - state->complete = cs_complete_auto; + sp->complete = cs_complete_auto; p->timeout = COMSTACK_DEFAULT_TIMEOUT; TRC(fprintf(stderr, "Created new TCPIP comstack\n")); @@ -194,33 +218,20 @@ COMSTACK tcpip_type(int s, int blocking, int protocol, void *vp) COMSTACK ssl_type(int s, int blocking, int protocol, void *vp) { - tcpip_state *state; + tcpip_state *sp; COMSTACK p; - yaz_log(LOG_LOG, "ssl_type begin"); p = tcpip_type (s, blocking, protocol, 0); if (!p) - return 0; + return 0; p->f_get = ssl_get; p->f_put = ssl_put; p->type = ssl_type; - state = (tcpip_state *) p->cprivate; - if (vp) - state->ctx = vp; - else - { - SSL_load_error_strings(); - SSLeay_add_all_algorithms(); - - state->ctx = state->ctx_alloc = SSL_CTX_new (SSLv23_method()); - if (!state->ctx) - { - tcpip_close(p); - return 0; - } - } + sp = (tcpip_state *) p->cprivate; + + sp->ctx = (SSL_CTX *) vp; /* may be NULL */ + /* note: we don't handle already opened socket in SSL mode - yet */ - yaz_log(LOG_LOG, "ssl_type end"); return p; } #endif @@ -251,7 +262,7 @@ int tcpip_strtoaddr_ex(const char *str, struct sockaddr_in *add, add->sin_addr.s_addr = INADDR_ANY; else if ((hp = gethostbyname(buf))) memcpy(&add->sin_addr.s_addr, *hp->h_addr_list, - sizeof(struct in_addr)); + sizeof(struct in_addr)); else if ((tmpadd = (unsigned) inet_addr(buf)) != 0) memcpy(&add->sin_addr.s_addr, &tmpadd, sizeof(struct in_addr)); else @@ -268,7 +279,7 @@ void *tcpip_straddr(COMSTACK h, const char *str) port = 80; if (!tcpip_strtoaddr_ex (str, &sp->addr, port)) - return 0; + return 0; return &sp->addr; } @@ -277,7 +288,7 @@ struct sockaddr_in *tcpip_strtoaddr(const char *str) static struct sockaddr_in add; if (!tcpip_strtoaddr_ex (str, &add, 210)) - return 0; + return 0; return &add; } @@ -286,7 +297,7 @@ int tcpip_more(COMSTACK h) tcpip_state *sp = (tcpip_state *)h->cprivate; return sp->altlen && (*sp->complete)((unsigned char *) sp->altbuf, - sp->altlen); + sp->altlen); } /* @@ -297,9 +308,6 @@ int tcpip_more(COMSTACK h) int tcpip_connect(COMSTACK h, void *address) { struct sockaddr_in *add = (struct sockaddr_in *)address; -#if HAVE_OPENSSL_SSL_H - tcpip_state *sp = (tcpip_state *)h->cprivate; -#endif int r; #ifdef __sun__ int recbuflen; @@ -310,7 +318,7 @@ int tcpip_connect(COMSTACK h, void *address) if (h->state != CS_ST_UNBND) { h->cerrno = CSOUTSTATE; - return -1; + return -1; } #ifdef __sun__ /* On Suns, you must set a bigger Receive Buffer BEFORE a call to connect @@ -323,7 +331,7 @@ int tcpip_connect(COMSTACK h, void *address) return -1; } TRC(fprintf( stderr, "Current Size of TCP Receive Buffer= %d\n", - recbuflen )); + recbuflen )); recbuflen *= 10; /* lets be optimistic */ if ( setsockopt(h->iofile, SOL_SOCKET, SO_RCVBUF, (void *)&recbuflen, rbufsize ) < 0 ) { @@ -336,7 +344,7 @@ int tcpip_connect(COMSTACK h, void *address) return -1; } TRC(fprintf( stderr, "New Size of TCP Receive Buffer = %d\n", - recbuflen )); + recbuflen )); #endif r = connect(h->iofile, (struct sockaddr *) add, sizeof(*add)); if (r < 0) @@ -382,35 +390,47 @@ int tcpip_rcvconnect(COMSTACK h) if (h->state != CS_ST_CONNECTING) { h->cerrno = CSOUTSTATE; - return -1; + return -1; } #if HAVE_OPENSSL_SSL_H + if (h->type == ssl_type && !sp->ctx) + { + SSL_load_error_strings(); + SSLeay_add_all_algorithms(); + + sp->ctx = sp->ctx_alloc = SSL_CTX_new (SSLv23_method()); + if (!sp->ctx) + { + h->cerrno = CSERRORSSL; + return -1; + } + } if (sp->ctx) { - int res; - - if (!sp->ssl) - { - sp->ssl = SSL_new (sp->ctx); - SSL_set_fd (sp->ssl, h->iofile); - } - res = SSL_connect (sp->ssl); - if (res <= 0) - { - int err = SSL_get_error(sp->ssl, res); - if (err == SSL_ERROR_WANT_READ) - { - h->io_pending = CS_WANT_READ; - return 1; - } - if (err == SSL_ERROR_WANT_WRITE) - { - h->io_pending = CS_WANT_WRITE; - return 1; - } - h->cerrno = CSERRORSSL; - return -1; - } + int res; + + if (!sp->ssl) + { + sp->ssl = SSL_new (sp->ctx); + SSL_set_fd (sp->ssl, h->iofile); + } + res = SSL_connect (sp->ssl); + if (res <= 0) + { + int err = SSL_get_error(sp->ssl, res); + if (err == SSL_ERROR_WANT_READ) + { + h->io_pending = CS_WANT_READ; + return 1; + } + if (err == SSL_ERROR_WANT_WRITE) + { + h->io_pending = CS_WANT_WRITE; + return 1; + } + h->cerrno = CSERRORSSL; + return -1; + } } #endif h->event = CS_DATA; @@ -453,44 +473,56 @@ static int tcpip_bind(COMSTACK h, void *address, int mode) #if HAVE_OPENSSL_SSL_H tcpip_state *sp = (tcpip_state *)h->cprivate; + if (h->type == ssl_type && !sp->ctx) + { + SSL_load_error_strings(); + SSLeay_add_all_algorithms(); + + sp->ctx = sp->ctx_alloc = SSL_CTX_new (SSLv23_method()); + if (!sp->ctx) + { + h->cerrno = CSERRORSSL; + return -1; + } + } if (sp->ctx) { - if (sp->ctx_alloc) - { - int res; - res = SSL_CTX_use_certificate_file (sp->ctx, CERTF, - SSL_FILETYPE_PEM); - if (res <= 0) - { - ERR_print_errors_fp(stderr); - exit (2); - } - res = SSL_CTX_use_PrivateKey_file (sp->ctx, KEYF, - SSL_FILETYPE_PEM); - if (res <= 0) - { - ERR_print_errors_fp(stderr); - exit (3); - } - res = SSL_CTX_check_private_key (sp->ctx); - if (res <= 0) - { - ERR_print_errors_fp(stderr); - exit(5); - } - } - TRC (fprintf (stderr, "ssl_bind\n")); + if (sp->ctx_alloc) + { + int res; + res = SSL_CTX_use_certificate_file (sp->ctx, sp->cert_fname, + SSL_FILETYPE_PEM); + if (res <= 0) + { + ERR_print_errors_fp(stderr); + exit (2); + } + res = SSL_CTX_use_PrivateKey_file (sp->ctx, sp->cert_fname, + SSL_FILETYPE_PEM); + if (res <= 0) + { + ERR_print_errors_fp(stderr); + exit (3); + } + res = SSL_CTX_check_private_key (sp->ctx); + if (res <= 0) + { + ERR_print_errors_fp(stderr); + exit(5); + } + } + TRC (fprintf (stderr, "ssl_bind\n")); } else { - TRC (fprintf (stderr, "tcpip_bind\n")); + TRC (fprintf (stderr, "tcpip_bind\n")); } #else TRC (fprintf (stderr, "tcpip_bind\n")); #endif #ifndef WIN32 if (setsockopt(h->iofile, SOL_SOCKET, SO_REUSEADDR, (char*) - &one, sizeof(one)) < 0) + &one, sizeof(one)) < 0) { h->cerrno = CSYSERR; return -1; @@ -502,7 +534,8 @@ static int tcpip_bind(COMSTACK h, void *address, int mode) h->cerrno = CSYSERR; return -1; } - if (mode == CS_SERVER && listen(h->iofile, 3) < 0) + /* Allow a maximum-sized backlog of waiting-to-connect clients */ + if (mode == CS_SERVER && listen(h->iofile, SOMAXCONN) < 0) { h->cerrno = CSYSERR; return -1; @@ -513,8 +546,8 @@ static int tcpip_bind(COMSTACK h, void *address, int mode) } int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, - int (*check_ip)(void *cd, const char *a, int len, int t), - void *cd) + int (*check_ip)(void *cd, const char *a, int len, int t), + void *cd) { struct sockaddr_in addr; YAZ_SOCKLEN_T len = sizeof(addr); @@ -528,21 +561,21 @@ int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, h->newfd = accept(h->iofile, (struct sockaddr*)&addr, &len); if (h->newfd < 0) { - if ( + if ( #ifdef WIN32 - WSAGetLastError() == WSAEWOULDBLOCK + WSAGetLastError() == WSAEWOULDBLOCK #else - yaz_errno() == EWOULDBLOCK + yaz_errno() == EWOULDBLOCK #ifdef EAGAIN #if EAGAIN != EWOULDBLOCK || yaz_errno() == EAGAIN #endif #endif #endif - ) - h->cerrno = CSNODATA; - else - h->cerrno = CSYSERR; + ) + h->cerrno = CSNODATA; + else + h->cerrno = CSYSERR; return -1; } if (addrlen && (size_t) (*addrlen) >= sizeof(struct sockaddr_in)) @@ -552,14 +585,14 @@ int tcpip_listen(COMSTACK h, char *raddr, int *addrlen, if (check_ip && (*check_ip)(cd, (const char *) &addr, sizeof(addr), AF_INET)) { - h->cerrno = CSDENY; + h->cerrno = CSDENY; #ifdef WIN32 closesocket(h->newfd); #else close(h->newfd); #endif - h->newfd = -1; - return -1; + h->newfd = -1; + return -1; } h->state = CS_ST_INCON; tcpip_setsockopt (h->newfd); @@ -577,102 +610,102 @@ COMSTACK tcpip_accept(COMSTACK h) TRC(fprintf(stderr, "tcpip_accept\n")); if (h->state == CS_ST_INCON) { - if (!(cnew = (COMSTACK)xmalloc(sizeof(*cnew)))) - { - h->cerrno = CSYSERR; + if (!(cnew = (COMSTACK)xmalloc(sizeof(*cnew)))) + { + h->cerrno = CSYSERR; #ifdef WIN32 - closesocket(h->newfd); + closesocket(h->newfd); #else - close(h->newfd); + close(h->newfd); #endif - h->newfd = -1; - return 0; - } - memcpy(cnew, h, sizeof(*h)); - cnew->iofile = h->newfd; - cnew->io_pending = 0; - if (!(state = (tcpip_state *) - (cnew->cprivate = xmalloc(sizeof(tcpip_state))))) - { - h->cerrno = CSYSERR; - if (h->newfd != -1) - { + h->newfd = -1; + return 0; + } + memcpy(cnew, h, sizeof(*h)); + cnew->iofile = h->newfd; + cnew->io_pending = 0; + if (!(state = (tcpip_state *) + (cnew->cprivate = xmalloc(sizeof(tcpip_state))))) + { + h->cerrno = CSYSERR; + if (h->newfd != -1) + { #ifdef WIN32 - closesocket(h->newfd); + closesocket(h->newfd); #else - close(h->newfd); + close(h->newfd); #endif - h->newfd = -1; - } - return 0; - } - if (!(cnew->blocking&1) && + h->newfd = -1; + } + return 0; + } + if (!(cnew->blocking&1) && #ifdef WIN32 - (ioctlsocket(cnew->iofile, FIONBIO, &tru) < 0) + (ioctlsocket(cnew->iofile, FIONBIO, &tru) < 0) #else - (fcntl(cnew->iofile, F_SETFL, O_NONBLOCK) < 0) + (fcntl(cnew->iofile, F_SETFL, O_NONBLOCK) < 0) #endif - ) - { - h->cerrno = CSYSERR; - if (h->newfd != -1) - { + ) + { + h->cerrno = CSYSERR; + if (h->newfd != -1) + { #ifdef WIN32 - closesocket(h->newfd); + closesocket(h->newfd); #else - close(h->newfd); + close(h->newfd); #endif - h->newfd = -1; - } - xfree (cnew); - xfree (state); - return 0; - } - h->newfd = -1; - state->altbuf = 0; - state->altsize = state->altlen = 0; - state->towrite = state->written = -1; - state->complete = st->complete; - cnew->state = CS_ST_ACCEPT; - h->state = CS_ST_IDLE; - + h->newfd = -1; + } + xfree (cnew); + xfree (state); + return 0; + } + h->newfd = -1; + state->altbuf = 0; + state->altsize = state->altlen = 0; + state->towrite = state->written = -1; + state->complete = st->complete; + cnew->state = CS_ST_ACCEPT; + h->state = CS_ST_IDLE; + #if HAVE_OPENSSL_SSL_H - state->ctx = st->ctx; - state->ctx_alloc = 0; - state->ssl = st->ssl; - if (state->ctx) - { - state->ssl = SSL_new (state->ctx); - SSL_set_fd (state->ssl, cnew->iofile); - } + state->ctx = st->ctx; + state->ctx_alloc = 0; + state->ssl = st->ssl; + if (state->ctx) + { + state->ssl = SSL_new (state->ctx); + SSL_set_fd (state->ssl, cnew->iofile); + } #endif - h = cnew; + h = cnew; } if (h->state == CS_ST_ACCEPT) { #if HAVE_OPENSSL_SSL_H - tcpip_state *state = (tcpip_state *)h->cprivate; - if (state->ctx) - { - int res = SSL_accept (state->ssl); - TRC(fprintf(stderr, "SSL_accept\n")); - if (res <= 0) - { - int err = SSL_get_error(state->ssl, res); - if (err == SSL_ERROR_WANT_READ) - { - h->io_pending = CS_WANT_READ; - return h; - } - if (err == SSL_ERROR_WANT_WRITE) - { - h->io_pending = CS_WANT_WRITE; - return h; - } - cs_close (h); - return 0; - } - } + tcpip_state *state = (tcpip_state *)h->cprivate; + if (state->ctx) + { + int res = SSL_accept (state->ssl); + TRC(fprintf(stderr, "SSL_accept\n")); + if (res <= 0) + { + int err = SSL_get_error(state->ssl, res); + if (err == SSL_ERROR_WANT_READ) + { + h->io_pending = CS_WANT_READ; + return h; + } + if (err == SSL_ERROR_WANT_WRITE) + { + h->io_pending = CS_WANT_WRITE; + return h; + } + cs_close (h); + return 0; + } + } #endif } else @@ -725,52 +758,52 @@ int tcpip_get(COMSTACK h, char **buf, int *bufsize) if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2))) return -1; #ifdef __sun__ - yaz_set_errno( 0 ); - /* unfortunatly, sun sometimes forgets to set errno in recv - when EWOULDBLOCK etc. would be required (res = -1) */ + yaz_set_errno( 0 ); + /* unfortunatly, sun sometimes forgets to set errno in recv + when EWOULDBLOCK etc. would be required (res = -1) */ #endif - res = recv(h->iofile, *buf + hasread, CS_TCPIP_BUFCHUNK, 0); - TRC(fprintf(stderr, " recv res=%d, hasread=%d\n", res, hasread)); - if (res < 0) - { - TRC(fprintf(stderr, " recv errno=%d, (%s)\n", yaz_errno(), - strerror(yaz_errno()))); + res = recv(h->iofile, *buf + hasread, CS_TCPIP_BUFCHUNK, 0); + TRC(fprintf(stderr, " recv res=%d, hasread=%d\n", res, hasread)); + if (res < 0) + { + TRC(fprintf(stderr, " recv errno=%d, (%s)\n", yaz_errno(), + strerror(yaz_errno()))); #ifdef WIN32 - if (WSAGetLastError() == WSAEWOULDBLOCK) - { - h->io_pending = CS_WANT_READ; - break; - } - else - return -1; + if (WSAGetLastError() == WSAEWOULDBLOCK) + { + h->io_pending = CS_WANT_READ; + break; + } + else + return -1; #else - if (yaz_errno() == EWOULDBLOCK + if (yaz_errno() == EWOULDBLOCK #ifdef EAGAIN #if EAGAIN != EWOULDBLOCK || yaz_errno() == EAGAIN #endif #endif - || yaz_errno() == EINPROGRESS + || yaz_errno() == EINPROGRESS #ifdef __sun__ - || yaz_errno() == ENOENT /* Sun's sometimes set errno to this */ + || yaz_errno() == ENOENT /* Sun's sometimes set errno to this */ #endif - ) - { - h->io_pending = CS_WANT_READ; - break; - } - else if (yaz_errno() == 0) - continue; - else - return -1; + ) + { + h->io_pending = CS_WANT_READ; + break; + } + else if (yaz_errno() == 0) + continue; + else + return -1; #endif - } - else if (!res) - return 0; + } + else if (!res) + return hasread; hasread += res; } TRC (fprintf (stderr, " Out of read loop with hasread=%d, berlen=%d\n", - hasread, berlen)); + hasread, berlen)); /* move surplus buffer (or everything if we didn't get a BER rec.) */ if (hasread > berlen) { @@ -832,27 +865,27 @@ int ssl_get(COMSTACK h, char **buf, int *bufsize) else if (*bufsize - hasread < CS_TCPIP_BUFCHUNK) if (!(*buf =(char *)xrealloc(*buf, *bufsize *= 2))) return -1; - res = SSL_read (sp->ssl, *buf + hasread, CS_TCPIP_BUFCHUNK); - TRC(fprintf(stderr, " SSL_read res=%d, hasread=%d\n", res, hasread)); - if (res <= 0) - { - int ssl_err = SSL_get_error(sp->ssl, res); - if (ssl_err == SSL_ERROR_WANT_READ) - { - h->io_pending = CS_WANT_READ; - break; - } - if (ssl_err == SSL_ERROR_WANT_WRITE) - { - h->io_pending = CS_WANT_WRITE; - break; - } - if (res == 0) - return 0; - h->cerrno = CSERRORSSL; - return -1; - } - hasread += res; + res = SSL_read (sp->ssl, *buf + hasread, CS_TCPIP_BUFCHUNK); + TRC(fprintf(stderr, " SSL_read res=%d, hasread=%d\n", res, hasread)); + if (res <= 0) + { + int ssl_err = SSL_get_error(sp->ssl, res); + if (ssl_err == SSL_ERROR_WANT_READ) + { + h->io_pending = CS_WANT_READ; + break; + } + if (ssl_err == SSL_ERROR_WANT_WRITE) + { + h->io_pending = CS_WANT_WRITE; + break; + } + if (res == 0) + return 0; + h->cerrno = CSERRORSSL; + return -1; + } + hasread += res; } TRC (fprintf (stderr, " Out of read loop with hasread=%d, berlen=%d\n", hasread, berlen)); @@ -905,21 +938,21 @@ int tcpip_put(COMSTACK h, char *buf, int size) } while (state->towrite > state->written) { - if ((res = - send(h->iofile, buf + state->written, size - - state->written, + if ((res = + send(h->iofile, buf + state->written, size - + state->written, #ifdef MSG_NOSIGNAL - MSG_NOSIGNAL + MSG_NOSIGNAL #else - 0 + 0 #endif - )) < 0) - { - if ( + )) < 0) + { + if ( #ifdef WIN32 - WSAGetLastError() == WSAEWOULDBLOCK + WSAGetLastError() == WSAEWOULDBLOCK #else - yaz_errno() == EWOULDBLOCK + yaz_errno() == EWOULDBLOCK #ifdef EAGAIN #if EAGAIN != EWOULDBLOCK || yaz_errno() == EAGAIN @@ -928,20 +961,20 @@ int tcpip_put(COMSTACK h, char *buf, int size) #ifdef __sun__ || yaz_errno() == ENOENT /* Sun's sometimes set errno to this value! */ #endif - || yaz_errno() == EINPROGRESS + || yaz_errno() == EINPROGRESS #endif - ) - { - TRC(fprintf(stderr, " Flow control stop\n")); - h->io_pending = CS_WANT_WRITE; - return 1; - } - h->cerrno = CSYSERR; - return -1; - } - state->written += res; - TRC(fprintf(stderr, " Wrote %d, written=%d, nbytes=%d\n", - res, state->written, size)); + ) + { + TRC(fprintf(stderr, " Flow control stop\n")); + h->io_pending = CS_WANT_WRITE; + return 1; + } + h->cerrno = CSYSERR; + return -1; + } + state->written += res; + TRC(fprintf(stderr, " Wrote %d, written=%d, nbytes=%d\n", + res, state->written, size)); } state->towrite = state->written = -1; TRC(fprintf(stderr, " Ok\n")); @@ -975,27 +1008,27 @@ int ssl_put(COMSTACK h, char *buf, int size) } while (state->towrite > state->written) { - res = SSL_write (state->ssl, buf + state->written, - size - state->written); - if (res <= 0) - { - int ssl_err = SSL_get_error(state->ssl, res); - if (ssl_err == SSL_ERROR_WANT_READ) - { - h->io_pending = CS_WANT_READ; - return 1; - } - if (ssl_err == SSL_ERROR_WANT_WRITE) - { - h->io_pending = CS_WANT_WRITE; - return 1; - } - h->cerrno = CSERRORSSL; - return -1; - } - state->written += res; - TRC(fprintf(stderr, " Wrote %d, written=%d, nbytes=%d\n", - res, state->written, size)); + res = SSL_write (state->ssl, buf + state->written, + size - state->written); + if (res <= 0) + { + int ssl_err = SSL_get_error(state->ssl, res); + if (ssl_err == SSL_ERROR_WANT_READ) + { + h->io_pending = CS_WANT_READ; + return 1; + } + if (ssl_err == SSL_ERROR_WANT_WRITE) + { + h->io_pending = CS_WANT_WRITE; + return 1; + } + h->cerrno = CSERRORSSL; + return -1; + } + state->written += res; + TRC(fprintf(stderr, " Wrote %d, written=%d, nbytes=%d\n", + res, state->written, size)); } state->towrite = state->written = -1; TRC(fprintf(stderr, " Ok\n")); @@ -1011,10 +1044,10 @@ int tcpip_close(COMSTACK h) if (h->iofile != -1) { #if HAVE_OPENSSL_SSL_H - if (sp->ssl) - { - SSL_shutdown (sp->ssl); - } + if (sp->ssl) + { + SSL_shutdown (sp->ssl); + } #endif #ifdef WIN32 closesocket(h->iofile); @@ -1027,12 +1060,12 @@ int tcpip_close(COMSTACK h) #if HAVE_OPENSSL_SSL_H if (sp->ssl) { - TRC (fprintf(stderr, "SSL_free\n")); - SSL_free (sp->ssl); + TRC (fprintf(stderr, "SSL_free\n")); + SSL_free (sp->ssl); } sp->ssl = 0; if (sp->ctx_alloc) - SSL_CTX_free (sp->ctx_alloc); + SSL_CTX_free (sp->ctx_alloc); #endif xfree(sp); xfree(h); @@ -1050,16 +1083,16 @@ char *tcpip_addrstr(COMSTACK h) len = sizeof(addr); if (getpeername(h->iofile, (struct sockaddr*) &addr, &len) < 0) { - h->cerrno = CSYSERR; - return 0; + h->cerrno = CSYSERR; + return 0; } if (!(h->blocking&2)) { if ((host = gethostbyaddr((char*)&addr.sin_addr, sizeof(addr.sin_addr), - AF_INET))) - r = (char*) host->h_name; + AF_INET))) + r = (char*) host->h_name; } if (!r) - r = inet_ntoa(addr.sin_addr); + r = inet_ntoa(addr.sin_addr); if (h->protocol == PROTO_HTTP) sprintf(buf, "http:%s", r); else @@ -1081,36 +1114,105 @@ int static tcpip_set_blocking(COMSTACK p, int blocking) unsigned long flag; if (p->blocking == blocking) - return 1; + return 1; #ifdef WIN32 flag = 1; if (ioctlsocket(p->iofile, FIONBIO, &flag) < 0) - return 0; + return 0; #else flag = fcntl(p->iofile, F_GETFL, 0); if(!(blocking&1)) - flag = flag & ~O_NONBLOCK; + flag = flag & ~O_NONBLOCK; else flag = flag | O_NONBLOCK; if (fcntl(p->iofile, F_SETFL, flag) < 0) - return 0; + return 0; #endif p->blocking = blocking; return 1; } #if HAVE_OPENSSL_SSL_H +int cs_set_ssl_ctx(COMSTACK cs, void *ctx) +{ + struct tcpip_state *sp; + if (!cs || cs->type != ssl_type) + return 0; + sp = (struct tcpip_state *) cs->cprivate; + if (sp->ctx_alloc) + return 0; + sp->ctx = (SSL_CTX *) ctx; + return 1; +} + void *cs_get_ssl(COMSTACK cs) { - struct tcpip_state *state; + struct tcpip_state *sp; + if (!cs || cs->type != ssl_type) + return 0; + sp = (struct tcpip_state *) cs->cprivate; + return sp->ssl; +} + +int cs_set_ssl_certificate_file(COMSTACK cs, const char *fname) +{ + struct tcpip_state *sp; if (!cs || cs->type != ssl_type) return 0; - state = (struct tcpip_state *) cs->cprivate; - return state->ssl; + sp = (struct tcpip_state *) cs->cprivate; + strncpy(sp->cert_fname, fname, sizeof(sp->cert_fname)-1); + sp->cert_fname[sizeof(sp->cert_fname)-1] = '\0'; + return 1; +} + +int cs_get_peer_certificate_x509(COMSTACK cs, char **buf, int *len) +{ + SSL *ssl = (SSL *) cs_get_ssl(cs); + if (ssl) + { + X509 *server_cert = SSL_get_peer_certificate (ssl); + if (server_cert) + { + BIO *bio = BIO_new(BIO_s_mem()); + char *pem_buf; + /* get PEM buffer in memory */ + PEM_write_bio_X509(bio, server_cert); + *len = BIO_get_mem_data(bio, &pem_buf); + *buf = (char *) xmalloc(*len); + memcpy(*buf, pem_buf, *len); + BIO_free(bio); + return 1; + } + } + return 0; } #else +int cs_set_ssl_ctx(COMSTACK cs, void *ctx) +{ + return 0; +} + void *cs_get_ssl(COMSTACK cs) { return 0; } + +int cs_get_peer_certificate_x509(COMSTACK cs, char **buf, int *len) +{ + return 0; +} + +int cs_set_ssl_certificate_file(COMSTACK cs, const char *fname) +{ + return 0; +} #endif + +/* + * Local variables: + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ +