/* Initiate an SSL handshake on this stream and encrypt all subsequent data */ int stream_enable_ssl(PTSTREAM *pts) { #ifdef USE_SSL SSL_METHOD *meth; SSL *ssl; SSL_CTX *ctx; /* Initialise the connection */ SSLeay_add_ssl_algorithms(); meth = TLSv1_client_method(); SSL_load_error_strings(); ctx = SSL_CTX_new (meth); ssl = SSL_new (ctx); SSL_set_rfd (ssl, stream_get_incoming_fd(pts)); SSL_set_wfd (ssl, stream_get_outgoing_fd(pts)); SSL_connect (ssl); /* Store ssl and ctx parameters */ pts->ssl = ssl; pts->ctx = ctx; #else message("Warning: stream_open(): SSL stream requested but no SSL support available; using unencrypted connection"); #endif /* USE_SSL */ return 1; }
int sycSSL_set_wfd(SSL *ssl, int fd) { int result; Debug2("SSL_set_wfd(%p, %d)", ssl, fd); result = SSL_set_wfd(ssl, fd); Debug1("SSL_set_wfd() -> %d", result); return result; }
/* Initiate an SSL handshake on this stream and encrypt all subsequent data */ int stream_enable_ssl(PTSTREAM *pts) { #ifdef USE_SSL SSL *ssl; SSL_CTX *ctx; int ret; /* Initialise the connection */ SSLeay_add_ssl_algorithms(); SSL_load_error_strings(); ctx = SSL_CTX_new (SSLv3_client_method()); ssl = SSL_new (ctx); if (args_info.verbose_flag) { message("Set SNI hostname to %s\n", args_info.proxyhost_arg); } ret = SSL_set_tlsext_host_name(ssl, args_info.proxyhost_arg); if (!ret) { message("TLS SNI error, giving up: SSL_set_tlsext_host_name failed\n"); exit(1); } SSL_set_rfd (ssl, stream_get_incoming_fd(pts)); SSL_set_wfd (ssl, stream_get_outgoing_fd(pts)); SSL_connect (ssl); /* Store ssl and ctx parameters */ pts->ssl = ssl; pts->ctx = ctx; #else message("Warning: stream_open(): SSL stream requested but no SSL support available; using unencrypted connection"); #endif /* USE_SSL */ return 1; }
SSLConnection::SSLConnection(SSL *ssl, int rfd, int wfd) : m_ssl(ssl) , m_iStatus(DISCONNECTED) , m_iWant(0) { SSL_set_rfd(m_ssl, rfd); SSL_set_wfd(m_ssl, wfd); }
int SSLConnection::setfd(int rfd, int wfd) { m_iWant = 0; int ret = SSL_set_rfd(m_ssl, rfd); if (!ret) return ret == 0; m_iStatus = DISCONNECTED; return SSL_set_wfd(m_ssl, wfd) == 0; }
int tls_accept_fds(struct tls *ctx, struct tls **cctx, int fd_read, int fd_write) { struct tls *conn_ctx = *cctx; int ret, err; if ((ctx->flags & TLS_SERVER) == 0) { tls_set_error(ctx, "not a server context"); goto err; } if (conn_ctx == NULL) { if ((conn_ctx = tls_server_conn(ctx)) == NULL) { tls_set_error(ctx, "connection context failure"); goto err; } *cctx = conn_ctx; if ((conn_ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { tls_set_error(ctx, "ssl failure"); goto err; } if (SSL_set_rfd(conn_ctx->ssl_conn, fd_read) != 1 || SSL_set_wfd(conn_ctx->ssl_conn, fd_write) != 1) { tls_set_error(ctx, "ssl set fd failure"); goto err; } SSL_set_app_data(conn_ctx->ssl_conn, conn_ctx); } if ((ret = SSL_accept(conn_ctx->ssl_conn)) != 1) { err = tls_ssl_error(ctx, conn_ctx->ssl_conn, ret, "accept"); if (err == TLS_READ_AGAIN || err == TLS_WRITE_AGAIN) { return (err); } goto err; } return (0); err: return (-1); }
/* Initiate an SSL handshake on this stream and encrypt all subsequent data */ int stream_enable_ssl(PTSTREAM *pts) { #ifdef USE_SSL const SSL_METHOD *meth; SSL *ssl; SSL_CTX *ctx; long res = 1; /* Initialise the connection */ SSLeay_add_ssl_algorithms(); if (args_info.enforcetls1_flag) { meth = TLSv1_client_method(); } else { meth = SSLv23_client_method(); } SSL_load_error_strings(); ctx = SSL_CTX_new (meth); ssl = SSL_new (ctx); SSL_set_rfd (ssl, stream_get_incoming_fd(pts)); SSL_set_wfd (ssl, stream_get_outgoing_fd(pts)); /* SNI support */ if ( args_info.verbose_flag ) { message( "Set SNI hostname to %s\n", args_info.proxyhost_arg ); } res = SSL_set_tlsext_host_name(ssl,args_info.proxyhost_arg); if (res < 0) { message( "TLS SNI error, giving up: SSL_set_tlsext_host_name returned error message:\n %u\n", res ); exit( 1 ); } SSL_connect (ssl); /* Store ssl and ctx parameters */ pts->ssl = ssl; pts->ctx = ctx; #else message("Warning: stream_open(): SSL stream requested but no SSL support available; using unencrypted connection"); #endif /* USE_SSL */ return 1; }
int tls_accept_fds(struct tls *ctx, struct tls **cctx, int fd_read, int fd_write) { struct tls *conn_ctx = NULL; if ((ctx->flags & TLS_SERVER) == 0) { tls_set_errorx(ctx, "not a server context"); goto err; } if ((conn_ctx = tls_server_conn(ctx)) == NULL) { tls_set_errorx(ctx, "connection context failure"); goto err; } if ((conn_ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { tls_set_errorx(ctx, "ssl failure"); goto err; } if (SSL_set_app_data(conn_ctx->ssl_conn, conn_ctx) != 1) { tls_set_errorx(ctx, "ssl application data failure"); goto err; } if (SSL_set_rfd(conn_ctx->ssl_conn, fd_read) != 1 || SSL_set_wfd(conn_ctx->ssl_conn, fd_write) != 1) { tls_set_errorx(ctx, "ssl file descriptor failure"); goto err; } *cctx = conn_ctx; return (0); err: tls_free(conn_ctx); *cctx = NULL; return (-1); }
int sio_set_tlsserver_ssl (struct siobuf *sio, SSL *ssl) { int ret; assert (sio != NULL); if (ssl != NULL) { sio->ssl = ssl; SSL_set_rfd (sio->ssl, sio->sdr); SSL_set_wfd (sio->ssl, sio->sdw); while ((ret = SSL_accept (sio->ssl)) <= 0) if (sio_sslpoll (sio, ret) <= 0) { SSL_free (sio->ssl); sio->ssl = NULL; break; } sio_set_timeout (sio, sio->milliseconds); } return sio->ssl != NULL; }
int tls_connect_fds(struct tls *ctx, int fd_read, int fd_write, const char *servername) { int rv = -1; if (fd_read < 0 || fd_write < 0) { tls_set_errorx(ctx, "invalid file descriptors"); goto err; } if (tls_connect_common(ctx, servername) != 0) goto err; if (SSL_set_rfd(ctx->ssl_conn, fd_read) != 1 || SSL_set_wfd(ctx->ssl_conn, fd_write) != 1) { tls_set_errorx(ctx, "ssl file descriptor failure"); goto err; } rv = 0; err: return (rv); }
static void init_local(CLI *c) { SOCKADDR_UNION addr; socklen_t addrlen; addrlen=sizeof addr; if(getpeername(c->local_rfd.fd, &addr.sa, &addrlen)<0) { strcpy(c->accepted_address, "NOT A SOCKET"); c->local_rfd.is_socket=0; c->local_wfd.is_socket=0; /* TODO: It's not always true */ #ifdef USE_WIN32 if(get_last_socket_error()!=ENOTSOCK) { #else if(c->opt->option.transparent_src || get_last_socket_error()!=ENOTSOCK) { #endif sockerror("getpeerbyname"); longjmp(c->err, 1); } /* ignore ENOTSOCK error so 'local' doesn't have to be a socket */ } else { /* success */ /* copy addr to c->peer_addr */ memcpy(&c->peer_addr.addr[0], &addr, sizeof addr); c->peer_addr.num=1; s_ntop(c->accepted_address, &c->peer_addr.addr[0]); c->local_rfd.is_socket=1; c->local_wfd.is_socket=1; /* TODO: It's not always true */ /* it's a socket: lets setup options */ if(set_socket_options(c->local_rfd.fd, 1)<0) longjmp(c->err, 1); #ifdef USE_LIBWRAP libwrap_auth(c); #endif /* USE_LIBWRAP */ auth_user(c); s_log(LOG_NOTICE, "Service %s accepted connection from %s", c->opt->servname, c->accepted_address); } } static void init_remote(CLI *c) { /* create connection to host/service */ if(c->opt->source_addr.num) memcpy(&c->bind_addr, &c->opt->source_addr, sizeof(SOCKADDR_LIST)); #ifndef USE_WIN32 else if(c->opt->option.transparent_src) memcpy(&c->bind_addr, &c->peer_addr, sizeof(SOCKADDR_LIST)); #endif else { c->bind_addr.num=0; /* don't bind connecting socket */ } /* setup c->remote_fd, now */ if(c->opt->option.remote) c->remote_fd.fd=connect_remote(c); #ifdef SO_ORIGINAL_DST else if(c->opt->option.transparent_dst) c->remote_fd.fd=connect_transparent(c); #endif /* SO_ORIGINAL_DST */ else /* NOT in remote mode */ c->remote_fd.fd=connect_local(c); c->remote_fd.is_socket=1; /* always! */ s_log(LOG_DEBUG, "Remote FD=%d initialized", c->remote_fd.fd); if(set_socket_options(c->remote_fd.fd, 2)<0) longjmp(c->err, 1); } static void init_ssl(CLI *c) { int i, err; SSL_SESSION *old_session; if(!(c->ssl=SSL_new(c->opt->ctx))) { sslerror("SSL_new"); longjmp(c->err, 1); } SSL_set_ex_data(c->ssl, cli_index, c); /* for callbacks */ SSL_set_session_id_context(c->ssl, (unsigned char *)sid_ctx, strlen(sid_ctx)); if(c->opt->option.client) { #ifndef OPENSSL_NO_TLSEXT if(c->opt->host_name) { s_log(LOG_DEBUG, "SNI: host name: %s", c->opt->host_name); if(!SSL_set_tlsext_host_name(c->ssl, c->opt->host_name)) { sslerror("SSL_set_tlsext_host_name"); longjmp(c->err, 1); } } #endif if(c->opt->session) { enter_critical_section(CRIT_SESSION); SSL_set_session(c->ssl, c->opt->session); leave_critical_section(CRIT_SESSION); } SSL_set_fd(c->ssl, c->remote_fd.fd); SSL_set_connect_state(c->ssl); } else { if(c->local_rfd.fd==c->local_wfd.fd) SSL_set_fd(c->ssl, c->local_rfd.fd); else { /* does it make sence to have SSL on STDIN/STDOUT? */ SSL_set_rfd(c->ssl, c->local_rfd.fd); SSL_set_wfd(c->ssl, c->local_wfd.fd); } SSL_set_accept_state(c->ssl); } /* setup some values for transfer() function */ if(c->opt->option.client) { c->sock_rfd=&(c->local_rfd); c->sock_wfd=&(c->local_wfd); c->ssl_rfd=c->ssl_wfd=&(c->remote_fd); } else { c->sock_rfd=c->sock_wfd=&(c->remote_fd); c->ssl_rfd=&(c->local_rfd); c->ssl_wfd=&(c->local_wfd); } while(1) { #if OPENSSL_VERSION_NUMBER<0x1000002f /* this critical section is a crude workaround for CVE-2010-3864 * * see http://www.securityfocus.com/bid/44884 for details * * NOTE: this critical section also covers callbacks (e.g. OCSP) */ enter_critical_section(CRIT_SSL); #endif /* OpenSSL version < 1.0.0b */ if(c->opt->option.client) i=SSL_connect(c->ssl); else i=SSL_accept(c->ssl); #if OPENSSL_VERSION_NUMBER<0x1000002f leave_critical_section(CRIT_SSL); #endif /* OpenSSL version < 1.0.0b */ err=SSL_get_error(c->ssl, i); if(err==SSL_ERROR_NONE) break; /* ok -> done */ if(err==SSL_ERROR_WANT_READ || err==SSL_ERROR_WANT_WRITE) { s_poll_init(&c->fds); s_poll_add(&c->fds, c->ssl_rfd->fd, err==SSL_ERROR_WANT_READ, err==SSL_ERROR_WANT_WRITE); switch(s_poll_wait(&c->fds, c->opt->timeout_busy, 0)) { case -1: sockerror("init_ssl: s_poll_wait"); longjmp(c->err, 1); case 0: s_log(LOG_INFO, "init_ssl: s_poll_wait:" " TIMEOUTbusy exceeded: sending reset"); longjmp(c->err, 1); case 1: break; /* OK */ default: s_log(LOG_ERR, "init_ssl: s_poll_wait: unknown result"); longjmp(c->err, 1); } continue; /* ok -> retry */ } if(err==SSL_ERROR_SYSCALL) { switch(get_last_socket_error()) { case EINTR: case EAGAIN: continue; } } if(c->opt->option.client) sslerror("SSL_connect"); else sslerror("SSL_accept"); longjmp(c->err, 1); } if(SSL_session_reused(c->ssl)) { s_log(LOG_INFO, "SSL %s: previous session reused", c->opt->option.client ? "connected" : "accepted"); } else { /* a new session was negotiated */ if(c->opt->option.client) { s_log(LOG_INFO, "SSL connected: new session negotiated"); enter_critical_section(CRIT_SESSION); old_session=c->opt->session; c->opt->session=SSL_get1_session(c->ssl); /* store it */ if(old_session) SSL_SESSION_free(old_session); /* release the old one */ leave_critical_section(CRIT_SESSION); } else s_log(LOG_INFO, "SSL accepted: new session negotiated"); print_cipher(c); } }
/* run as if invoked by inetd */ int main (int argc, char *argv[]) { int c; int filetype = SSL_FILETYPE_PEM; char *peer = NULL; char *ptr; char buf[4096]; enum optype op = NOOP; char *setkey = NULL; SSL_CTX *ctx; X509 *client_cert; int r; pool *p = NULL; security_context *context = NULL; int max_wait = 0; while ((c = getopt (argc, argv, "apc:k:C:D:f:")) != -1) { switch (c) { case 'a': filetype = SSL_FILETYPE_ASN1; break; case 'p': filetype = SSL_FILETYPE_PEM; break; case 'c': /* 'optarg' is the certificate file */ certfile = strdup (optarg); break; case 'k': /* 'optarg' is the key file */ keyfile = strdup (optarg); break; case 'C': /* 'optarg' is the CA we accept */ cafile = strdup (optarg); break; case 'D': /* 'optarg' is a directory of CAs */ cadir = strdup (optarg); break; case 'f': configfile = strdup (optarg); break; case '?': default: usage (); break; } } libpbc_config_init (p, configfile, "keyserver"); pbc_log_init_syslog (p, "keyserver"); libpbc_pubcookie_init (p, &context); debug = libpbc_config_getint (p, "logging_level", 0); if (!keyfile) keyfile = libpbc_config_getstring (p, "ssl_key_file", "server.pem"); if (!certfile) certfile = libpbc_config_getstring (p, "ssl_cert_file", "server.pem"); if (!cafile) cafile = libpbc_config_getstring (p, "ssl_ca_file", NULL); if (!cadir) cadir = libpbc_config_getstring (p, "ssl_ca_path", NULL); gcfile = libpbc_config_getstring (p, "granting_cert_file", NULL); max_wait = libpbc_config_getint (p, "keyserver_max_wait_time", 0); if (max_wait < 0) max_wait = 0; /* xxx log connection information */ /* initalize the PRNG as best we can if we have to */ if (RAND_status () == 0) { pbc_time_t t = pbc_time (NULL); pid_t pid = getpid (); char buf[1024]; char *cmd[3] = { "/bin/ps", "-ef", NULL }; RAND_seed ((unsigned char *) &t, sizeof (t)); RAND_seed ((unsigned char *) &pid, sizeof (pid)); capture_cmd_output (p, cmd, buf, sizeof (buf)); RAND_seed ((unsigned char *) buf, sizeof (buf)); } /* Load SSL Error Strings */ SSL_load_error_strings (); /* initialize the OpenSSL connection */ SSL_library_init (); ctx = SSL_CTX_new (TLSv1_server_method ()); /* setup the correct certificate */ if (!SSL_CTX_use_certificate_file (ctx, certfile, filetype)) { logerrstr ("SSL_CTX_use_certificate_file"); exit (1); } if (!SSL_CTX_use_PrivateKey_file (ctx, keyfile, filetype)) { logerrstr ("SSL_CTX_use_PrivateKey_file"); exit (1); } if (!SSL_CTX_load_verify_locations (ctx, cafile, cadir)) { logerrstr ("SSL_CTX_load_verify_locations"); exit (1); } SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, verify_callback); ssl = SSL_new (ctx); /* negotiate SSL */ SSL_set_rfd (ssl, 0); SSL_set_wfd (ssl, 1); SSL_set_accept_state (ssl); /* If no data in max_wait seconds, give up */ if (max_wait) { signal (SIGALRM, sig_alarm); alarm (max_wait); } if (SSL_accept (ssl) <= 0) { logerrstr ("SSL_accept"); ERR_print_errors_fp (stderr); exit (1); } if (max_wait) alarm (0); /* check certificate */ client_cert = SSL_get_peer_certificate (ssl); if (client_cert == NULL) { pbc_log_activity (p, PBC_LOG_ERROR, "client_cert == NULL???"); exit (1); } peer = get_cn_from_crt (client_cert); if (peer == NULL) { pbc_log_activity (p, PBC_LOG_ERROR, "peer == NULL???"); exit (1); } pbc_log_activity (p, PBC_LOG_DEBUG_VERBOSE, "peer cn: %s\n", peer); /* read HTTP query */ if ((c=SSL_read (ssl, buf, sizeof(buf)-1)) <= 0) { pbc_log_activity (p, PBC_LOG_ERROR, "SSL_read() failed"); ERR_print_errors_fp (stderr); exit (1); } buf[c] = '\0'; pbc_log_activity (p, PBC_LOG_DEBUG_VERBOSE, "REQ=%s", buf); for (ptr = buf; *ptr != '\0'; ptr++) { if (*ptr == '?' || *ptr == '&') { /* next arg */ /* look for 'genkey' */ if (!strncmp (ptr + 1, "genkey=yes", 10)) { op = GENKEY; } else if (!strncmp (ptr + 1, "genkey=no", 9)) { op = FETCHKEY; } else if (!strncmp (ptr + 1, "genkey=put", 10)) { op = SETKEY; } else if (!strncmp (ptr + 1, "genkey=permit", 13)) { op = PERMIT; } else if (!strncmp (ptr + 1, "genkey=getgc", 12)) { op = FETCHGC; } else if (!strncmp (ptr + 1, "genkey=setpkey", 12)) { op = SETPKEY; } /* look for 'setkey' */ else if (!strncmp (ptr + 1, "setkey=", 7)) { char *q; ptr++; /* ? or & */ ptr += 7; /* setkey= */ setkey = strdup (ptr); /* terminated by ? - this is a bit dubious, but i think it's compensated for later - ssw */ q = strchr (setkey, '?'); if (q) *q = '\0'; } } } if (op == NOOP) { pbc_log_activity (p, PBC_LOG_ERROR, "peer didn't specify an operation"); exit (1); } /* call doit */ r = doit (peer, context, op, setkey, client_cert); SSL_shutdown (ssl); return r; }
static int init_ssl(CLI *c) { int i, err; SSL_SESSION *old_session; if(!(c->ssl=SSL_new(ctx))) { sslerror("SSL_new"); return -1; } #if SSLEAY_VERSION_NUMBER >= 0x0922 SSL_set_session_id_context(c->ssl, sid_ctx, strlen(sid_ctx)); #endif if(options.option.client) { if(c->opt->session) { enter_critical_section(CRIT_SESSION); SSL_set_session(c->ssl, c->opt->session); leave_critical_section(CRIT_SESSION); } SSL_set_fd(c->ssl, c->remote_fd.fd); SSL_set_connect_state(c->ssl); } else { if(c->local_rfd.fd==c->local_wfd.fd) SSL_set_fd(c->ssl, c->local_rfd.fd); else { /* Does it make sence to have SSL on STDIN/STDOUT? */ SSL_set_rfd(c->ssl, c->local_rfd.fd); SSL_set_wfd(c->ssl, c->local_wfd.fd); } SSL_set_accept_state(c->ssl); } /* Setup some values for transfer() function */ if(options.option.client) { c->sock_rfd=&(c->local_rfd); c->sock_wfd=&(c->local_wfd); c->ssl_rfd=c->ssl_wfd=&(c->remote_fd); } else { c->sock_rfd=c->sock_wfd=&(c->remote_fd); c->ssl_rfd=&(c->local_rfd); c->ssl_wfd=&(c->local_wfd); } while(1) { if(options.option.client) i=SSL_connect(c->ssl); else i=SSL_accept(c->ssl); err=SSL_get_error(c->ssl, i); if(err==SSL_ERROR_NONE) break; /* ok -> done */ if(err==SSL_ERROR_WANT_READ || err==SSL_ERROR_WANT_WRITE) { s_poll_zero(&c->fds); s_poll_add(&c->fds, c->ssl_rfd->fd, err==SSL_ERROR_WANT_READ, err==SSL_ERROR_WANT_WRITE); switch(s_poll_wait(&c->fds, c->opt->timeout_busy)) { case -1: sockerror("init_ssl: s_poll_wait"); return -1; /* error */ case 0: s_log(LOG_INFO, "init_ssl: s_poll_wait timeout"); return -1; /* timeout */ case 1: break; /* OK */ default: s_log(LOG_ERR, "init_ssl: s_poll_wait unknown result"); return -1; /* error */ } continue; /* ok -> retry */ } if(err==SSL_ERROR_SYSCALL) { switch(get_last_socket_error()) { case EINTR: case EAGAIN: continue; } } if(options.option.client) sslerror("SSL_connect"); else sslerror("SSL_accept"); return -1; } if(SSL_session_reused(c->ssl)) { s_log(LOG_INFO, "SSL %s: previous session reused", options.option.client ? "connected" : "accepted"); } else { /* a new session was negotiated */ if(options.option.client) { s_log(LOG_INFO, "SSL connected: new session negotiated"); enter_critical_section(CRIT_SESSION); old_session=c->opt->session; c->opt->session=SSL_get1_session(c->ssl); /* store it */ if(old_session) SSL_SESSION_free(old_session); /* release the old one */ leave_critical_section(CRIT_SESSION); } else s_log(LOG_INFO, "SSL accepted: new session negotiated"); print_cipher(c); } return 0; /* OK */ }
static void init_ssl(CLI * c) { int i, err; SSL_SESSION *old_session; c->ssl = SSL_new(c->opt->ctx); if (!c->ssl) { sslerror("SSL_new"); longjmp(c->err, 1); } SSL_set_ex_data(c->ssl, cli_index, c); if (c->opt->option.client) { if (c->opt->session) { SSL_set_session(c->ssl, c->opt->session); } SSL_set_fd(c->ssl, c->remote_fd.fd); SSL_set_connect_state(c->ssl); } else { if (c->local_rfd.fd == c->local_wfd.fd) SSL_set_fd(c->ssl, c->local_rfd.fd); else { SSL_set_rfd(c->ssl, c->local_rfd.fd); SSL_set_wfd(c->ssl, c->local_wfd.fd); } SSL_set_accept_state(c->ssl); } if (c->opt->option.client) { c->sock_rfd = &(c->local_rfd); c->sock_wfd = &(c->local_wfd); c->ssl_rfd = c->ssl_wfd = &(c->remote_fd); } else { c->sock_rfd = c->sock_wfd = &(c->remote_fd); c->ssl_rfd = &(c->local_rfd); c->ssl_wfd = &(c->local_wfd); } while (1) { if (c->opt->option.client) i = SSL_connect(c->ssl); else i = SSL_accept(c->ssl); err = SSL_get_error(c->ssl, i); if (err == SSL_ERROR_NONE) break; if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { s_poll_init(c->fds); s_poll_add(c->fds, c->ssl_rfd->fd, err == SSL_ERROR_WANT_READ, err == SSL_ERROR_WANT_WRITE); switch (s_poll_wait(c->fds, c->opt->timeout_busy, 0)) { case -1: sockerror("init_ssl: s_poll_wait"); longjmp(c->err, 1); case 0: s_log(LOG_INFO, "init_ssl: s_poll_wait:" " TIMEOUTbusy exceeded: sending reset"); longjmp(c->err, 1); case 1: break; default: s_log(LOG_ERR, "init_ssl: s_poll_wait: unknown result"); longjmp(c->err, 1); } continue; } if (err == SSL_ERROR_SYSCALL) { switch (get_last_socket_error()) { case S_EINTR: case S_EWOULDBLOCK: #if S_EAGAIN!=S_EWOULDBLOCK case S_EAGAIN: #endif continue; } } if (c->opt->option.client) sslerror("SSL_connect"); else sslerror("SSL_accept"); longjmp(c->err, 1); } if (SSL_session_reused(c->ssl)) { s_log(LOG_INFO, "SSL %s: previous session reused", c->opt->option.client ? "connected" : "accepted"); } else { if (c->opt->option.client) { s_log(LOG_INFO, "SSL connected: new session negotiated"); old_session = c->opt->session; c->opt->session = SSL_get1_session(c->ssl); if (old_session) SSL_SESSION_free(old_session); } else s_log(LOG_INFO, "SSL accepted: new session negotiated"); print_cipher(c); } }
static int openssl_ssl_set(lua_State*L) { SSL* s = CHECK_OBJECT(1, SSL, "openssl.ssl"); int i; int top = lua_gettop(L); int ret = 1; for (i = 2; i <= top; i += 2) { const char* what = luaL_checklstring(L, i, NULL); if (strcmp(what, "fd") == 0) { ret = SSL_set_fd(s, luaL_checkint(L, i + 1)); } else if (strcmp(what, "rfd") == 0) { ret = SSL_set_wfd(s, luaL_checkint(L, i + 1)); } else if (strcmp(what, "wfd") == 0) { ret = SSL_set_wfd(s, luaL_checkint(L, i + 1)); } else if (strcmp(what, "client_CA") == 0) { X509* x = CHECK_OBJECT(i + 1, X509, "openssl.x509"); ret = SSL_add_client_CA(s, x); } else if (strcmp(what, "read_ahead") == 0) { int yes = auxiliar_checkboolean(L, i + 1); SSL_set_read_ahead(s, yes); } else if (strcmp(what, "cipher_list") == 0) { const char* list = lua_tostring(L, i + 1); ret = SSL_set_cipher_list(s, list); } else if (strcmp(what, "verify_depth") == 0) { int depth = luaL_checkint(L, i + 1); SSL_set_verify_depth(s, depth); } else if (strcmp(what, "purpose") == 0) { //FIX int purpose = luaL_checkint(L, i + 1); ret = SSL_set_purpose(s, purpose); } else if (strcmp(what, "trust") == 0) { //FIX int trust = luaL_checkint(L, i + 1); ret = SSL_set_trust(s, trust); } else if (strcmp(what, "verify_result") == 0) { int result = luaL_checkint(L, i + 1); SSL_set_verify_result(s, result); } else if (strcmp(what, "hostname") == 0) { const char* hostname = luaL_checkstring(L, i + 1); SSL_set_tlsext_host_name(s, hostname); } #if OPENSSL_VERSION_NUMBER > 0x10000000L else if (strcmp(what, "state") == 0) { int l = luaL_checkint(L, 2); SSL_set_state(s, l); } #endif else luaL_argerror(L, i, "don't understand"); if (ret != 1) return openssl_pushresult(L, ret); } return 0; }
int tls_connect_fds(struct tls *ctx, int fd_read, int fd_write, const char *servername) { union tls_addr addrbuf; int rv = -1; if ((ctx->flags & TLS_CLIENT) == 0) { tls_set_errorx(ctx, "not a client context"); goto err; } if (fd_read < 0 || fd_write < 0) { tls_set_errorx(ctx, "invalid file descriptors"); goto err; } if (servername != NULL) { if ((ctx->servername = strdup(servername)) == NULL) { tls_set_errorx(ctx, "out of memory"); goto err; } } if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) { tls_set_errorx(ctx, "ssl context failure"); goto err; } if (tls_configure_ssl(ctx) != 0) goto err; if (tls_configure_keypair(ctx, ctx->ssl_ctx, ctx->config->keypair, 0) != 0) goto err; if (ctx->config->verify_name) { if (servername == NULL) { tls_set_errorx(ctx, "server name not specified"); goto err; } } if (ctx->config->verify_cert && (tls_configure_ssl_verify(ctx, SSL_VERIFY_PEER) == -1)) goto err; if (SSL_CTX_set_tlsext_status_cb(ctx->ssl_ctx, tls_ocsp_verify_callback) != 1) { tls_set_errorx(ctx, "ssl OCSP verification setup failure"); goto err; } if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { tls_set_errorx(ctx, "ssl connection failure"); goto err; } if (SSL_set_app_data(ctx->ssl_conn, ctx) != 1) { tls_set_errorx(ctx, "ssl application data failure"); goto err; } if (SSL_set_rfd(ctx->ssl_conn, fd_read) != 1 || SSL_set_wfd(ctx->ssl_conn, fd_write) != 1) { tls_set_errorx(ctx, "ssl file descriptor failure"); goto err; } if (SSL_set_tlsext_status_type(ctx->ssl_conn, TLSEXT_STATUSTYPE_ocsp) != 1) { tls_set_errorx(ctx, "ssl OCSP extension setup failure"); goto err; } /* * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not * permitted in "HostName". */ if (servername != NULL && inet_pton(AF_INET, servername, &addrbuf) != 1 && inet_pton(AF_INET6, servername, &addrbuf) != 1) { if (SSL_set_tlsext_host_name(ctx->ssl_conn, servername) == 0) { tls_set_errorx(ctx, "server name indication failure"); goto err; } } rv = 0; err: return (rv); }
static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int verify) { #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) const SSL_METHOD *meth; #else SSL_METHOD *meth; #endif SSL_CTX *ctx; int ret; X509 *cert; SSL_library_init(); SSL_load_error_strings(); meth = SSLv23_method(); if (!meth) { ssl_socket_perror("SSLv23_method"); return -1; } ctx = SSL_CTX_new(meth); if (!ctx) { ssl_socket_perror("SSL_CTX_new"); return -1; } if (use_tls_only) SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); if (verify) SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); if (!SSL_CTX_set_default_verify_paths(ctx)) { ssl_socket_perror("SSL_CTX_set_default_verify_paths"); return -1; } sock->ssl = SSL_new(ctx); if (!sock->ssl) { ssl_socket_perror("SSL_new"); return -1; } if (!SSL_set_rfd(sock->ssl, sock->fd[0])) { ssl_socket_perror("SSL_set_rfd"); return -1; } if (!SSL_set_wfd(sock->ssl, sock->fd[1])) { ssl_socket_perror("SSL_set_wfd"); return -1; } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME /* * SNI (RFC4366) * OpenSSL does not document this function, but the implementation * returns 1 on success, 0 on failure after calling SSLerr(). */ ret = SSL_set_tlsext_host_name(sock->ssl, server.host); if (ret != 1) warning("SSL_set_tlsext_host_name(%s) failed.", server.host); #endif ret = SSL_connect(sock->ssl); if (ret <= 0) { socket_perror("SSL_connect", sock, ret); return -1; } if (verify) { /* make sure the hostname matches that of the certificate */ cert = SSL_get_peer_certificate(sock->ssl); if (!cert) return error("unable to get peer certificate."); if (verify_hostname(cert, server.host) < 0) return -1; } return 0; }
static void init_ssl(CLI *c) { int i, err; SSL_SESSION *old_session; int unsafe_openssl; c->ssl=SSL_new(c->opt->ctx); if(!c->ssl) { sslerror("SSL_new"); longjmp(c->err, 1); } SSL_set_ex_data(c->ssl, cli_index, c); /* for callbacks */ if(c->opt->option.client) { #ifndef OPENSSL_NO_TLSEXT if(c->opt->sni) { s_log(LOG_DEBUG, "SNI: host name: %s", c->opt->sni); if(!SSL_set_tlsext_host_name(c->ssl, c->opt->sni)) { sslerror("SSL_set_tlsext_host_name"); longjmp(c->err, 1); } } #endif if(c->opt->session) { enter_critical_section(CRIT_SESSION); SSL_set_session(c->ssl, c->opt->session); leave_critical_section(CRIT_SESSION); } SSL_set_fd(c->ssl, c->remote_fd.fd); SSL_set_connect_state(c->ssl); } else { if(c->local_rfd.fd==c->local_wfd.fd) SSL_set_fd(c->ssl, c->local_rfd.fd); else { /* does it make sense to have SSL on STDIN/STDOUT? */ SSL_set_rfd(c->ssl, c->local_rfd.fd); SSL_set_wfd(c->ssl, c->local_wfd.fd); } SSL_set_accept_state(c->ssl); } /* setup some values for transfer() function */ if(c->opt->option.client) { c->sock_rfd=&(c->local_rfd); c->sock_wfd=&(c->local_wfd); c->ssl_rfd=c->ssl_wfd=&(c->remote_fd); } else { c->sock_rfd=c->sock_wfd=&(c->remote_fd); c->ssl_rfd=&(c->local_rfd); c->ssl_wfd=&(c->local_wfd); } unsafe_openssl=SSLeay()<0x0090810fL || (SSLeay()>=0x10000000L && SSLeay()<0x1000002fL); while(1) { /* critical section for OpenSSL version < 0.9.8p or 1.x.x < 1.0.0b * * this critical section is a crude workaround for CVE-2010-3864 * * see http://www.securityfocus.com/bid/44884 for details * * alternative solution is to disable internal session caching * * NOTE: this critical section also covers callbacks (e.g. OCSP) */ if(unsafe_openssl) enter_critical_section(CRIT_SSL); if(c->opt->option.client) i=SSL_connect(c->ssl); else i=SSL_accept(c->ssl); if(unsafe_openssl) leave_critical_section(CRIT_SSL); err=SSL_get_error(c->ssl, i); if(err==SSL_ERROR_NONE) break; /* ok -> done */ if(err==SSL_ERROR_WANT_READ || err==SSL_ERROR_WANT_WRITE) { s_poll_init(c->fds); s_poll_add(c->fds, c->ssl_rfd->fd, err==SSL_ERROR_WANT_READ, err==SSL_ERROR_WANT_WRITE); switch(s_poll_wait(c->fds, c->opt->timeout_busy, 0)) { case -1: sockerror("init_ssl: s_poll_wait"); longjmp(c->err, 1); case 0: s_log(LOG_INFO, "init_ssl: s_poll_wait:" " TIMEOUTbusy exceeded: sending reset"); longjmp(c->err, 1); case 1: break; /* OK */ default: s_log(LOG_ERR, "init_ssl: s_poll_wait: unknown result"); longjmp(c->err, 1); } continue; /* ok -> retry */ } if(err==SSL_ERROR_SYSCALL) { switch(get_last_socket_error()) { case S_EINTR: case S_EWOULDBLOCK: #if S_EAGAIN!=S_EWOULDBLOCK case S_EAGAIN: #endif continue; } } if(c->opt->option.client) sslerror("SSL_connect"); else sslerror("SSL_accept"); longjmp(c->err, 1); } if(SSL_session_reused(c->ssl)) { s_log(LOG_INFO, "SSL %s: previous session reused", c->opt->option.client ? "connected" : "accepted"); } else { /* a new session was negotiated */ #ifdef USE_WIN32 win_new_chain(c); #endif if(c->opt->option.client) { s_log(LOG_INFO, "SSL connected: new session negotiated"); enter_critical_section(CRIT_SESSION); old_session=c->opt->session; c->opt->session=SSL_get1_session(c->ssl); /* store it */ if(old_session) SSL_SESSION_free(old_session); /* release the old one */ leave_critical_section(CRIT_SESSION); } else s_log(LOG_INFO, "SSL accepted: new session negotiated"); print_cipher(c); } }
int tls_connect_fds(struct tls *ctx, int fd_read, int fd_write, const char *servername) { union { struct in_addr ip4; struct in6_addr ip6; } addrbuf; X509 *cert = NULL; int ret, err; if (ctx->flags & TLS_CONNECTING) goto connecting; if ((ctx->flags & TLS_CLIENT) == 0) { tls_set_error(ctx, "not a client context"); goto err; } if (fd_read < 0 || fd_write < 0) { tls_set_error(ctx, "invalid file descriptors"); return (-1); } if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) { tls_set_error(ctx, "ssl context failure"); goto err; } if (tls_configure_ssl(ctx) != 0) goto err; if (ctx->config->verify_name) { if (servername == NULL) { tls_set_error(ctx, "server name not specified"); goto err; } } if (ctx->config->verify_cert) { SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL); if (ctx->config->ca_mem != NULL) { if (ctx->config->ca_len > INT_MAX) { tls_set_error(ctx, "ca too long"); goto err; } if (SSL_CTX_load_verify_mem(ctx->ssl_ctx, ctx->config->ca_mem, ctx->config->ca_len) != 1) { tls_set_error(ctx, "ssl verify memory setup failure"); goto err; } } else if (SSL_CTX_load_verify_locations(ctx->ssl_ctx, ctx->config->ca_file, ctx->config->ca_path) != 1) { tls_set_error(ctx, "ssl verify setup failure"); goto err; } if (ctx->config->verify_depth >= 0) SSL_CTX_set_verify_depth(ctx->ssl_ctx, ctx->config->verify_depth); } if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { tls_set_error(ctx, "ssl connection failure"); goto err; } if (SSL_set_rfd(ctx->ssl_conn, fd_read) != 1 || SSL_set_wfd(ctx->ssl_conn, fd_write) != 1) { tls_set_error(ctx, "ssl file descriptor failure"); goto err; } /* * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not * permitted in "HostName". */ if (servername != NULL && inet_pton(AF_INET, servername, &addrbuf) != 1 && inet_pton(AF_INET6, servername, &addrbuf) != 1) { if (SSL_set_tlsext_host_name(ctx->ssl_conn, servername) == 0) { tls_set_error(ctx, "server name indication failure"); goto err; } } connecting: if ((ret = SSL_connect(ctx->ssl_conn)) != 1) { err = tls_ssl_error(ctx, ret, "connect"); if (err == TLS_READ_AGAIN || err == TLS_WRITE_AGAIN) { ctx->flags |= TLS_CONNECTING; return (err); } goto err; } ctx->flags &= ~TLS_CONNECTING; if (ctx->config->verify_name) { cert = SSL_get_peer_certificate(ctx->ssl_conn); if (cert == NULL) { tls_set_error(ctx, "no server certificate"); goto err; } if ((ret = tls_check_servername(ctx, cert, servername)) != 0) { if (ret != -2) tls_set_error(ctx, "name `%s' not present in" " server certificate", servername); goto err; } } return (0); err: X509_free(cert); return (-1); }
static int init_ssl(CLI *c) { int i, err; if(!(c->ssl=SSL_new(ctx))) { sslerror("SSL_new"); return -1; } #if SSLEAY_VERSION_NUMBER >= 0x0922 SSL_set_session_id_context(c->ssl, sid_ctx, strlen(sid_ctx)); #endif if(options.option.client) { /* Attempt to use the most recent id in the session cache */ #ifndef HAVE_YASSL /* yassl add, ctx members available */ if(ctx->session_cache_head) if(!SSL_set_session(c->ssl, ctx->session_cache_head)) log(LOG_WARNING, "Cannot set SSL session id to most recent used"); #endif /* yassl end add */ SSL_set_fd(c->ssl, c->remote_fd.fd); SSL_set_connect_state(c->ssl); } else { if(c->local_rfd.fd==c->local_wfd.fd) SSL_set_fd(c->ssl, c->local_rfd.fd); else { /* Does it make sence to have SSL on STDIN/STDOUT? */ SSL_set_rfd(c->ssl, c->local_rfd.fd); SSL_set_wfd(c->ssl, c->local_wfd.fd); } SSL_set_accept_state(c->ssl); } /* Setup some values for transfer() function */ if(options.option.client) { c->sock_rfd=&(c->local_rfd); c->sock_wfd=&(c->local_wfd); c->ssl_rfd=c->ssl_wfd=&(c->remote_fd); } else { c->sock_rfd=c->sock_wfd=&(c->remote_fd); c->ssl_rfd=&(c->local_rfd); c->ssl_wfd=&(c->local_wfd); } while(1) { if(options.option.client) i=SSL_connect(c->ssl); else i=SSL_accept(c->ssl); err=SSL_get_error(c->ssl, i); if(err==SSL_ERROR_NONE) break; /* ok -> done */ if(err==SSL_ERROR_WANT_READ) { if(waitforsocket(c->ssl_rfd->fd, 0, c->opt->timeout_busy)==1) continue; /* ok -> retry */ return -1; /* timeout or error */ } if(err==SSL_ERROR_WANT_WRITE) { if(waitforsocket(c->ssl_wfd->fd, 1, c->opt->timeout_busy)==1) continue; /* ok -> retry */ return -1; /* timeout or error */ } if(err==SSL_ERROR_SYSCALL) { switch(get_last_socket_error()) { case EINTR: case EAGAIN: continue; } } if(options.option.client) sslerror("SSL_connect"); else sslerror("SSL_accept"); return -1; } print_cipher(c); return 0; /* OK */ }