R_API RSocket *r_socket_accept(RSocket *s) { RSocket *sock; if (!s) return NULL; sock = R_NEW (RSocket); if (!sock) return NULL; sock->is_ssl = s->is_ssl; sock->fd = accept (s->fd, NULL, NULL); if (sock->fd == -1) { free (sock); return NULL; } #if HAVE_LIB_SSL if (sock->is_ssl) { sock->sfd = NULL; sock->ctx = NULL; sock->bio = NULL; BIO *sbio = BIO_new_socket (sock->fd, BIO_NOCLOSE); sock->sfd = SSL_new (s->ctx); SSL_set_bio (sock->sfd, sbio, sbio); if (SSL_accept (sock->sfd) <= 0) { r_socket_free (sock); return NULL; } sock->bio = BIO_new (BIO_f_buffer ()); sbio = BIO_new (BIO_f_ssl ()); BIO_set_ssl (sbio, sock->sfd, BIO_CLOSE); BIO_push (sock->bio, sbio); } #endif return sock; }
int receiveFile(char *socket, char *outfile) { BIO *receive = BIO_new_accept(socket); BIO *fileout = BIO_new_file(outfile,"w"); // it seems you need to do this twice.. not sure why, but we do // guess I'll try figure out why at some point if (BIO_do_accept(receive) <= 0) { fprintf(stderr, "Error setting up accept\n"); exit(0); } if (BIO_do_accept(receive) <= 0) { fprintf(stderr, "Error setting up accept\n"); exit(0); } char tmpbuf[BUFSIZ]; // magic wrapper BIO *bufbio = BIO_new(BIO_f_buffer()); BIO_push(bufbio, receive); //read in the file length and store BIO_gets(bufbio, tmpbuf, BUFSIZ); printf("Getting file length: %s\n", tmpbuf); unsigned int size = atoi(tmpbuf); transmit(bufbio, fileout, size); BIO_flush(fileout); BIO_free(bufbio); return 1; }
static BIO_METHOD * hb_BIO_METHOD_par( int iParam ) { BIO_METHOD * p; switch( hb_parni( iParam ) ) { case HB_BIO_METHOD_S_NULL: p = BIO_s_null(); break; #ifndef OPENSSL_NO_FP_API case HB_BIO_METHOD_S_FILE: p = BIO_s_file(); break; #endif case HB_BIO_METHOD_S_MEM: p = BIO_s_mem(); break; case HB_BIO_METHOD_S_SOCKET: p = BIO_s_socket(); break; case HB_BIO_METHOD_S_CONNECT: p = BIO_s_connect(); break; case HB_BIO_METHOD_S_ACCEPT: p = BIO_s_accept(); break; case HB_BIO_METHOD_S_FD: p = BIO_s_fd(); break; #if 0 /* BIO_s_log() isn't exported via implibs on Windows at version 0.9.8k. [vszakats] */ #ifndef OPENSSL_SYS_OS2 case HB_BIO_METHOD_S_LOG: p = BIO_s_log(); break; #endif #endif case HB_BIO_METHOD_S_BIO: p = BIO_s_bio(); break; #ifndef OPENSSL_NO_DGRAM case HB_BIO_METHOD_S_DATAGRAM: p = BIO_s_datagram(); break; #endif case HB_BIO_METHOD_F_NULL: p = BIO_f_null(); break; case HB_BIO_METHOD_F_BUFFER: p = BIO_f_buffer(); break; #ifdef OPENSSL_SYS_VMS case HB_BIO_METHOD_F_LINEBUFFER: p = BIO_f_linebuffer(); break; #endif case HB_BIO_METHOD_F_NBIO_TEST: p = BIO_f_nbio_test(); break; default: p = NULL; } return p; }
R_API RSocket *r_socket_accept(RSocket *s) { RSocket *sock; socklen_t salen = sizeof (s->sa); if (!s) return NULL; sock = R_NEW (RSocket); if (!sock) return NULL; //signal (SIGPIPE, SIG_DFL); sock->fd = accept (s->fd, (struct sockaddr *)&s->sa, &salen); if (sock->fd == -1) { free (sock); return NULL; } #if HAVE_LIB_SSL sock->is_ssl = s->is_ssl; if (sock->is_ssl) { sock->sfd = NULL; sock->ctx = NULL; sock->bio = NULL; BIO *sbio = BIO_new_socket (sock->fd, BIO_NOCLOSE); sock->sfd = SSL_new (s->ctx); SSL_set_bio (sock->sfd, sbio, sbio); if (SSL_accept (sock->sfd) <= 0) { r_socket_free (sock); return NULL; } sock->bio = BIO_new (BIO_f_buffer ()); sbio = BIO_new (BIO_f_ssl ()); BIO_set_ssl (sbio, sock->sfd, BIO_CLOSE); BIO_push (sock->bio, sbio); } #else sock->is_ssl = 0; #endif return sock; }
int alloc_cipher_BIOs( BIO **buffer, BIO **b64, BIO **cipher ) { *buffer = *b64 = *cipher = NULL; /* Create a buffering filter BIO to buffer writes to the file */ *buffer = BIO_new (BIO_f_buffer ()); if( buffer == NULL ) { return -1; } /* Create a base64 encoding filter BIO */ *b64 = BIO_new (BIO_f_base64 ()); if( *b64 == NULL ) { BIO_free( *buffer ); *buffer = NULL; return -1; } *cipher = BIO_new (BIO_f_cipher ()); if( *cipher == NULL ) { BIO_free( *buffer ); BIO_free( *b64 ); *buffer = *b64 = NULL; return -1; } /* success */ return 0; }
int read_b64( const char *filename, unsigned char *out, int len ) { int count; BIO *b64, *buffer, *file; /* Create a buffered file BIO for reading */ file = BIO_new_file (filename, "r"); if (!file) { /* FIXME - log an error */ return -1; } /* Create a base64 encoding filter BIO */ b64 = BIO_new (BIO_f_base64 ()); if( b64 == NULL ) { /* FIXME - log an error */ return -1; } buffer = BIO_new (BIO_f_buffer ()); /* Assemble the BIO chain to be in the order b64-file */ BIO_push (b64, buffer ); BIO_push( buffer, file ); /* load the data */ count = read_from_BIO( b64, out, len ); assert( count == len ); BIO_free_all( b64 ); /* success */ return count; }
bool SSLClient::connection(const string& host, const int& port) { if(host=="localhost") { return connectionUnresolv(host, port); } struct sockaddr_in *remote; int tmpres; char *ip; sockfd = create_tcp_socket(); ip = get_ip((char*)host.c_str()); fprintf(stderr, "IP is %s\n", ip); remote = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in *)); remote->sin_family = AF_INET; tmpres = inet_pton(AF_INET, ip, (void *)(&(remote->sin_addr.s_addr))); if( tmpres < 0) { perror("Can't set remote->sin_addr.s_addr"); return false; } else if(tmpres == 0) { fprintf(stderr, "%s is not a valid IP address\n", ip); return false; } remote->sin_port = htons(port); if(connect(sockfd, (struct sockaddr *)remote, sizeof(struct sockaddr)) < 0){ perror("Could not connect"); connected = false; } else { connected = true; } free(remote); free(ip); /* Build our SSL context*/ init(); /* Connect the SSL socket */ ssl=SSL_new(ctx); sbio=BIO_new_socket(sockfd,BIO_CLOSE); SSL_set_bio(ssl,sbio,sbio); io=BIO_new(BIO_f_buffer()); ssl_bio=BIO_new(BIO_f_ssl()); BIO_set_ssl(ssl_bio,ssl,BIO_NOCLOSE); BIO_push(io,ssl_bio); if(SSL_connect(ssl)<=0) { logger << "SSL connect error"; return false; } ERR_clear_error(); connected = true; return true; }
/* NOTE: Unused yet. Commented to avoid warning */ static int hb_BIO_METHOD_ptr_to_id( const BIO_METHOD * p ) { int n; if( p == BIO_s_null() ) n = HB_BIO_METHOD_S_NULL; #ifndef OPENSSL_NO_FP_API else if( p == BIO_s_file() ) n = HB_BIO_METHOD_S_FILE; #endif else if( p == BIO_s_mem() ) n = HB_BIO_METHOD_S_MEM; else if( p == BIO_s_socket() ) n = HB_BIO_METHOD_S_SOCKET; else if( p == BIO_s_connect() ) n = HB_BIO_METHOD_S_CONNECT; else if( p == BIO_s_accept() ) n = HB_BIO_METHOD_S_ACCEPT; else if( p == BIO_s_fd() ) n = HB_BIO_METHOD_S_FD; #if 0 /* BIO_s_log() isn't exported via implibs on Windows at version 0.9.8k. [vszakats] */ #ifndef OPENSSL_SYS_OS2 else if( p == BIO_s_log() ) n = HB_BIO_METHOD_S_LOG; #endif #endif else if( p == BIO_s_bio() ) n = HB_BIO_METHOD_S_BIO; #ifndef OPENSSL_NO_DGRAM else if( p == BIO_s_datagram() ) n = HB_BIO_METHOD_S_DATAGRAM; #endif else if( p == BIO_f_null() ) n = HB_BIO_METHOD_F_NULL; else if( p == BIO_f_buffer() ) n = HB_BIO_METHOD_F_BUFFER; #ifdef OPENSSL_SYS_VMS else if( p == BIO_f_linebuffer() ) n = HB_BIO_METHOD_F_LINEBUFFER; #endif else if( p == BIO_f_nbio_test() ) n = HB_BIO_METHOD_F_NBIO_TEST; else n = HB_BIO_METHOD_UNSUPPORTED; return n; }
int MaOpenSslSocket::initConnection() { BIO *bioSSL, *bioSock; if (bio) { return 0; } bio = BIO_new(BIO_f_buffer()); if (bio == 0) { return MPR_ERR_CANT_INITIALIZE; } BIO_set_write_buffer_size(bio, 128); ssl = (SSL*) SSL_new(context); mprAssert(ssl); if (ssl == 0) { return MPR_ERR_CANT_INITIALIZE; } SSL_set_app_data(ssl, (void*) this); SSL_set_session(ssl, 0); bioSSL = BIO_new(BIO_f_ssl()); mprAssert(bioSSL); bioSock = BIO_new_socket(sock, BIO_NOCLOSE); mprAssert(bioSock); SSL_set_bio(ssl, bioSock, bioSock); SSL_set_accept_state(ssl); BIO_set_ssl(bioSSL, ssl, BIO_CLOSE); BIO_push(bio, bioSSL); return 0; }
void* conn_handler(void *arg) { long err; SSL *ssl; struct conn_ctx *ctx = (struct conn_ctx *)arg; struct freeq_ctx *freeqctx = ctx->srvctx->freeqctx; struct freeqd_state *fst = ctx->srvctx->fst; BIO *client = ctx->client; pthread_detach(pthread_self()); ssl = freeq_ssl_new(freeqctx); SSL_set_bio(ssl, client, client); if (SSL_accept(ssl) <= 0) { int_error("Error accepting SSL connection"); return NULL; } if ((err = post_connection_check(freeqctx, ssl, "localhost")) != X509_V_OK) { err(freeqctx, "error: peer certificate: %s\n", X509_verify_cert_error_string(err)); int_error("Error checking SSL object after connection"); } BIO *buf_io, *ssl_bio; buf_io = BIO_new(BIO_f_buffer()); ssl_bio = BIO_new(BIO_f_ssl()); BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE); BIO_push(buf_io, ssl_bio); dbg(freeqctx, "ssl client connection opened\n"); if (generation_table_merge(freeqctx, fst, buf_io)) { err(freeqctx, "table merge failed\n"); SSL_shutdown(ssl); } else { dbg(freeqctx, "table merged ok\n"); SSL_clear(ssl); } dbg(freeqctx, "ssl client connection closed\n"); SSL_free(ssl); ERR_remove_state(0); return 0; }
HybridSslConnection* hybrid_ssl_connect(const gchar *hostname, gint port, ssl_callback func, gpointer user_data) { BIO *buf_io; BIO *ssl_bio; HybridSslConnection *conn; g_return_val_if_fail(hostname != NULL, NULL); g_return_val_if_fail(port != 0, NULL); g_return_val_if_fail(func != NULL, NULL); SSLeay_add_all_algorithms(); SSL_load_error_strings(); SSL_library_init(); conn = g_new0(HybridSslConnection, 1); if (!(conn->ssl_ctx = SSL_CTX_new(SSLv23_client_method()))) { hybrid_debug_error("ssl", "initialize SSL CTX: %s", ERR_reason_error_string(ERR_get_error())); hybrid_ssl_connection_destory(conn); return NULL; } if (!(conn->ssl = ssl_new_with_certs(conn->ssl_ctx))) { hybrid_ssl_connection_destory(conn); return NULL; } SSL_set_mode(conn->ssl, SSL_MODE_AUTO_RETRY); buf_io = BIO_new(BIO_f_buffer()); ssl_bio = BIO_new(BIO_f_ssl()); BIO_set_ssl(ssl_bio, conn->ssl, BIO_NOCLOSE); BIO_push(buf_io, ssl_bio); conn->conn_cb = func; conn->conn_data = user_data; conn->rbio = buf_io; conn->conn = hybrid_proxy_connect(hostname, port, ssl_connect_cb, conn); return conn; }
BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx) { #ifndef OPENSSL_NO_SOCK BIO *ret=NULL,*buf=NULL,*ssl=NULL; if ((buf=BIO_new(BIO_f_buffer())) == NULL) return(NULL); if ((ssl=BIO_new_ssl_connect(ctx)) == NULL) goto err; if ((ret=BIO_push(buf,ssl)) == NULL) goto err; return(ret); err: if (buf != NULL) BIO_free(buf); if (ssl != NULL) BIO_free(ssl); #endif return(NULL); }
void handle_table(struct freeq_ctx *ctx, SSL *ssl) { BIO *buf_io, *ssl_bio; //char rbuf[1024]; //char wbuf[1024]; buf_io = BIO_new(BIO_f_buffer()); /* create a buffer BIO */ ssl_bio = BIO_new(BIO_f_ssl()); /* create an ssl BIO */ BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE); /* assign the ssl BIO to SSL */ BIO_push(buf_io, ssl_bio); /* add ssl_bio to buf_io */ /* ret = BIO_puts(buf_io, wbuf); */ /* Write contents of wbuf[] into buf_io */ /* ret = BIO_write(buf_io, wbuf, wlen); */ /* Write wlen-byte contents of wbuf[] into buf_io */ /* ret = BIO_gets(buf_io, rbuf, READBUF_SIZE); */ /* Read data from buf_io and store in rbuf[] */ /* ret = BIO_read(buf_io, rbuf, rlen); */ /* Read rlen-byte data from buf_io and store rbuf[] */ }
bool SSLClient::connectionUnresolv(const string& host, const int& port) { struct addrinfo hints, *servinfo, *p; int rv; char s[INET6_ADDRSTRLEN]; memset(s, 0, sizeof(s)); memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; string sport = CastUtil::lexical_cast<string>(port); if ((rv = getaddrinfo(host.c_str(), sport.c_str(), &hints, &servinfo)) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); return false; } // loop through all the results and connect to the first we can for(p = servinfo; p != NULL; p = p->ai_next) { if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { perror("client: socket"); continue; } if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) { closesocket(sockfd); perror("client: connect"); connected = false; continue; } else { connected = true; } break; } if (p == NULL) { fprintf(stderr, "client: failed to connect\n"); return false; } inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof s); //printf("client: connecting to %s\n", s); freeaddrinfo(servinfo); // all done with this structure /* Build our SSL context*/ init(); /* Connect the SSL socket */ ssl=SSL_new(ctx); sbio=BIO_new_socket(sockfd,BIO_CLOSE); SSL_set_bio(ssl,sbio,sbio); io=BIO_new(BIO_f_buffer()); ssl_bio=BIO_new(BIO_f_ssl()); BIO_set_ssl(ssl_bio,ssl,BIO_NOCLOSE); BIO_push(io,ssl_bio); if(SSL_connect(ssl)<=0) { logger << "SSL connect error"; return false; } ERR_clear_error(); return connected; }
static int http_serve(SSL *ssl, int s) { char buf[BUFSIZZ]; int r,len; BIO *io,*ssl_bio; io=BIO_new(BIO_f_buffer()); ssl_bio=BIO_new(BIO_f_ssl()); BIO_set_ssl(ssl_bio,ssl,BIO_CLOSE); BIO_push(io,ssl_bio); while(1){ r=BIO_gets(io,buf,BUFSIZZ-1); switch(SSL_get_error(ssl,r)){ case SSL_ERROR_NONE: len=r; break; case SSL_ERROR_ZERO_RETURN: goto shutdown; break; default: berr_exit("SSL read problem"); } /* Look for the blank line that signals the end of the HTTP headers */ if(!strcmp(buf,"\r\n") || !strcmp(buf,"\n")) break; } /* Now perform renegotiation if requested */ if(client_auth==CLIENT_AUTH_REHANDSHAKE){ SSL_set_verify(ssl,SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0); /* Stop the client from just resuming the un-authenticated session */ SSL_set_session_id_context(ssl, (void *)&s_server_auth_session_id_context, sizeof(s_server_auth_session_id_context)); if(SSL_renegotiate(ssl)<=0) berr_exit("SSL renegotiation error"); if(SSL_do_handshake(ssl)<=0) berr_exit("SSL renegotiation error"); ssl->state=SSL_ST_ACCEPT; if(SSL_do_handshake(ssl)<=0) berr_exit("SSL renegotiation error"); } if((r=BIO_puts (io,"HTTP/1.0 200 OK\r\n"))<=0) err_exit("Write error"); if((r=BIO_puts (io,"Server: EKRServer\r\n\r\n"))<=0) err_exit("Write error"); if((r=BIO_puts (io,"Server test page\r\n"))<=0) err_exit("Write error"); if((r=BIO_flush(io))<0) err_exit("Error flushing BIO"); shutdown: r=SSL_shutdown(ssl); if(!r){ /* If we called SSL_shutdown() first then we always get return value of '0'. In this case, try again, but first send a TCP FIN to trigger the other side's close_notify*/ shutdown(s,1); r=SSL_shutdown(ssl); } switch(r){ case 1: break; /* Success */ case 0: case -1: default: berr_exit("Shutdown failed"); } SSL_free(ssl); close(s); return(0); }
static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader, const char *uri, const UI_METHOD *ui_method, void *ui_data) { OSSL_STORE_LOADER_CTX *ctx = NULL; struct stat st; struct { const char *path; unsigned int check_absolute:1; } path_data[2]; size_t path_data_n = 0, i; const char *path; /* * First step, just take the URI as is. */ path_data[path_data_n].check_absolute = 0; path_data[path_data_n++].path = uri; /* * Second step, if the URI appears to start with the 'file' scheme, * extract the path and make that the second path to check. * There's a special case if the URI also contains an authority, then * the full URI shouldn't be used as a path anywhere. */ if (strncasecmp(uri, "file:", 5) == 0) { const char *p = &uri[5]; if (strncmp(&uri[5], "//", 2) == 0) { path_data_n--; /* Invalidate using the full URI */ if (strncasecmp(&uri[7], "localhost/", 10) == 0) { p = &uri[16]; } else if (uri[7] == '/') { p = &uri[7]; } else { OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN, OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED); return NULL; } } path_data[path_data_n].check_absolute = 1; #ifdef _WIN32 /* Windows file: URIs with a drive letter start with a / */ if (p[0] == '/' && p[2] == ':' && p[3] == '/') { char c = ossl_tolower(p[1]); if (c >= 'a' && c <= 'z') { p++; /* We know it's absolute, so no need to check */ path_data[path_data_n].check_absolute = 0; } } #endif path_data[path_data_n++].path = p; } for (i = 0, path = NULL; path == NULL && i < path_data_n; i++) { /* * If the scheme "file" was an explicit part of the URI, the path must * be absolute. So says RFC 8089 */ if (path_data[i].check_absolute && path_data[i].path[0] != '/') { OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN, OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE); ERR_add_error_data(1, path_data[i].path); return NULL; } if (stat(path_data[i].path, &st) < 0) { SYSerr(SYS_F_STAT, errno); ERR_add_error_data(1, path_data[i].path); } else { path = path_data[i].path; } } if (path == NULL) { return NULL; } /* Successfully found a working path, clear possible collected errors */ ERR_clear_error(); ctx = OPENSSL_zalloc(sizeof(*ctx)); if (ctx == NULL) { OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN, ERR_R_MALLOC_FAILURE); return NULL; } if ((st.st_mode & S_IFDIR) == S_IFDIR) { /* * Try to copy everything, even if we know that some of them must be * NULL for the moment. This prevents errors in the future, when more * components may be used. */ ctx->_.dir.uri = OPENSSL_strdup(uri); ctx->type = is_dir; if (ctx->_.dir.uri == NULL) goto err; ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx, path); ctx->_.dir.last_errno = errno; if (ctx->_.dir.last_entry == NULL) { if (ctx->_.dir.last_errno != 0) { char errbuf[256]; errno = ctx->_.dir.last_errno; openssl_strerror_r(errno, errbuf, sizeof(errbuf)); OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN, ERR_R_SYS_LIB); ERR_add_error_data(1, errbuf); goto err; } ctx->_.dir.end_reached = 1; } } else { BIO *buff = NULL; char peekbuf[4096] = { 0, }; if ((buff = BIO_new(BIO_f_buffer())) == NULL || (ctx->_.file.file = BIO_new_file(path, "rb")) == NULL) { BIO_free_all(buff); goto err; } ctx->_.file.file = BIO_push(buff, ctx->_.file.file); if (BIO_buffer_peek(ctx->_.file.file, peekbuf, sizeof(peekbuf) - 1) > 0) { peekbuf[sizeof(peekbuf) - 1] = '\0'; if (strstr(peekbuf, "-----BEGIN ") != NULL) ctx->type = is_pem; } } return ctx; err: OSSL_STORE_LOADER_CTX_free(ctx); return NULL; }
int main(int argc, char **argv) { CK_ULONG nslots; CK_SLOT_ID *pslots = NULL; CK_FUNCTION_LIST *funcs = NULL; CK_UTF8CHAR_PTR opt_pin = NULL; CK_ULONG opt_pin_len = 0; CK_RV rc; CK_ULONG opt_slot = -1; CK_SESSION_HANDLE h_session; char *opt_module = NULL, *opt_dir = NULL; /* struct sockaddr_un sockaddr; */ int long_optind = 0; int fd, verbose = 0; key_id_t *rsa_keys, *ec_keys; CK_ULONG rsa_len = 0, ec_len = 0, i; init_crypto(); while (1) { char c = getopt_long(argc, argv, "d:hp:s:m:v", options, &long_optind); if (c == -1) break; switch (c) { case 'd': opt_dir = optarg; break; case 'p': opt_pin = (CK_UTF8CHAR_PTR) strdup(optarg); if(opt_pin) { opt_pin_len = strlen(optarg); } break; case 's': opt_slot = (CK_SLOT_ID) atoi(optarg); break; case 'm': opt_module = optarg; break; case 'v': verbose = 1; break; case 'h': default: print_usage_and_die(app_name, options, option_help); } } rc = pkcs11_load_init(opt_module, opt_dir, stderr, &funcs); if (rc != CKR_OK) { return rc; } rc = pkcs11_get_slots(funcs, stderr, &pslots, &nslots); if (rc != CKR_OK) { return rc; } if(opt_slot == -1) { if(nslots < 1) { /* No slots */ return -1; } else { opt_slot = pslots[0]; } } else { /* Check selected slot is in pslots */ } fprintf(stderr, "Slot: %ld\n", opt_slot); rc = pkcs11_login_session(funcs, stderr, opt_slot, &h_session, CK_TRUE, CKU_USER, opt_pin, opt_pin_len); if (rc != CKR_OK) { show_error(stderr, "Login", rc); return rc; } load_keys(funcs, h_session, CKK_RSA, &rsa_keys, &rsa_len); load_keys(funcs, h_session, CKK_EC, &ec_keys, &ec_len); /* fd = nw_unix_server("pkcs11d.sock", &sockaddr, 0, 0, 0, 64); */ /* close(fd); */ fd = nw_tcp_server(1234, 0, 64); do { struct sockaddr address; socklen_t a_len = sizeof(address); int s = accept(fd, &address, &a_len); BIO *b = BIO_new_socket(s, BIO_NOCLOSE); BIO *buf = BIO_new(BIO_f_buffer()); b = BIO_push(buf, b); char buffer[4096], sig[4096], keyid[KEY_ID_SIZE + 1]; int l, slen = 0, plen = 0; CK_KEY_TYPE type; CK_ATTRIBUTE_TYPE operation; EVP_PKEY *pkey = NULL; l = BIO_gets(b, buffer, sizeof(buffer)); if(l <= 0) { fprintf(stderr, "Error reading query line\n"); goto end; } if(strncmp(buffer, "POST /sign/rsa/", 15) == 0) { memcpy(keyid, buffer + 15, KEY_ID_SIZE - 1); type = CKK_RSA; operation = CKA_SIGN; } else if(strncmp(buffer, "POST /decrypt/rsa/", 18) == 0) { memcpy(keyid, buffer + 18, KEY_ID_SIZE - 1); type = CKK_RSA; operation = CKA_DECRYPT; } else if(strncmp(buffer, "POST /sign/ec/", 14) == 0) { memcpy(keyid, buffer + 14, KEY_ID_SIZE - 1); type = CKK_EC; operation = CKA_SIGN; } else { goto end; } keyid[KEY_ID_SIZE] = '\0'; l = BIO_gets(b, buffer, sizeof(buffer)); if((l <= 0) || strncmp(buffer, "Content-Length: ", 16) != 0) { fprintf(stderr, "Invalid content length line = %s\n", buffer); goto end; } plen = atoi(buffer + 16); l = BIO_gets(b, buffer, sizeof(buffer)); l = BIO_read(b, buffer, plen); if(l < plen) { fprintf(stderr, "Error reading payload\n"); goto end; } if(type == CKK_RSA) { for(i = 0; (i < rsa_len) && (pkey == NULL); i++) { if(strncmp(rsa_keys[i].id, keyid, KEY_ID_SIZE - 1) == 0) { pkey = rsa_keys[i].key; } } } else if(type == CKK_EC) { for(i = 0; (i < ec_len) && (pkey == NULL); i++) { if(strncmp(ec_keys[i].id, keyid, KEY_ID_SIZE - 1) == 0) { pkey = ec_keys[i].key; } } } if(pkey == NULL) { fprintf(stderr, "Key not found\n"); goto end; } else if(verbose) { fprintf(stderr, "Key '%s'found\n", keyid); } if(type == CKK_RSA && operation == CKA_SIGN) { if(verbose) { fprintf(stderr, "RSA signature operation requested\n"); } l = RSA_private_encrypt(plen, (unsigned char *)buffer, (unsigned char *)sig, EVP_PKEY_get1_RSA(pkey), RSA_PKCS1_PADDING); } else if(type == CKK_RSA && operation == CKA_DECRYPT) { if(verbose) { fprintf(stderr, "RSA decryption operation requested\n"); } l = RSA_private_decrypt(plen, (unsigned char *)buffer, (unsigned char *)sig, EVP_PKEY_get1_RSA(pkey), RSA_PKCS1_PADDING); } else if (type == CKK_EC && operation == CKA_SIGN) { unsigned char *ptr = (unsigned char *)sig; ECDSA_SIG *s = ECDSA_do_sign((unsigned char *)buffer, plen, EVP_PKEY_get1_EC_KEY(pkey)); l = i2d_ECDSA_SIG(s, &ptr); ECDSA_SIG_free(s); } else { if(verbose) { fprintf(stderr, "Invalid operation requested\n"); } goto end; } slen = l; if(l <= 0) { if(verbose) { fprintf(stderr, "Error unsuccessful\n"); } goto end; } else if(verbose) { fprintf(stderr, "Operation successful\n"); } BIO_printf(b, "200 Ok\r\n"); BIO_printf(b, "Content-Length: %d\r\n\r\n", slen); l = BIO_write(b, sig, slen); BIO_flush(b); i= 0; /* for(i = 0; i < rsa_len; i++) { BIO_write(b, rsa_keys[i].id, KEY_ID_SIZE); BIO_write(b, "\n", 1); PEM_write_bio_RSAPrivateKey(b, EVP_PKEY_get1_RSA(rsa_keys[i].key), NULL, NULL, 0, NULL, NULL); } for(i = 0; i < ec_len; i++) { BIO_write(b, ec_keys[i].id, KEY_ID_SIZE); BIO_write(b, "\n", 1); PEM_write_bio_ECPrivateKey(b, EVP_PKEY_get1_EC_KEY(ec_keys[i].key), NULL, NULL, 0, NULL, NULL); } */ end: close(s); BIO_free(b); } while(1); close(fd); if(opt_pin) { funcs->C_CloseAllSessions(opt_slot); free(opt_pin); } rc = funcs->C_Finalize(NULL); if (rc != CKR_OK) { show_error(stderr, "C_Finalize", rc); return rc; } return rc; }
int do_starttls(enum APP_STARTTLS starttls, BIO *sbio, char *service, const char *hostname) { int rc = 0; char buffer[MYBUFSIZE], myhostname[MYBUFSIZE], param[MYBUFSIZE], *cp; int read_len; switch (starttls) { case STARTTLS_SMTP: { int seen_starttls = 0, reply_code = -1; BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); /* consume greeting (possibly multiline) & inspect reply code */ while (1) { read_len = BIO_gets(fbio, buffer, MYBUFSIZE); (void) sscanf(buffer, "%3d", &reply_code); if (debug) { cp = strstr(buffer, "\r\n"); *cp = '\0'; fprintf(stdout, "recv: %s\n", buffer); } if (read_len <= 3 || buffer[3] != '-') break; } if (reply_code != 220) { fprintf(stdout, "Invalid ESMTP greeting: %s\n", buffer); BIO_pop(fbio); BIO_free(fbio); return rc; } /* Send EHLO, read response, and look for STARTTLS parameter */ (void) gethostname(myhostname, MYBUFSIZE); if (debug) { fprintf(stdout, "send: EHLO %s\n", myhostname); } BIO_printf(fbio, "EHLO %s\r\n", myhostname); (void)BIO_flush(fbio); while (1) { read_len = BIO_gets(fbio, buffer, MYBUFSIZE); (void) sscanf(buffer, "%3d", &reply_code); (void) sscanf(buffer+4, "%255s", param); if (strcmp(param, "STARTTLS") == 0) seen_starttls = 1; if (debug) { cp = strstr(buffer, "\r\n"); *cp = '\0'; fprintf(stdout, "recv: %s\n", buffer); } if (read_len <= 3 || buffer[3] != '-') break; } BIO_pop(fbio); BIO_free(fbio); if (reply_code == 250 && seen_starttls) { /* send STARTTLS command and inspect reply code */ if (debug) { fprintf(stdout, "send: STARTTLS\n"); } BIO_printf(sbio, "STARTTLS\r\n"); BIO_read(sbio, buffer, MYBUFSIZE); if (debug) { cp = strstr(buffer, "\r\n"); *cp = '\0'; fprintf(stdout, "recv: %s\n", buffer); } (void) sscanf(buffer, "%3d", &reply_code); if (reply_code == 220) rc = 1; else fprintf(stdout, "Invalid response to STARTTLS: %s\n", buffer); } else if (reply_code != 250) { fprintf(stdout, "Invalid reply code to SMTP EHLO: %d\n", reply_code); } else { fprintf(stdout, "Unable to find STARTTLS in SMTP EHLO response.\n"); } break; } case STARTTLS_IMAP: { int seen_starttls = 0; BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); BIO_gets(fbio, buffer, MYBUFSIZE); if (debug) { cp = strstr(buffer, "\r\n"); *cp = '\0'; fprintf(stdout, "recv: %s\n", buffer); fprintf(stdout, "send: . CAPABILITY\n"); } BIO_printf(fbio, ". CAPABILITY\r\n"); (void) BIO_flush(fbio); while (1) { read_len = BIO_gets(fbio, buffer, MYBUFSIZE); if (debug) { cp = strstr(buffer, "\r\n"); *cp = '\0'; fprintf(stdout, "recv: %s\n", buffer); } if (strstr(buffer, "STARTTLS")) seen_starttls = 1; if (read_len <= 3 || buffer[0] == '.') break; } (void) BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); if (seen_starttls) { if (debug) { fprintf(stdout, "send: . STARTTLS\n"); } BIO_printf(sbio, ". STARTTLS\r\n"); BIO_read(sbio, buffer, MYBUFSIZE); if (debug) { cp = strstr(buffer, "\r\n"); *cp = '\0'; fprintf(stdout, "recv: %s\n", buffer); } if (strncmp(buffer, ". OK", 4) == 0) rc = 1; else fprintf(stdout, "ERROR: STARTTLS ready response failed.\n"); } else { fprintf(stdout, "ERROR: no STARTTLS capability found.\n"); } break; } case STARTTLS_POP3: { BIO_read(sbio, buffer, MYBUFSIZE); if (debug) { cp = strstr(buffer, "\r\n"); *cp = '\0'; fprintf(stdout, "recv: %s\n", buffer); fprintf(stdout, "send: STLS\n"); } BIO_printf(sbio, "STLS\r\n"); BIO_read(sbio, buffer, MYBUFSIZE); if (debug) { cp = strstr(buffer, "\r\n"); *cp = '\0'; fprintf(stdout, "recv: %s\n", buffer); } if (strncmp(buffer, "+OK", 3) == 0) rc = 1; else fprintf(stdout, "ERROR: Didn't get +OK in response to STARTTLS.\n"); break; } case STARTTLS_XMPP_CLIENT: case STARTTLS_XMPP_SERVER: { int readn, seen_starttls = 0; snprintf(buffer, sizeof(buffer), "<?xml version='1.0'?>" "<stream:stream " "to='%s' " "version='1.0' xml:lang='en' " "xmlns='jabber:%s' " "xmlns:stream='http://etherx.jabber.org/streams'>", service ? service : hostname, starttls == STARTTLS_XMPP_CLIENT ? "client" : "server"); if (debug) { fprintf(stdout, "send: %s\n", buffer); } BIO_printf(sbio, buffer); while (1) { readn = BIO_read(sbio, buffer, MYBUFSIZE); if (readn == 0) break; buffer[readn] = '\0'; if (debug) { fprintf(stdout, "recv: %s\n", buffer); } if (strstr(buffer, "<starttls xmlns") && strstr(buffer, "urn:ietf:params:xml:ns:xmpp-tls")) { seen_starttls = 1; break; } } if (!seen_starttls) fprintf(stdout, "Unable to find STARTTLS in XMPP response.\n"); else { snprintf(buffer, sizeof(buffer), "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); if (debug) { fprintf(stdout, "send: %s\n", buffer); } BIO_printf(sbio, buffer); readn = BIO_read(sbio, buffer, MYBUFSIZE); buffer[readn] = '\0'; if (debug) { fprintf(stdout, "recv: %s\n", buffer); } if (strstr(buffer, "<proceed")) rc = 1; } break; } default: fprintf(stdout, "STARTTLS application not implemented.\n"); break; } return rc; }
POP_SESSION *pop_set_socket(POP_SESSION *psp, int s, int opt) { if (s < 0) { return NULL; } if (psp == NULL && (psp = pop_session_create()) == NULL) { return NULL; } #ifdef WITH_OPENSSL if ((psp->bio = BIO_new_socket(s, BIO_NOCLOSE)) == NULL) { __pop_set_error_openssl(psp, "BIO_new_socket(): "); pop_session_destroy(psp); return NULL; } #ifdef ENABLE_SSL if (opt & POP_OPT_SSL) { SSL_CTX *ctxp; BIO *bio_ssl; if ((ctxp = SSL_CTX_new(SSLv23_client_method())) == NULL) { __pop_set_error_openssl(psp, "SSL_CTX_new(): "); pop_session_destroy(psp); return NULL; } if ((bio_ssl = BIO_new_ssl(ctxp, 1)) == NULL) { __pop_set_error_openssl(psp, "BIO_new_ssl(): "); pop_session_destroy(psp); return NULL; } BIO_push(bio_ssl, psp->bio); psp->bio = bio_ssl; BIO_do_handshake(psp->bio); } #endif /* ENABLE_SSL */ { BIO *bio_buffer; if ((bio_buffer = BIO_new(BIO_f_buffer())) == NULL) { __pop_set_error_openssl(psp, "BIO_new(): "); pop_session_destroy(psp); return NULL; } BIO_push(bio_buffer, psp->bio); psp->bio = bio_buffer; } #else /* WITH_OPENSSL */ if ((psp->sw = dup(s)) < 0) { __pop_set_error_errno(psp, "dup(s): "); pop_session_destroy(psp); return NULL; } if ((psp->fw = fdopen(psp->sw, "w")) == NULL) { __pop_set_error_errno(psp, "fdopen(fw): "); pop_session_destroy(psp); return NULL; } if ((psp->fr = fdopen(s, "r")) == NULL) { __pop_set_error_errno(psp, "fdopen(fr): "); pop_session_destroy(psp); return NULL; } psp->sr = s; #endif /* WITH_OPENSSL */ return psp; }
void ServiceTask::run() { //logger << dlib << endl; string ip = "invalid session"; string alldatlg = "\ngot fd from parent"; SSL *ssl=NULL; BIO *sbio=NULL; BIO *io=NULL,*ssl_bio=NULL; try { int cntlen = 0; char buf[MAXBUFLENM]; strVec results; stringstream ss; string temp; //int bytes = -1; if(isSSLEnabled) { sbio=BIO_new_socket(fd,BIO_NOCLOSE); ssl=SSL_new(ctx); SSL_set_bio(ssl,sbio,sbio); io=BIO_new(BIO_f_buffer()); ssl_bio=BIO_new(BIO_f_ssl()); BIO_set_ssl(ssl_bio,ssl,BIO_CLOSE); BIO_push(io,ssl_bio); int r = SSL_accept(ssl); cout << r << endl; int bser = SSL_get_error(ssl,r); cout << bser << endl; if(r<=0) { sslHandler.error_occurred((char*)"SSL accept error",fd,ssl); return; } int er=-1; bool flag = true; while(flag) { er = BIO_gets(io,buf,BUFSIZZ-1); cout << er << endl; int bser = SSL_get_error(ssl,er); cout << bser << endl; switch(bser) { case SSL_ERROR_WANT_READ: { logger << "more to read error" << endl; break; } case SSL_ERROR_WANT_WRITE: { logger << "more to write error" << endl; break; } case SSL_ERROR_NONE: { break; } case SSL_ERROR_ZERO_RETURN: { sslHandler.error_occurred((char*)"SSL error problem",fd,ssl); if(io!=NULL)BIO_free(io); return; } default: { sslHandler.error_occurred((char*)"SSL read problem",fd,ssl); if(io!=NULL)BIO_free(io); return; } } ss << buf; //logger <<buf <<endl; if(!strcmp(buf,"\r\n") || !strcmp(buf,"\n")) break; string temp(buf); if(temp=="")continue; temp = temp.substr(0,temp.length()-1); results.push_back(temp); //logger << temp <<endl; if(temp.find("Content-Length:")!=string::npos) { std::string cntle = temp.substr(temp.find(": ")+2); cntle = cntle.substr(0,cntle.length()-1); //logger << "contne-length="<<cntle <<endl; try { cntlen = CastUtil::lexical_cast<int>(cntle); } catch(const char* ex) { logger << "bad lexical cast" <<endl; } } memset(&buf[0], 0, sizeof(buf)); } } else { int er=-1; bool flag = true; sbio=BIO_new_socket(fd,BIO_CLOSE); io=BIO_new(BIO_f_buffer()); BIO_push(io,sbio); logger << "into run method" << endl; while(flag) { er = BIO_gets(io,buf,BUFSIZZ-1); if(er==0) { close(fd); logger << "\nsocket closed before being serviced" <<flush; return; } ss << buf; if(!strcmp(buf,"\r\n") || !strcmp(buf,"\n") || er<0) break; string temp(buf); temp = temp.substr(0,temp.length()-1); results.push_back(temp); //logger << temp <<endl; if(temp.find("Content-Length:")!=string::npos) { std::string cntle = temp.substr(temp.find(": ")+2); cntle = cntle.substr(0,cntle.length()-1); //logger << "contne-length="<<cntle <<endl; try { cntlen = CastUtil::lexical_cast<int>(cntle); } catch(const char* ex) { logger << "bad lexical cast" <<endl; } } memset(&buf[0], 0, sizeof(buf)); } } ss.clear(); if(isSSLEnabled && cntlen>0) { int er=-1; if(cntlen>0) { //logger << "reading conetnt " << cntlen << endl; er = BIO_read(io,buf,cntlen); switch(SSL_get_error(ssl,er)) { case SSL_ERROR_NONE: cntlen -= er; break; case SSL_ERROR_ZERO_RETURN: { sslHandler.error_occurred((char*)"SSL error problem",fd,ssl); if(io!=NULL)BIO_free(io); return; } default: { sslHandler.error_occurred((char*)"SSL read problem",fd,ssl); if(io!=NULL)BIO_free(io); return; } } string temp(buf); results.push_back("\r"); results.push_back(temp); //logger <<buf <<endl; memset(&buf[0], 0, sizeof(buf)); } } else if(cntlen>0) { int er=-1; if(cntlen>0) { //logger << "reading conetnt " << cntlen << endl; er = BIO_read(io,buf,cntlen); if(er==0) { close(fd); logger << "\nsocket closed before being serviced" <<flush; return; } else if(er>0) { string temp(buf); results.push_back("\r"); results.push_back(temp); //logger << temp <<endl; memset(&buf[0], 0, sizeof(buf)); } } } alldatlg += "--read data"; map<string,string> params1 = *params; string webpath = serverRootDirectory + "web/"; HttpRequest* req= new HttpRequest(results,webpath); //logger << req->toString() << endl; if(req->getFile()=="") { logger << req->getFile() << endl; req->setFile("index.html"); } if(req->hasCookie()) { logger << "has the session id" << endl; if(!configData.sessatserv) req->getSession()->setSessionAttributes(req->getCookieInfo()); else { string id = req->getCookieInfoAttribute("FFEADID"); logger << id << endl; map<string,string> values = readFromSharedMemeory(id); req->getSession()->setSessionAttributes(values); } } if(configData.cntMap[req->getCntxt_name()]!="true") { req->setCntxt_name("default"); req->setCntxt_root(webpath+"default"); req->setUrl(webpath+"default"+req->getActUrl()); } //logger << req->getCntxt_name() << req->getCntxt_root() << req->getUrl() << endl; if(configData.appMap[req->getCntxt_name()]!="false") { if(dlib == NULL) { cerr << dlerror() << endl; exit(-1); } string meth1 = (req->getCntxt_name()+"checkRules"); string path1; void *mkr1 = dlsym(dlib, meth1.c_str()); if(mkr1!=NULL) { typedef string (*DCPPtr1) (string,HttpSession); DCPPtr1 f = (DCPPtr1)mkr1; path1 = f(req->getUrl(),*(req->getSession())); //logger << path1 << flush; if(path1=="FAILED") { req->setUrl(""); } else if(path1!="" && path1!=req->getUrl()) { req->setUrl(path1); } } } HttpResponse res; string ext = getFileExtension(req->getUrl()); vector<unsigned char> test; string content; string claz; bool isoAuthRes = false; long sessionTimeoutVar = configData.sessionTimeout; bool isContrl = securityHandler.handle(configData.ip_address, req, res, configData.securityObjectMap, sessionTimeoutVar, dlib, configData.cntMap); filterHandler.handleIn(req, res, configData.filterMap, dlib, ext); if(!isContrl) { isContrl = authHandler.handle(configData.autMap, configData.autpattMap, req, res, configData.filterMap, dlib, ext); } string pthwofile = req->getCntxt_name()+req->getActUrl(); if(req->getCntxt_name()!="default" && configData.cntMap[req->getCntxt_name()]=="true") { pthwofile = req->getActUrl(); } if(!isContrl) { isContrl = controllerHandler.handle(req, res, configData.urlpattMap, configData.mappattMap, dlib, ext, configData.rstCntMap, configData.mapMap, configData.urlMap, pthwofile); } /*After going through the controller the response might be blank, just set the HTTP version*/ res.setHttpVersion(req->getHttpVersion()); //logger << req->toString() << endl; if(req->getMethod()!="TRACE") { if(isContrl) { } else if(ext==".form") { formHandler.handle(req, res, configData.formMap, dlib); } else if((req->getContent_type().find("application/soap+xml")!=string::npos || req->getContent_type().find("text/xml")!=string::npos) && (req->getContent().find("<soap:Envelope")!=string::npos || req->getContent().find("<soapenv:Envelope")!=string::npos) && configData.wsdlmap[req->getFile()]==req->getCntxt_name()) { soapHandler.handle(req, res, dlib, configData.props[".xml"]); } else { bool cntrlit = scriptHandler.handle(req, res, configData.handoffs, dlib, ext, configData.props); logger << "html page requested" <<endl; if(cntrlit) { } else { cntrlit = extHandler.handle(req, res, dlib, configData.resourcePath, configData.tmplMap, configData.vwMap, ext, configData.props); } if(!cntrlit && ext==".fview") { content = fviewHandler.handle(req, res, configData.fviewmap); } else { if(res.getContent_str()=="") content = getContentStr(req->getUrl(),configData.lprops[req->getDefaultLocale()],ext); else content = res.getContent_str(); } if(content.length()==0) { res.setStatusCode("404"); res.setStatusMsg("Not Found"); //res.setContent_len(CastUtil::lexical_cast<string>(0)); } else { res.setStatusCode("200"); res.setStatusMsg("OK"); if(res.getContent_type()=="")res.setContent_type(configData.props[ext]); res.setContent_str(content); //res.setContent_len(CastUtil::lexical_cast<string>(content.length())); //sess.setAttribute("CURR",req->getUrl()); } } filterHandler.handleOut(req, res, configData.filterMap, dlib, ext); } alldatlg += "--processed data"; string h1; bool sessionchanged = !req->hasCookie(); sessionchanged |= req->getSession()->isDirty(); if(req->getConnection()!="") res.setConnection("close"); createResponse(res,sessionchanged,req->getSession()->getSessionAttributes(),req->getCookieInfoAttribute("FFEADID"), sessionTimeoutVar, configData.sessatserv); //Head should behave exactly as Get but there should be no entity body if(req->getMethod()=="HEAD") { h1 = res.generateHeadResponse(); } else if(req->getMethod()=="OPTIONS") { h1 = res.generateOptionsResponse(); } else if(req->getMethod()=="TRACE") { h1 = res.generateTraceResponse(req); } else { h1 = res.generateResponse(); } //logger << h1 << endl; if(isSSLEnabled) { int r; /* Now perform renegotiation if requested */ if(configData.client_auth==CLIENT_AUTH_REHANDSHAKE){ SSL_set_verify(ssl,SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0); /* Stop the client from just resuming the un-authenticated session */ SSL_set_session_id_context(ssl, (const unsigned char*)&SSLHandler::s_server_auth_session_id_context, sizeof(SSLHandler::s_server_auth_session_id_context)); if(SSL_renegotiate(ssl)<=0) { sslHandler.error_occurred((char*)"SSL renegotiation error",fd,ssl); if(io!=NULL)BIO_free(io); return; } if(SSL_do_handshake(ssl)<=0) { sslHandler.error_occurred((char*)"SSL renegotiation error",fd,ssl); if(io!=NULL)BIO_free(io); return; } ssl->state=SSL_ST_ACCEPT; if(SSL_do_handshake(ssl)<=0) { sslHandler.error_occurred((char*)"SSL renegotiation error",fd,ssl); if(io!=NULL)BIO_free(io); return; } } if((r=BIO_puts(io,h1.c_str()))<=0) { sslHandler.error_occurred((char*)"send failed",fd,ssl); if(io!=NULL)BIO_free(io); return; } if((r=BIO_flush(io))<0) { sslHandler.error_occurred((char*)"Error flushing BIO",fd,ssl); if(io!=NULL)BIO_free(io); return; } sslHandler.closeSSL(fd,ssl,io); } else { int size; if ((size=send(fd,&h1[0] , h1.length(), 0)) == -1) logger << "send failed" << flush; else if(size==0) { close(fd); memset(&buf[0], 0, sizeof(buf)); logger << "socket closed for writing" << flush; return; } if(io!=NULL)BIO_free_all(io); } close(fd); memset(&buf[0], 0, sizeof(buf)); ss.clear(); //Logger::info("got new connection to process\n"+req->getFile()+" :: " + res.getStatusCode() + "\n"+req->getCntxt_name() + "\n"+req->getCntxt_root() + "\n"+req->getUrl()); delete req; logger << alldatlg << "--sent data--DONE" << flush; //sessionMap[sessId] = sess; } catch(...) { logger << "Standard exception: " << endl; } }
/****** * Everything starts here... ******/ int main(int argc, char **argv) { BIO *abio = NULL; BIO *biobuf = NULL; int rc = 0; if (rc = init(argc, argv, &cfg)) goto done; signal(SIGQUIT, SIGQUIThandler); /* We need a BIO to accept connections */ abio = BIO_new_accept(cfg->hostport); if (!abio) { fprintf(stderr, "Unable to create a new accept BIO.\n"); rc = -1; goto done; } BIO_set_bind_mode(abio, BIO_BIND_REUSEADDR); if ((rc = BIO_do_accept(abio)) <= 0) { fprintf(stderr, "Unable to accept connections.\n"); goto done; } /* And we add a buffer BIO that will be duplicated for each created * connections */ biobuf = BIO_new(BIO_f_buffer()); if (!biobuf) { fprintf(stderr, "Unable to create a buffer BIO.\n"); rc = -1; goto done; } BIO_set_accept_bios(abio, biobuf); /* Release all rights and go background */ if (!cfg->debug) { changeidentity(cfg->user, cfg->group); beadaemon(); } while (1) { BIO *cbio = NULL; /* This is a blocking call */ BIO_do_accept(abio); /* A connection has arrived, detach the corresponding BIO and * process the request */ cbio = BIO_pop(abio); processrequest(cbio); } done: BIO_free(abio); return rc; }
int s_client_main(int argc, char **argv) { unsigned int off = 0, clr = 0; SSL *con = NULL; int s, k, width, state = 0, af = AF_UNSPEC; char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL; int cbuf_len, cbuf_off; int sbuf_len, sbuf_off; fd_set readfds, writefds; char *port = PORT_STR; int full_log = 1; char *host = SSL_HOST_NAME; char *cert_file = NULL, *key_file = NULL; int cert_format = FORMAT_PEM, key_format = FORMAT_PEM; char *passarg = NULL, *pass = NULL; X509 *cert = NULL; EVP_PKEY *key = NULL; char *CApath = NULL, *CAfile = NULL, *cipher = NULL; int reconnect = 0, badop = 0, verify = SSL_VERIFY_NONE, bugs = 0; int crlf = 0; int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending; SSL_CTX *ctx = NULL; int ret = 1, in_init = 1, i, nbio_test = 0; int starttls_proto = PROTO_OFF; int prexit = 0; X509_VERIFY_PARAM *vpm = NULL; int badarg = 0; const SSL_METHOD *meth = NULL; int socket_type = SOCK_STREAM; BIO *sbio; int mbuf_len = 0; struct timeval timeout, *timeoutp; const char *errstr = NULL; #ifndef OPENSSL_NO_ENGINE char *engine_id = NULL; char *ssl_client_engine_id = NULL; ENGINE *ssl_client_engine = NULL; #endif ENGINE *e = NULL; #ifndef OPENSSL_NO_TLSEXT char *servername = NULL; tlsextctx tlsextcbp = {NULL, 0}; #ifndef OPENSSL_NO_NEXTPROTONEG const char *next_proto_neg_in = NULL; #endif #endif char *sess_in = NULL; char *sess_out = NULL; struct sockaddr peer; int peerlen = sizeof(peer); int enable_timeouts = 0; long socket_mtu = 0; meth = SSLv23_client_method(); c_Pause = 0; c_quiet = 0; c_ign_eof = 0; c_debug = 0; c_msg = 0; c_showcerts = 0; if (((cbuf = malloc(BUFSIZZ)) == NULL) || ((sbuf = malloc(BUFSIZZ)) == NULL) || ((mbuf = malloc(BUFSIZZ + 1)) == NULL)) { /* NUL byte */ BIO_printf(bio_err, "out of memory\n"); goto end; } verify_depth = 0; verify_error = X509_V_OK; c_nbio = 0; argc--; argv++; while (argc >= 1) { if (strcmp(*argv, "-host") == 0) { if (--argc < 1) goto bad; host = *(++argv); } else if (strcmp(*argv, "-port") == 0) { if (--argc < 1) goto bad; port = *(++argv); if (port == NULL || *port == '\0') goto bad; } else if (strcmp(*argv, "-connect") == 0) { if (--argc < 1) goto bad; if (!extract_host_port(*(++argv), &host, NULL, &port)) goto bad; } else if (strcmp(*argv, "-verify") == 0) { verify = SSL_VERIFY_PEER; if (--argc < 1) goto bad; verify_depth = strtonum(*(++argv), 0, INT_MAX, &errstr); if (errstr) goto bad; BIO_printf(bio_err, "verify depth is %d\n", verify_depth); } else if (strcmp(*argv, "-cert") == 0) { if (--argc < 1) goto bad; cert_file = *(++argv); } else if (strcmp(*argv, "-sess_out") == 0) { if (--argc < 1) goto bad; sess_out = *(++argv); } else if (strcmp(*argv, "-sess_in") == 0) { if (--argc < 1) goto bad; sess_in = *(++argv); } else if (strcmp(*argv, "-certform") == 0) { if (--argc < 1) goto bad; cert_format = str2fmt(*(++argv)); } else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) { if (badarg) goto bad; continue; } else if (strcmp(*argv, "-verify_return_error") == 0) verify_return_error = 1; else if (strcmp(*argv, "-prexit") == 0) prexit = 1; else if (strcmp(*argv, "-crlf") == 0) crlf = 1; else if (strcmp(*argv, "-quiet") == 0) { c_quiet = 1; c_ign_eof = 1; } else if (strcmp(*argv, "-ign_eof") == 0) c_ign_eof = 1; else if (strcmp(*argv, "-no_ign_eof") == 0) c_ign_eof = 0; else if (strcmp(*argv, "-pause") == 0) c_Pause = 1; else if (strcmp(*argv, "-debug") == 0) c_debug = 1; #ifndef OPENSSL_NO_TLSEXT else if (strcmp(*argv, "-tlsextdebug") == 0) c_tlsextdebug = 1; else if (strcmp(*argv, "-status") == 0) c_status_req = 1; #endif else if (strcmp(*argv, "-msg") == 0) c_msg = 1; else if (strcmp(*argv, "-showcerts") == 0) c_showcerts = 1; else if (strcmp(*argv, "-nbio_test") == 0) nbio_test = 1; else if (strcmp(*argv, "-state") == 0) state = 1; else if (strcmp(*argv, "-ssl3") == 0) meth = SSLv3_client_method(); else if (strcmp(*argv, "-tls1_2") == 0) meth = TLSv1_2_client_method(); else if (strcmp(*argv, "-tls1_1") == 0) meth = TLSv1_1_client_method(); else if (strcmp(*argv, "-tls1") == 0) meth = TLSv1_client_method(); #ifndef OPENSSL_NO_DTLS1 else if (strcmp(*argv, "-dtls1") == 0) { meth = DTLSv1_client_method(); socket_type = SOCK_DGRAM; } else if (strcmp(*argv, "-timeout") == 0) enable_timeouts = 1; else if (strcmp(*argv, "-mtu") == 0) { if (--argc < 1) goto bad; socket_mtu = strtonum(*(++argv), 0, LONG_MAX, &errstr); if (errstr) goto bad; } #endif else if (strcmp(*argv, "-bugs") == 0) bugs = 1; else if (strcmp(*argv, "-keyform") == 0) { if (--argc < 1) goto bad; key_format = str2fmt(*(++argv)); } else if (strcmp(*argv, "-pass") == 0) { if (--argc < 1) goto bad; passarg = *(++argv); } else if (strcmp(*argv, "-key") == 0) { if (--argc < 1) goto bad; key_file = *(++argv); } else if (strcmp(*argv, "-reconnect") == 0) { reconnect = 5; } else if (strcmp(*argv, "-CApath") == 0) { if (--argc < 1) goto bad; CApath = *(++argv); } else if (strcmp(*argv, "-CAfile") == 0) { if (--argc < 1) goto bad; CAfile = *(++argv); } else if (strcmp(*argv, "-no_tls1_2") == 0) off |= SSL_OP_NO_TLSv1_2; else if (strcmp(*argv, "-no_tls1_1") == 0) off |= SSL_OP_NO_TLSv1_1; else if (strcmp(*argv, "-no_tls1") == 0) off |= SSL_OP_NO_TLSv1; else if (strcmp(*argv, "-no_ssl3") == 0) off |= SSL_OP_NO_SSLv3; else if (strcmp(*argv, "-no_ssl2") == 0) off |= SSL_OP_NO_SSLv2; else if (strcmp(*argv, "-no_comp") == 0) { off |= SSL_OP_NO_COMPRESSION; } #ifndef OPENSSL_NO_TLSEXT else if (strcmp(*argv, "-no_ticket") == 0) { off |= SSL_OP_NO_TICKET; } #ifndef OPENSSL_NO_NEXTPROTONEG else if (strcmp(*argv, "-nextprotoneg") == 0) { if (--argc < 1) goto bad; next_proto_neg_in = *(++argv); } #endif #endif else if (strcmp(*argv, "-serverpref") == 0) off |= SSL_OP_CIPHER_SERVER_PREFERENCE; else if (strcmp(*argv, "-legacy_renegotiation") == 0) ; /* no-op */ else if (strcmp(*argv, "-legacy_server_connect") == 0) { off |= SSL_OP_LEGACY_SERVER_CONNECT; } else if (strcmp(*argv, "-no_legacy_server_connect") == 0) { clr |= SSL_OP_LEGACY_SERVER_CONNECT; } else if (strcmp(*argv, "-cipher") == 0) { if (--argc < 1) goto bad; cipher = *(++argv); } else if (strcmp(*argv, "-nbio") == 0) { c_nbio = 1; } else if (strcmp(*argv, "-starttls") == 0) { if (--argc < 1) goto bad; ++argv; if (strcmp(*argv, "smtp") == 0) starttls_proto = PROTO_SMTP; else if (strcmp(*argv, "lmtp") == 0) starttls_proto = PROTO_LMTP; else if (strcmp(*argv, "pop3") == 0) starttls_proto = PROTO_POP3; else if (strcmp(*argv, "imap") == 0) starttls_proto = PROTO_IMAP; else if (strcmp(*argv, "ftp") == 0) starttls_proto = PROTO_FTP; else if (strcmp(*argv, "xmpp") == 0) starttls_proto = PROTO_XMPP; else goto bad; } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv, "-engine") == 0) { if (--argc < 1) goto bad; engine_id = *(++argv); } else if (strcmp(*argv, "-ssl_client_engine") == 0) { if (--argc < 1) goto bad; ssl_client_engine_id = *(++argv); } #endif else if (strcmp(*argv, "-4") == 0) { af = AF_INET; } else if (strcmp(*argv, "-6") == 0) { af = AF_INET6; } #ifndef OPENSSL_NO_TLSEXT else if (strcmp(*argv, "-servername") == 0) { if (--argc < 1) goto bad; servername = *(++argv); /* meth=TLSv1_client_method(); */ } #endif #ifndef OPENSSL_NO_SRTP else if (strcmp(*argv, "-use_srtp") == 0) { if (--argc < 1) goto bad; srtp_profiles = *(++argv); } #endif else if (strcmp(*argv, "-keymatexport") == 0) { if (--argc < 1) goto bad; keymatexportlabel = *(++argv); } else if (strcmp(*argv, "-keymatexportlen") == 0) { const char *errstr; if (--argc < 1) goto bad; keymatexportlen = strtonum(*(++argv), 1, INT_MAX, &errstr); if (errstr) goto bad; } else { BIO_printf(bio_err, "unknown option %s\n", *argv); badop = 1; break; } argc--; argv++; } if (badop) { bad: if (errstr) BIO_printf(bio_err, "invalid argument %s: %s\n", *argv, errstr); else sc_usage(); goto end; } #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) next_proto.status = -1; if (next_proto_neg_in) { next_proto.data = next_protos_parse(&next_proto.len, next_proto_neg_in); if (next_proto.data == NULL) { BIO_printf(bio_err, "Error parsing -nextprotoneg argument\n"); goto end; } } else next_proto.data = NULL; #endif #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine_id, 1); if (ssl_client_engine_id) { ssl_client_engine = ENGINE_by_id(ssl_client_engine_id); if (!ssl_client_engine) { BIO_printf(bio_err, "Error getting client auth engine\n"); goto end; } } #endif if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (key_file == NULL) key_file = cert_file; if (key_file) { key = load_key(bio_err, key_file, key_format, 0, pass, e, "client certificate private key file"); if (!key) { ERR_print_errors(bio_err); goto end; } } if (cert_file) { cert = load_cert(bio_err, cert_file, cert_format, NULL, e, "client certificate file"); if (!cert) { ERR_print_errors(bio_err); goto end; } } if (bio_c_out == NULL) { if (c_quiet && !c_debug && !c_msg) { bio_c_out = BIO_new(BIO_s_null()); } else { if (bio_c_out == NULL) bio_c_out = BIO_new_fp(stdout, BIO_NOCLOSE); } } ctx = SSL_CTX_new(meth); if (ctx == NULL) { ERR_print_errors(bio_err); goto end; } if (vpm) SSL_CTX_set1_param(ctx, vpm); #ifndef OPENSSL_NO_ENGINE if (ssl_client_engine) { if (!SSL_CTX_set_client_cert_engine(ctx, ssl_client_engine)) { BIO_puts(bio_err, "Error setting client auth engine\n"); ERR_print_errors(bio_err); ENGINE_free(ssl_client_engine); goto end; } ENGINE_free(ssl_client_engine); } #endif #ifndef OPENSSL_NO_SRTP if (srtp_profiles != NULL) SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles); #endif if (bugs) SSL_CTX_set_options(ctx, SSL_OP_ALL | off); else SSL_CTX_set_options(ctx, off); if (clr) SSL_CTX_clear_options(ctx, clr); /* * DTLS: partial reads end up discarding unread UDP bytes :-( Setting * read ahead solves this problem. */ if (socket_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) if (next_proto.data) SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto); #endif if (state) SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback); if (cipher != NULL) if (!SSL_CTX_set_cipher_list(ctx, cipher)) { BIO_printf(bio_err, "error setting cipher list\n"); ERR_print_errors(bio_err); goto end; } SSL_CTX_set_verify(ctx, verify, verify_callback); if (!set_cert_key_stuff(ctx, cert, key)) goto end; if ((!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) || (!SSL_CTX_set_default_verify_paths(ctx))) { /* * BIO_printf(bio_err,"error setting default verify * locations\n"); */ ERR_print_errors(bio_err); /* goto end; */ } #ifndef OPENSSL_NO_TLSEXT if (servername != NULL) { tlsextcbp.biodebug = bio_err; SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp); } #endif con = SSL_new(ctx); if (sess_in) { SSL_SESSION *sess; BIO *stmp = BIO_new_file(sess_in, "r"); if (!stmp) { BIO_printf(bio_err, "Can't open session file %s\n", sess_in); ERR_print_errors(bio_err); goto end; } sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL); BIO_free(stmp); if (!sess) { BIO_printf(bio_err, "Can't open session file %s\n", sess_in); ERR_print_errors(bio_err); goto end; } SSL_set_session(con, sess); SSL_SESSION_free(sess); } #ifndef OPENSSL_NO_TLSEXT if (servername != NULL) { if (!SSL_set_tlsext_host_name(con, servername)) { BIO_printf(bio_err, "Unable to set TLS servername extension.\n"); ERR_print_errors(bio_err); goto end; } } #endif /* SSL_set_cipher_list(con,"RC4-MD5"); */ re_start: if (init_client(&s, host, port, socket_type, af) == 0) { BIO_printf(bio_err, "connect:errno=%d\n", errno); shutdown(s, SHUT_RD); close(s); goto end; } BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s); if (c_nbio) { unsigned long l = 1; BIO_printf(bio_c_out, "turning on non blocking io\n"); if (BIO_socket_ioctl(s, FIONBIO, &l) < 0) { ERR_print_errors(bio_err); goto end; } } if (c_Pause & 0x01) SSL_set_debug(con, 1); if (SSL_version(con) == DTLS1_VERSION) { sbio = BIO_new_dgram(s, BIO_NOCLOSE); if (getsockname(s, &peer, (void *) &peerlen) < 0) { BIO_printf(bio_err, "getsockname:errno=%d\n", errno); shutdown(s, SHUT_RD); close(s); goto end; } (void) BIO_ctrl_set_connected(sbio, 1, &peer); if (enable_timeouts) { timeout.tv_sec = 0; timeout.tv_usec = DGRAM_RCV_TIMEOUT; BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); timeout.tv_sec = 0; timeout.tv_usec = DGRAM_SND_TIMEOUT; BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); } if (socket_mtu > 28) { SSL_set_options(con, SSL_OP_NO_QUERY_MTU); SSL_set_mtu(con, socket_mtu - 28); } else /* want to do MTU discovery */ BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); } else sbio = BIO_new_socket(s, BIO_NOCLOSE); if (nbio_test) { BIO *test; test = BIO_new(BIO_f_nbio_test()); sbio = BIO_push(test, sbio); } if (c_debug) { SSL_set_debug(con, 1); BIO_set_callback(sbio, bio_dump_callback); BIO_set_callback_arg(sbio, (char *) bio_c_out); } if (c_msg) { SSL_set_msg_callback(con, msg_cb); SSL_set_msg_callback_arg(con, bio_c_out); } #ifndef OPENSSL_NO_TLSEXT if (c_tlsextdebug) { SSL_set_tlsext_debug_callback(con, tlsext_cb); SSL_set_tlsext_debug_arg(con, bio_c_out); } if (c_status_req) { SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp); SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb); SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out); } #endif SSL_set_bio(con, sbio, sbio); SSL_set_connect_state(con); /* ok, lets connect */ width = SSL_get_fd(con) + 1; read_tty = 1; write_tty = 0; tty_on = 0; read_ssl = 1; write_ssl = 1; cbuf_len = 0; cbuf_off = 0; sbuf_len = 0; sbuf_off = 0; /* This is an ugly hack that does a lot of assumptions */ /* * We do have to handle multi-line responses which may come in a * single packet or not. We therefore have to use BIO_gets() which * does need a buffering BIO. So during the initial chitchat we do * push a buffering BIO into the chain that is removed again later on * to not disturb the rest of the s_client operation. */ if (starttls_proto == PROTO_SMTP || starttls_proto == PROTO_LMTP) { int foundit = 0; BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); /* wait for multi-line response to end from SMTP */ do { mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); } while (mbuf_len > 3 && mbuf[3] == '-'); /* STARTTLS command requires EHLO... */ BIO_printf(fbio, "%cHLO openssl.client.net\r\n", starttls_proto == PROTO_SMTP ? 'E' : 'L'); (void) BIO_flush(fbio); /* wait for multi-line response to end EHLO SMTP response */ do { mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); if (strstr(mbuf, "STARTTLS")) foundit = 1; } while (mbuf_len > 3 && mbuf[3] == '-'); (void) BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); if (!foundit) BIO_printf(bio_err, "didn't found starttls in server response," " try anyway...\n"); BIO_printf(sbio, "STARTTLS\r\n"); BIO_read(sbio, sbuf, BUFSIZZ); } else if (starttls_proto == PROTO_POP3) { mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ); if (mbuf_len == -1) { BIO_printf(bio_err, "BIO_read failed\n"); goto end; } BIO_printf(sbio, "STLS\r\n"); BIO_read(sbio, sbuf, BUFSIZZ); } else if (starttls_proto == PROTO_IMAP) { int foundit = 0; BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); BIO_gets(fbio, mbuf, BUFSIZZ); /* STARTTLS command requires CAPABILITY... */ BIO_printf(fbio, ". CAPABILITY\r\n"); (void) BIO_flush(fbio); /* wait for multi-line CAPABILITY response */ do { mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); if (strstr(mbuf, "STARTTLS")) foundit = 1; } while (mbuf_len > 3 && mbuf[0] != '.'); (void) BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); if (!foundit) BIO_printf(bio_err, "didn't found STARTTLS in server response," " try anyway...\n"); BIO_printf(sbio, ". STARTTLS\r\n"); BIO_read(sbio, sbuf, BUFSIZZ); } else if (starttls_proto == PROTO_FTP) { BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); /* wait for multi-line response to end from FTP */ do { mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); } while (mbuf_len > 3 && mbuf[3] == '-'); (void) BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); BIO_printf(sbio, "AUTH TLS\r\n"); BIO_read(sbio, sbuf, BUFSIZZ); } if (starttls_proto == PROTO_XMPP) { int seen = 0; BIO_printf(sbio, "<stream:stream " "xmlns:stream='http://etherx.jabber.org/streams' " "xmlns='jabber:client' to='%s' version='1.0'>", host); seen = BIO_read(sbio, mbuf, BUFSIZZ); mbuf[seen] = 0; while (!strstr(mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'")) { if (strstr(mbuf, "/stream:features>")) goto shut; seen = BIO_read(sbio, mbuf, BUFSIZZ); mbuf[seen] = 0; } BIO_printf(sbio, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); seen = BIO_read(sbio, sbuf, BUFSIZZ); sbuf[seen] = 0; if (!strstr(sbuf, "<proceed")) goto shut; mbuf[0] = 0; } for (;;) { FD_ZERO(&readfds); FD_ZERO(&writefds); if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_get_timeout(con, &timeout)) timeoutp = &timeout; else timeoutp = NULL; if (SSL_in_init(con) && !SSL_total_renegotiations(con)) { in_init = 1; tty_on = 0; } else { tty_on = 1; if (in_init) { in_init = 0; if (sess_out) { BIO *stmp = BIO_new_file(sess_out, "w"); if (stmp) { PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con)); BIO_free(stmp); } else BIO_printf(bio_err, "Error writing session file %s\n", sess_out); } print_stuff(bio_c_out, con, full_log); if (full_log > 0) full_log--; if (starttls_proto) { BIO_write(bio_err, mbuf, mbuf_len); /* We don't need to know any more */ starttls_proto = PROTO_OFF; } if (reconnect) { reconnect--; BIO_printf(bio_c_out, "drop connection and then reconnect\n"); SSL_shutdown(con); SSL_set_connect_state(con); shutdown(SSL_get_fd(con), SHUT_RD); close(SSL_get_fd(con)); goto re_start; } } } ssl_pending = read_ssl && SSL_pending(con); /* XXX should add tests for fd_set overflow */ if (!ssl_pending) { if (tty_on) { if (read_tty) FD_SET(fileno(stdin), &readfds); if (write_tty) FD_SET(fileno(stdout), &writefds); } if (read_ssl) FD_SET(SSL_get_fd(con), &readfds); if (write_ssl) FD_SET(SSL_get_fd(con), &writefds); /* printf("mode tty(%d %d%d) ssl(%d%d)\n", tty_on,read_tty,write_tty,read_ssl,write_ssl);*/ i = select(width, &readfds, &writefds, NULL, timeoutp); if (i < 0) { BIO_printf(bio_err, "bad select %d\n", errno); goto shut; /* goto end; */ } } if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_handle_timeout(con) > 0) { BIO_printf(bio_err, "TIMEOUT occured\n"); } if (!ssl_pending && FD_ISSET(SSL_get_fd(con), &writefds)) { k = SSL_write(con, &(cbuf[cbuf_off]), (unsigned int) cbuf_len); switch (SSL_get_error(con, k)) { case SSL_ERROR_NONE: cbuf_off += k; cbuf_len -= k; if (k <= 0) goto end; /* we have done a write(con,NULL,0); */ if (cbuf_len <= 0) { read_tty = 1; write_ssl = 0; } else { /* if (cbuf_len > 0) */ read_tty = 0; write_ssl = 1; } break; case SSL_ERROR_WANT_WRITE: BIO_printf(bio_c_out, "write W BLOCK\n"); write_ssl = 1; read_tty = 0; break; case SSL_ERROR_WANT_READ: BIO_printf(bio_c_out, "write R BLOCK\n"); write_tty = 0; read_ssl = 1; write_ssl = 0; break; case SSL_ERROR_WANT_X509_LOOKUP: BIO_printf(bio_c_out, "write X BLOCK\n"); break; case SSL_ERROR_ZERO_RETURN: if (cbuf_len != 0) { BIO_printf(bio_c_out, "shutdown\n"); ret = 0; goto shut; } else { read_tty = 1; write_ssl = 0; break; } case SSL_ERROR_SYSCALL: if ((k != 0) || (cbuf_len != 0)) { BIO_printf(bio_err, "write:errno=%d\n", errno); goto shut; } else { read_tty = 1; write_ssl = 0; } break; case SSL_ERROR_SSL: ERR_print_errors(bio_err); goto shut; } } else if (!ssl_pending && FD_ISSET(fileno(stdout), &writefds)) { i = write(fileno(stdout), &(sbuf[sbuf_off]), sbuf_len); if (i <= 0) { BIO_printf(bio_c_out, "DONE\n"); ret = 0; goto shut; /* goto end; */ } sbuf_len -= i; sbuf_off += i; if (sbuf_len <= 0) { read_ssl = 1; write_tty = 0; } } else if (ssl_pending || FD_ISSET(SSL_get_fd(con), &readfds)) { #ifdef RENEG { static int iiii; if (++iiii == 52) { SSL_renegotiate(con); iiii = 0; } } #endif k = SSL_read(con, sbuf, 1024 /* BUFSIZZ */ ); switch (SSL_get_error(con, k)) { case SSL_ERROR_NONE: if (k <= 0) goto end; sbuf_off = 0; sbuf_len = k; read_ssl = 0; write_tty = 1; break; case SSL_ERROR_WANT_WRITE: BIO_printf(bio_c_out, "read W BLOCK\n"); write_ssl = 1; read_tty = 0; break; case SSL_ERROR_WANT_READ: BIO_printf(bio_c_out, "read R BLOCK\n"); write_tty = 0; read_ssl = 1; if ((read_tty == 0) && (write_ssl == 0)) write_ssl = 1; break; case SSL_ERROR_WANT_X509_LOOKUP: BIO_printf(bio_c_out, "read X BLOCK\n"); break; case SSL_ERROR_SYSCALL: ret = errno; BIO_printf(bio_err, "read:errno=%d\n", ret); goto shut; case SSL_ERROR_ZERO_RETURN: BIO_printf(bio_c_out, "closed\n"); ret = 0; goto shut; case SSL_ERROR_SSL: ERR_print_errors(bio_err); goto shut; /* break; */ } } else if (FD_ISSET(fileno(stdin), &readfds)) { if (crlf) { int j, lf_num; i = read(fileno(stdin), cbuf, BUFSIZZ / 2); lf_num = 0; /* both loops are skipped when i <= 0 */ for (j = 0; j < i; j++) if (cbuf[j] == '\n') lf_num++; for (j = i - 1; j >= 0; j--) { cbuf[j + lf_num] = cbuf[j]; if (cbuf[j] == '\n') { lf_num--; i++; cbuf[j + lf_num] = '\r'; } } assert(lf_num == 0); } else i = read(fileno(stdin), cbuf, BUFSIZZ); if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q'))) { BIO_printf(bio_err, "DONE\n"); ret = 0; goto shut; } if ((!c_ign_eof) && (cbuf[0] == 'R')) { BIO_printf(bio_err, "RENEGOTIATING\n"); SSL_renegotiate(con); cbuf_len = 0; } else { cbuf_len = i; cbuf_off = 0; } write_ssl = 1; read_tty = 0; } } ret = 0; shut: if (in_init) print_stuff(bio_c_out, con, full_log); SSL_shutdown(con); shutdown(SSL_get_fd(con), SHUT_RD); close(SSL_get_fd(con)); end: if (con != NULL) { if (prexit != 0) print_stuff(bio_c_out, con, 1); SSL_free(con); } #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) free(next_proto.data); #endif if (ctx != NULL) SSL_CTX_free(ctx); if (cert) X509_free(cert); if (key) EVP_PKEY_free(key); free(pass); if (vpm) X509_VERIFY_PARAM_free(vpm); if (cbuf != NULL) { OPENSSL_cleanse(cbuf, BUFSIZZ); free(cbuf); } if (sbuf != NULL) { OPENSSL_cleanse(sbuf, BUFSIZZ); free(sbuf); } if (mbuf != NULL) { OPENSSL_cleanse(mbuf, BUFSIZZ); free(mbuf); } if (bio_c_out != NULL) { BIO_free(bio_c_out); bio_c_out = NULL; } return (ret); }
HybridSslConnection* hybrid_ssl_connect_with_fd(gint sk, ssl_callback func, gpointer user_data) { gint l; SSL *ssl; BIO *sbio; BIO *buf_io; BIO *ssl_bio; SSL_CTX *ssl_ctx; HybridSslConnection *ssl_conn; SSL_load_error_strings(); SSL_library_init(); if (!(ssl_ctx = SSL_CTX_new(TLSv1_client_method()))) { hybrid_debug_error("ssl", "initialize SSL CTX: %s", ERR_reason_error_string(ERR_get_error())); return NULL; } if (!(ssl = ssl_new_with_certs(ssl_ctx))) { return NULL; } if (!SSL_set_fd(ssl, sk)) { hybrid_debug_error("ssl", "add ssl to tcp socket:%s", ERR_reason_error_string(ERR_get_error())); return NULL; } sbio = BIO_new(BIO_s_socket()); BIO_set_fd(sbio, sk, BIO_NOCLOSE); SSL_set_bio(ssl, sbio, sbio); SSL_set_connect_state(ssl); reconnect: l = SSL_connect(ssl); switch (SSL_get_error(ssl, l)) { case SSL_ERROR_NONE: goto ssl_conn_sk_ok; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: usleep(100); goto reconnect; case SSL_ERROR_SYSCALL: case SSL_ERROR_WANT_X509_LOOKUP: case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_SSL: default: hybrid_debug_error("ssl", "ssl hand-shake error:%s", ERR_reason_error_string(ERR_get_error())); return NULL; } ssl_conn_sk_ok: if (HYBRID_OK != ssl_verify_certs(ssl)) { return NULL; } SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); buf_io = BIO_new(BIO_f_buffer()); ssl_bio = BIO_new(BIO_f_ssl()); BIO_set_ssl(ssl_bio, ssl, BIO_NOCLOSE); BIO_push(buf_io, ssl_bio); ssl_conn = g_new0(HybridSslConnection, 1); ssl_conn->sk = sk; ssl_conn->ssl = ssl; ssl_conn->ssl_ctx = ssl_ctx; ssl_conn->conn_cb = func; ssl_conn->conn_data = user_data; ssl_conn->rbio = buf_io; ssl_conn->wbio = sbio; if (func) { func(ssl_conn, user_data); } return ssl_conn; }
static LUA_FUNCTION(openssl_bio_new_filter) { /* 0 1 2 3 4 5 */ static const char* sType[] = {"base64", "buffer", "cipher", "md", "ssl", NULL}; int type = luaL_checkoption(L, 1, NULL, sType); BIO* bio = NULL; int ret = 1; int closeflag = 0; switch (type) { case 0: bio = BIO_new(BIO_f_base64()); break; case 1: bio = BIO_new(BIO_f_buffer()); break; case 2: { const EVP_CIPHER* c = get_cipher(L, 2, NULL); size_t kl, il; const char* k = luaL_checklstring(L, 3, &kl); const char* v = luaL_checklstring(L, 4, &il); int encrypt = auxiliar_checkboolean(L, 5); bio = BIO_new(BIO_f_cipher()); BIO_set_cipher(bio, c, (const unsigned char*)k, (const unsigned char*)v, encrypt); } break; case 3: { const EVP_MD* md = get_digest(L, 2); bio = BIO_new(BIO_f_md()); ret = BIO_set_md(bio, md); } case 4: { SSL* ssl = CHECK_OBJECT(2, SSL, "openssl.ssl"); closeflag = luaL_checkoption(L, 3, "noclose", close_flags); bio = BIO_new(BIO_f_ssl()); ret = BIO_set_ssl(bio, ssl, closeflag); } break; default: ret = 0; } if (ret == 1 && bio) { PUSH_OBJECT(bio, "openssl.bio"); if (closeflag) { openssl_newvalue(L, bio); lua_pushboolean(L, 1); openssl_setvalue(L, bio, "free_all"); } return 1; } else { if (bio) BIO_free(bio); return openssl_pushresult(L, ret); } return 0; }
void* sqlhandler(void *arg) { char sql[MAX_MSG]; int ret, err; SSL *ssl; sqlite4_stmt *pStmt; struct conn_ctx *conn = (struct conn_ctx *)arg; struct freeq_ctx *freeqctx = conn->srvctx->freeqctx; BIO *client = conn->client; if (!(ssl = freeq_ssl_new(freeqctx))) { err(freeqctx, "couldn't allocate new ssl instance"); BIO_free_all(client); free(conn); pthread_exit(NULL); } SSL_set_bio(ssl, client, client); if (SSL_accept(ssl) <= 0) { int_error("Error accepting SSL connection"); BIO_free_all(client); free(conn); pthread_exit(NULL); } if ((err = post_connection_check(freeqctx, ssl, "localhost")) != X509_V_OK) { err(freeqctx, "error: peer certificate: %s\n", X509_verify_cert_error_string(err)); BIO_free_all(client); free(conn); pthread_exit(NULL); } BIO *b, *ssl_bio; b = BIO_new(BIO_f_buffer()); ssl_bio = BIO_new(BIO_f_ssl()); BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE); BIO_push(b, ssl_bio); memset(sql, 0, MAX_MSG); ret = BIO_gets(b, sql, MAX_MSG); ret = sqlite4_prepare(pDb, sql, strlen(sql), &pStmt, 0); if (ret != SQLITE4_OK) { dbg(freeqctx, "prepare failed for %s sending error, ret was %d\n", sql, ret); //freeq_error_write_sock(freeqctx, sqlite4_errmsg(pDb), b); dbg(freeqctx, sqlite4_errmsg(pDb)); //BIO_printf(b, "error: %s\n", sqlite4_errmsg(pDb)); sqlite4_finalize(pStmt); //pthread_exit(FREEQ_ERR); } freeq_sqlite_to_bio(freeqctx, b, pStmt); SSL_shutdown(ssl); SSL_free(ssl); BIO_free_all(client); free(conn); pthread_exit(FREEQ_OK); }
string Client::getTextData(string hdrdelm,string cntlnhdr) { int er=-1; bool flag = true; string alldat; int cntlen; char buf[MAXBUFLE]; BIO* sbio=BIO_new_socket(sockfd,BIO_NOCLOSE); BIO* io=BIO_new(BIO_f_buffer()); BIO_push(io,sbio); while(flag) { er = BIO_gets(io,buf,MAXBUFLE-1); if(er==0) { if(io!=NULL)BIO_free_all(io); //logger << "\nsocket closed before being serviced" <<flush; return alldat; } if(!strcmp(buf,hdrdelm.c_str())) { string tt(buf, er); alldat += tt; break; } string temp(buf, er); temp = temp.substr(0,temp.length()-1); alldat += (temp + "\n"); if(temp.find(cntlnhdr)!=string::npos) { std::string cntle = temp.substr(temp.find(": ")+2); cntle = cntle.substr(0,cntle.length()-1); try { cntlen = CastUtil::lexical_cast<int>(cntle); } catch(...) { logger << "bad lexical cast" <<endl; } } memset(&buf[0], 0, sizeof(buf)); } while(cntlen>0) { //logger << "reading conetnt " << cntlen; int toRead = cntlen; if(cntlen>MAXBUFLE) toRead = MAXBUFLE - 1; er = BIO_read(io,buf,toRead); if(er==0) { if(io!=NULL)BIO_free_all(io); //logger << "\nsocket closed before being serviced" <<flush; return alldat; } string temp(buf, er); alldat += temp; cntlen -= er; memset(&buf[0], 0, sizeof(buf)); } return alldat; }
/* Return value: * SSL_OK: the SSL handle is created * SSL_ERROR: failed, call ossSSLERRGetError() & ossSSLERRGetErrorMessage() for reason */ INT32 ossSSLNewHandle(SSLHandle** handle, SSLContext* ctx, SOCKET sock, const char* initialBytes, INT32 len) { SSLHandle* h = NULL; SSL* ssl = NULL; BIO* bufferBIO = NULL; BIO* socketBIO = NULL; INT32 ret = SSL_OK; SSL_ASSERT(NULL != handle); SSL_ASSERT(NULL != ctx); SSL_ASSERT(len >= 0); h = (SSLHandle*)OPENSSL_malloc(sizeof(SSLHandle)); if (NULL == h) { goto error; } _SSLHandleInit(h); h->sock = sock; ssl = SSL_new(ctx); if (NULL == ssl) { goto error; } h->ssl = ssl; if (0 == len) { /* there is no initial bytes, so we just set the socket to SSL */ ret = SSL_set_fd(ssl, sock); if (!ret) { goto error; } } else /* len > 0 */ { SSL_ASSERT(NULL != initialBytes); /* * There are initial SSL bytes, so we should give these bytes to SSL by some way. * Here we create a buffer BIO, and put these bytes to it. * Then we create a socket BIO, and set a BIO chain to link * the buffer and socket by BIO_push(). * Finally, we set the buffer to SSL instead of the socket. * * NOTE: when do SSL operations, it should explicitly flush the buffer. */ bufferBIO = BIO_new(BIO_f_buffer()); if (NULL == bufferBIO) { goto error; } ret = BIO_set_buffer_read_data(bufferBIO, (void*)initialBytes, len); if (!ret) { goto error; } socketBIO = BIO_new_socket(sock, BIO_NOCLOSE); if (NULL == socketBIO) { goto error; } /* link socket to the buffer */ if (NULL == BIO_push(bufferBIO, socketBIO)) { goto error; } /* SSL_free() will also free bufferBIO, * so it's no need to free bufferBIO later when free the SSL handle. */ SSL_set_bio(ssl, bufferBIO, bufferBIO); /* hold the bufferBIO pointer so we can flush it when do SSL operations */ h->bufferBIO = bufferBIO; } *handle = h; ret = SDB_OK; done: return ret; error: if (NULL != bufferBIO) { BIO_free(bufferBIO); } if (NULL != socketBIO) { BIO_free(socketBIO); } if (NULL != ssl) { SSL_free(ssl); } if (NULL != h) { OPENSSL_free(h); } ret = SSL_ERROR; goto done; }
int MAIN(int argc, char **argv) { int off=0; SSL *con=NULL,*con2=NULL; X509_STORE *store = NULL; int s,k,width,state=0; char *cbuf=NULL,*sbuf=NULL,*mbuf=NULL; int cbuf_len,cbuf_off; int sbuf_len,sbuf_off; fd_set readfds,writefds; short port=PORT; int full_log=1; char *host=SSL_HOST_NAME; char *cert_file=NULL,*key_file=NULL; int cert_format = FORMAT_PEM, key_format = FORMAT_PEM; char *passarg = NULL, *pass = NULL; X509 *cert = NULL; EVP_PKEY *key = NULL; char *CApath=NULL,*CAfile=NULL,*cipher=NULL; int reconnect=0,badop=0,verify=SSL_VERIFY_NONE,bugs=0; int crlf=0; int write_tty,read_tty,write_ssl,read_ssl,tty_on,ssl_pending; SSL_CTX *ctx=NULL; int ret=1,in_init=1,i,nbio_test=0; int starttls_proto = PROTO_OFF; int prexit = 0, vflags = 0; SSL_METHOD *meth=NULL; #ifdef sock_type #undef sock_type #endif int sock_type=SOCK_STREAM; BIO *sbio; char *inrand=NULL; int mbuf_len=0; #ifndef OPENSSL_NO_ENGINE char *engine_id=NULL; ENGINE *e=NULL; #endif #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) struct timeval tv; #endif struct sockaddr peer; int peerlen = sizeof(peer); int enable_timeouts = 0 ; long mtu = 0; #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) meth=SSLv23_client_method(); #elif !defined(OPENSSL_NO_SSL3) meth=SSLv3_client_method(); #elif !defined(OPENSSL_NO_SSL2) meth=SSLv2_client_method(); #endif apps_startup(); c_Pause=0; c_quiet=0; c_ign_eof=0; c_debug=0; c_msg=0; c_showcerts=0; if (bio_err == NULL) bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); if (!load_config(bio_err, NULL)) goto end; if ( ((cbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) || ((sbuf=OPENSSL_malloc(BUFSIZZ)) == NULL) || ((mbuf=OPENSSL_malloc(BUFSIZZ)) == NULL)) { BIO_printf(bio_err,"out of memory\n"); goto end; } verify_depth=0; verify_error=X509_V_OK; #ifdef FIONBIO c_nbio=0; #endif argc--; argv++; while (argc >= 1) { if (strcmp(*argv,"-host") == 0) { if (--argc < 1) goto bad; host= *(++argv); } else if (strcmp(*argv,"-port") == 0) { if (--argc < 1) goto bad; port=atoi(*(++argv)); if (port == 0) goto bad; } else if (strcmp(*argv,"-connect") == 0) { if (--argc < 1) goto bad; if (!extract_host_port(*(++argv),&host,NULL,&port)) goto bad; } else if (strcmp(*argv,"-verify") == 0) { verify=SSL_VERIFY_PEER; if (--argc < 1) goto bad; verify_depth=atoi(*(++argv)); BIO_printf(bio_err,"verify depth is %d\n",verify_depth); } else if (strcmp(*argv,"-cert") == 0) { if (--argc < 1) goto bad; cert_file= *(++argv); } else if (strcmp(*argv,"-certform") == 0) { if (--argc < 1) goto bad; cert_format = str2fmt(*(++argv)); } else if (strcmp(*argv,"-crl_check") == 0) vflags |= X509_V_FLAG_CRL_CHECK; else if (strcmp(*argv,"-crl_check_all") == 0) vflags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL; else if (strcmp(*argv,"-prexit") == 0) prexit=1; else if (strcmp(*argv,"-crlf") == 0) crlf=1; else if (strcmp(*argv,"-quiet") == 0) { c_quiet=1; c_ign_eof=1; } else if (strcmp(*argv,"-ign_eof") == 0) c_ign_eof=1; else if (strcmp(*argv,"-pause") == 0) c_Pause=1; else if (strcmp(*argv,"-debug") == 0) c_debug=1; #ifdef WATT32 else if (strcmp(*argv,"-wdebug") == 0) dbug_init(); #endif else if (strcmp(*argv,"-msg") == 0) c_msg=1; else if (strcmp(*argv,"-showcerts") == 0) c_showcerts=1; else if (strcmp(*argv,"-nbio_test") == 0) nbio_test=1; else if (strcmp(*argv,"-state") == 0) state=1; #ifndef OPENSSL_NO_SSL2 else if (strcmp(*argv,"-ssl2") == 0) meth=SSLv2_client_method(); #endif #ifndef OPENSSL_NO_SSL3 else if (strcmp(*argv,"-ssl3") == 0) meth=SSLv3_client_method(); #endif #ifndef OPENSSL_NO_TLS1 else if (strcmp(*argv,"-tls1") == 0) meth=TLSv1_client_method(); #endif #ifndef OPENSSL_NO_DTLS1 else if (strcmp(*argv,"-dtls1") == 0) { meth=DTLSv1_client_method(); sock_type=SOCK_DGRAM; } else if (strcmp(*argv,"-timeout") == 0) enable_timeouts=1; else if (strcmp(*argv,"-mtu") == 0) { if (--argc < 1) goto bad; mtu = atol(*(++argv)); } #endif else if (strcmp(*argv,"-bugs") == 0) bugs=1; else if (strcmp(*argv,"-keyform") == 0) { if (--argc < 1) goto bad; key_format = str2fmt(*(++argv)); } else if (strcmp(*argv,"-pass") == 0) { if (--argc < 1) goto bad; passarg = *(++argv); } else if (strcmp(*argv,"-key") == 0) { if (--argc < 1) goto bad; key_file= *(++argv); } else if (strcmp(*argv,"-reconnect") == 0) { reconnect=5; } else if (strcmp(*argv,"-CApath") == 0) { if (--argc < 1) goto bad; CApath= *(++argv); } else if (strcmp(*argv,"-CAfile") == 0) { if (--argc < 1) goto bad; CAfile= *(++argv); } else if (strcmp(*argv,"-no_tls1") == 0) off|=SSL_OP_NO_TLSv1; else if (strcmp(*argv,"-no_ssl3") == 0) off|=SSL_OP_NO_SSLv3; else if (strcmp(*argv,"-no_ssl2") == 0) off|=SSL_OP_NO_SSLv2; else if (strcmp(*argv,"-serverpref") == 0) off|=SSL_OP_CIPHER_SERVER_PREFERENCE; else if (strcmp(*argv,"-cipher") == 0) { if (--argc < 1) goto bad; cipher= *(++argv); } #ifdef FIONBIO else if (strcmp(*argv,"-nbio") == 0) { c_nbio=1; } #endif else if (strcmp(*argv,"-starttls") == 0) { if (--argc < 1) goto bad; ++argv; if (strcmp(*argv,"smtp") == 0) starttls_proto = PROTO_SMTP; else if (strcmp(*argv,"pop3") == 0) starttls_proto = PROTO_POP3; else if (strcmp(*argv,"imap") == 0) starttls_proto = PROTO_IMAP; else if (strcmp(*argv,"ftp") == 0) starttls_proto = PROTO_FTP; else goto bad; } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) goto bad; engine_id = *(++argv); } #endif else if (strcmp(*argv,"-rand") == 0) { if (--argc < 1) goto bad; inrand= *(++argv); } else { BIO_printf(bio_err,"unknown option %s\n",*argv); badop=1; break; } argc--; argv++; } if (badop) { bad: sc_usage(); goto end; } OpenSSL_add_ssl_algorithms(); SSL_load_error_strings(); #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine_id, 1); #endif if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (key_file == NULL) key_file = cert_file; if (key_file) { key = load_key(bio_err, key_file, key_format, 0, pass, e, "client certificate private key file"); if (!key) { ERR_print_errors(bio_err); goto end; } } if (cert_file) { cert = load_cert(bio_err,cert_file,cert_format, NULL, e, "client certificate file"); if (!cert) { ERR_print_errors(bio_err); goto end; } } if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL && !RAND_status()) { BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n"); } if (inrand != NULL) BIO_printf(bio_err,"%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); if (bio_c_out == NULL) { if (c_quiet && !c_debug && !c_msg) { bio_c_out=BIO_new(BIO_s_null()); } else { if (bio_c_out == NULL) bio_c_out=BIO_new_fp(stdout,BIO_NOCLOSE); } } ctx=SSL_CTX_new(meth); if (ctx == NULL) { ERR_print_errors(bio_err); goto end; } if (bugs) SSL_CTX_set_options(ctx,SSL_OP_ALL|off); else SSL_CTX_set_options(ctx,off); /* DTLS: partial reads end up discarding unread UDP bytes :-( * Setting read ahead solves this problem. */ if (sock_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1); if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback); if (cipher != NULL) if(!SSL_CTX_set_cipher_list(ctx,cipher)) { BIO_printf(bio_err,"error setting cipher list\n"); ERR_print_errors(bio_err); goto end; } #if 0 else SSL_CTX_set_cipher_list(ctx,getenv("SSL_CIPHER")); #endif SSL_CTX_set_verify(ctx,verify,verify_callback); if (!set_cert_key_stuff(ctx,cert,key)) goto end; if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) || (!SSL_CTX_set_default_verify_paths(ctx))) { /* BIO_printf(bio_err,"error setting default verify locations\n"); */ ERR_print_errors(bio_err); /* goto end; */ } store = SSL_CTX_get_cert_store(ctx); X509_STORE_set_flags(store, vflags); con=SSL_new(ctx); #ifndef OPENSSL_NO_KRB5 if (con && (con->kssl_ctx = kssl_ctx_new()) != NULL) { kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVER, host); } #endif /* OPENSSL_NO_KRB5 */ /* SSL_set_cipher_list(con,"RC4-MD5"); */ re_start: if (init_client(&s,host,port,sock_type) == 0) { BIO_printf(bio_err,"connect:errno=%d\n",get_last_socket_error()); SHUTDOWN(s); goto end; } BIO_printf(bio_c_out,"CONNECTED(%08X)\n",s); #ifdef FIONBIO if (c_nbio) { unsigned long l=1; BIO_printf(bio_c_out,"turning on non blocking io\n"); if (BIO_socket_ioctl(s,FIONBIO,&l) < 0) { ERR_print_errors(bio_err); goto end; } } #endif if (c_Pause & 0x01) con->debug=1; if ( SSL_version(con) == DTLS1_VERSION) { struct timeval timeout; sbio=BIO_new_dgram(s,BIO_NOCLOSE); if (getsockname(s, &peer, (void *)&peerlen) < 0) { BIO_printf(bio_err, "getsockname:errno=%d\n", get_last_socket_error()); SHUTDOWN(s); goto end; } (void)BIO_ctrl_set_connected(sbio, 1, &peer); if ( enable_timeouts) { timeout.tv_sec = 0; timeout.tv_usec = DGRAM_RCV_TIMEOUT; BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); timeout.tv_sec = 0; timeout.tv_usec = DGRAM_SND_TIMEOUT; BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout); } if ( mtu > 0) { SSL_set_options(con, SSL_OP_NO_QUERY_MTU); SSL_set_mtu(con, mtu); } else /* want to do MTU discovery */ BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); } else sbio=BIO_new_socket(s,BIO_NOCLOSE); if (nbio_test) { BIO *test; test=BIO_new(BIO_f_nbio_test()); sbio=BIO_push(test,sbio); } if (c_debug) { con->debug=1; BIO_set_callback(sbio,bio_dump_callback); BIO_set_callback_arg(sbio,(char *)bio_c_out); } if (c_msg) { SSL_set_msg_callback(con, msg_cb); SSL_set_msg_callback_arg(con, bio_c_out); } SSL_set_bio(con,sbio,sbio); SSL_set_connect_state(con); /* ok, lets connect */ width=SSL_get_fd(con)+1; read_tty=1; write_tty=0; tty_on=0; read_ssl=1; write_ssl=1; cbuf_len=0; cbuf_off=0; sbuf_len=0; sbuf_off=0; /* This is an ugly hack that does a lot of assumptions */ /* We do have to handle multi-line responses which may come in a single packet or not. We therefore have to use BIO_gets() which does need a buffering BIO. So during the initial chitchat we do push a buffering BIO into the chain that is removed again later on to not disturb the rest of the s_client operation. */ if (starttls_proto == PROTO_SMTP) { int foundit=0; BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); /* wait for multi-line response to end from SMTP */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); } while (mbuf_len>3 && mbuf[3]=='-'); /* STARTTLS command requires EHLO... */ BIO_printf(fbio,"EHLO openssl.client.net\r\n"); (void)BIO_flush(fbio); /* wait for multi-line response to end EHLO SMTP response */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); if (strstr(mbuf,"STARTTLS")) foundit=1; } while (mbuf_len>3 && mbuf[3]=='-'); (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); if (!foundit) BIO_printf(bio_err, "didn't found starttls in server response," " try anyway...\n"); BIO_printf(sbio,"STARTTLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } else if (starttls_proto == PROTO_POP3) { BIO_read(sbio,mbuf,BUFSIZZ); BIO_printf(sbio,"STLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } else if (starttls_proto == PROTO_IMAP) { int foundit=0; BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); BIO_gets(fbio,mbuf,BUFSIZZ); /* STARTTLS command requires CAPABILITY... */ BIO_printf(fbio,". CAPABILITY\r\n"); (void)BIO_flush(fbio); /* wait for multi-line CAPABILITY response */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); if (strstr(mbuf,"STARTTLS")) foundit=1; } while (mbuf_len>3 && mbuf[0]!='.'); (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); if (!foundit) BIO_printf(bio_err, "didn't found STARTTLS in server response," " try anyway...\n"); BIO_printf(sbio,". STARTTLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } else if (starttls_proto == PROTO_FTP) { BIO *fbio = BIO_new(BIO_f_buffer()); BIO_push(fbio, sbio); /* wait for multi-line response to end from FTP */ do { mbuf_len = BIO_gets(fbio,mbuf,BUFSIZZ); } while (mbuf_len>3 && mbuf[3]=='-'); (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); BIO_printf(sbio,"AUTH TLS\r\n"); BIO_read(sbio,sbuf,BUFSIZZ); } for (;;) { FD_ZERO(&readfds); FD_ZERO(&writefds); if (SSL_in_init(con) && !SSL_total_renegotiations(con)) { in_init=1; tty_on=0; } else { tty_on=1; if (in_init) { in_init=0; print_stuff(bio_c_out,con,full_log); if (full_log > 0) full_log--; if (starttls_proto) { BIO_printf(bio_err,"%s",mbuf); /* We don't need to know any more */ starttls_proto = PROTO_OFF; } if (reconnect) { reconnect--; BIO_printf(bio_c_out,"drop connection and then reconnect\n"); SSL_shutdown(con); SSL_set_connect_state(con); SHUTDOWN(SSL_get_fd(con)); goto re_start; } } } ssl_pending = read_ssl && SSL_pending(con); if (!ssl_pending) { #if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_NETWARE) if (tty_on) { if (read_tty) FD_SET(fileno(stdin),&readfds); if (write_tty) FD_SET(fileno(stdout),&writefds); } if (read_ssl) FD_SET(SSL_get_fd(con),&readfds); if (write_ssl) FD_SET(SSL_get_fd(con),&writefds); #else if(!tty_on || !write_tty) { if (read_ssl) FD_SET(SSL_get_fd(con),&readfds); if (write_ssl) FD_SET(SSL_get_fd(con),&writefds); } #endif /* printf("mode tty(%d %d%d) ssl(%d%d)\n", tty_on,read_tty,write_tty,read_ssl,write_ssl);*/ /* Note: under VMS with SOCKETSHR the second parameter * is currently of type (int *) whereas under other * systems it is (void *) if you don't have a cast it * will choke the compiler: if you do have a cast then * you can either go for (int *) or (void *). */ #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) /* Under Windows/DOS we make the assumption that we can * always write to the tty: therefore if we need to * write to the tty we just fall through. Otherwise * we timeout the select every second and see if there * are any keypresses. Note: this is a hack, in a proper * Windows application we wouldn't do this. */ i=0; if(!write_tty) { if(read_tty) { tv.tv_sec = 1; tv.tv_usec = 0; i=select(width,(void *)&readfds,(void *)&writefds, NULL,&tv); #if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) if(!i && (!_kbhit() || !read_tty) ) continue; #else if(!i && (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || !read_tty) ) continue; #endif } else i=select(width,(void *)&readfds,(void *)&writefds, NULL,NULL); } #elif defined(OPENSSL_SYS_NETWARE) if(!write_tty) { if(read_tty) { tv.tv_sec = 1; tv.tv_usec = 0; i=select(width,(void *)&readfds,(void *)&writefds, NULL,&tv); } else i=select(width,(void *)&readfds,(void *)&writefds, NULL,NULL); } #else i=select(width,(void *)&readfds,(void *)&writefds, NULL,NULL); #endif if ( i < 0) { BIO_printf(bio_err,"bad select %d\n", get_last_socket_error()); goto shut; /* goto end; */ } } if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds)) { k=SSL_write(con,&(cbuf[cbuf_off]), (unsigned int)cbuf_len); switch (SSL_get_error(con,k)) { case SSL_ERROR_NONE: cbuf_off+=k; cbuf_len-=k; if (k <= 0) goto end; /* we have done a write(con,NULL,0); */ if (cbuf_len <= 0) { read_tty=1; write_ssl=0; } else /* if (cbuf_len > 0) */ { read_tty=0; write_ssl=1; } break; case SSL_ERROR_WANT_WRITE: BIO_printf(bio_c_out,"write W BLOCK\n"); write_ssl=1; read_tty=0; break; case SSL_ERROR_WANT_READ: BIO_printf(bio_c_out,"write R BLOCK\n"); write_tty=0; read_ssl=1; write_ssl=0; break; case SSL_ERROR_WANT_X509_LOOKUP: BIO_printf(bio_c_out,"write X BLOCK\n"); break; case SSL_ERROR_ZERO_RETURN: if (cbuf_len != 0) { BIO_printf(bio_c_out,"shutdown\n"); goto shut; } else { read_tty=1; write_ssl=0; break; } case SSL_ERROR_SYSCALL: if ((k != 0) || (cbuf_len != 0)) { BIO_printf(bio_err,"write:errno=%d\n", get_last_socket_error()); goto shut; } else { read_tty=1; write_ssl=0; } break; case SSL_ERROR_SSL: ERR_print_errors(bio_err); goto shut; } } #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) /* Assume Windows/DOS can always write */ else if (!ssl_pending && write_tty) #else else if (!ssl_pending && FD_ISSET(fileno(stdout),&writefds)) #endif { #ifdef CHARSET_EBCDIC ascii2ebcdic(&(sbuf[sbuf_off]),&(sbuf[sbuf_off]),sbuf_len); #endif i=write(fileno(stdout),&(sbuf[sbuf_off]),sbuf_len); if (i <= 0) { BIO_printf(bio_c_out,"DONE\n"); goto shut; /* goto end; */ } sbuf_len-=i;; sbuf_off+=i; if (sbuf_len <= 0) { read_ssl=1; write_tty=0; } } else if (ssl_pending || FD_ISSET(SSL_get_fd(con),&readfds)) { #ifdef RENEG { static int iiii; if (++iiii == 52) { SSL_renegotiate(con); iiii=0; } } #endif #if 1 k=SSL_read(con,sbuf,1024 /* BUFSIZZ */ ); #else /* Demo for pending and peek :-) */ k=SSL_read(con,sbuf,16); { char zbuf[10240]; printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240)); } #endif switch (SSL_get_error(con,k)) { case SSL_ERROR_NONE: if (k <= 0) goto end; sbuf_off=0; sbuf_len=k; read_ssl=0; write_tty=1; break; case SSL_ERROR_WANT_WRITE: BIO_printf(bio_c_out,"read W BLOCK\n"); write_ssl=1; read_tty=0; break; case SSL_ERROR_WANT_READ: BIO_printf(bio_c_out,"read R BLOCK\n"); write_tty=0; read_ssl=1; if ((read_tty == 0) && (write_ssl == 0)) write_ssl=1; break; case SSL_ERROR_WANT_X509_LOOKUP: BIO_printf(bio_c_out,"read X BLOCK\n"); break; case SSL_ERROR_SYSCALL: BIO_printf(bio_err,"read:errno=%d\n",get_last_socket_error()); goto shut; case SSL_ERROR_ZERO_RETURN: BIO_printf(bio_c_out,"closed\n"); goto shut; case SSL_ERROR_SSL: ERR_print_errors(bio_err); goto shut; /* break; */ } } #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) #if defined(OPENSSL_SYS_WINCE) || defined(OPENSSL_SYS_MSDOS) else if (_kbhit()) #else else if ((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) #endif #elif defined (OPENSSL_SYS_NETWARE) else if (_kbhit()) #else else if (FD_ISSET(fileno(stdin),&readfds)) #endif { if (crlf) { int j, lf_num; i=read(fileno(stdin),cbuf,BUFSIZZ/2); lf_num = 0; /* both loops are skipped when i <= 0 */ for (j = 0; j < i; j++) if (cbuf[j] == '\n') lf_num++; for (j = i-1; j >= 0; j--) { cbuf[j+lf_num] = cbuf[j]; if (cbuf[j] == '\n') { lf_num--; i++; cbuf[j+lf_num] = '\r'; } } assert(lf_num == 0); } else i=read(fileno(stdin),cbuf,BUFSIZZ); if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q'))) { BIO_printf(bio_err,"DONE\n"); goto shut; } if ((!c_ign_eof) && (cbuf[0] == 'R')) { BIO_printf(bio_err,"RENEGOTIATING\n"); SSL_renegotiate(con); cbuf_len=0; } else { cbuf_len=i; cbuf_off=0; #ifdef CHARSET_EBCDIC ebcdic2ascii(cbuf, cbuf, i); #endif } write_ssl=1; read_tty=0; } } shut: SSL_shutdown(con); SHUTDOWN(SSL_get_fd(con)); ret=0; end: if(prexit) print_stuff(bio_c_out,con,1); if (con != NULL) SSL_free(con); if (con2 != NULL) SSL_free(con2); if (ctx != NULL) SSL_CTX_free(ctx); if (cert) X509_free(cert); if (key) EVP_PKEY_free(key); if (pass) OPENSSL_free(pass); if (cbuf != NULL) { OPENSSL_cleanse(cbuf,BUFSIZZ); OPENSSL_free(cbuf); } if (sbuf != NULL) { OPENSSL_cleanse(sbuf,BUFSIZZ); OPENSSL_free(sbuf); } if (mbuf != NULL) { OPENSSL_cleanse(mbuf,BUFSIZZ); OPENSSL_free(mbuf); } if (bio_c_out != NULL) { BIO_free(bio_c_out); bio_c_out=NULL; } apps_shutdown(); OPENSSL_EXIT(ret); }
static int http_serve(SSL *ssl, int s) { char buf[BUFSIZZ]; int r,len; BIO *io,*ssl_bio; io=BIO_new(BIO_f_buffer()); ssl_bio=BIO_new(BIO_f_ssl()); BIO_set_ssl(ssl_bio,ssl,BIO_CLOSE); BIO_push(io,ssl_bio); r=BIO_gets(io,buf,BUFSIZZ-1); switch(SSL_get_error(ssl,r)){ case SSL_ERROR_NONE: len=r; break; default: berr_exit("SSL read problem"); } char *saveptr; char resource[512] = {'\0'}; char *token = strtok_r(buf, " ", &saveptr); if (token && strcasecmp(token, "GET") == 0) { token = strtok_r(NULL, " ", &saveptr); if (token) { strncpy(resource, token, sizeof(resource)); } } if (resource[0]) { while(1){ r=BIO_gets(io,buf,BUFSIZZ-1); switch(SSL_get_error(ssl,r)){ case SSL_ERROR_NONE: len=r; break; default: berr_exit("SSL read problem"); } /* Look for the blank line that signals the end of the HTTP headers */ if(!strcmp(buf,"\r\n") || !strcmp(buf,"\n")) break; } } if (strcasecmp(resource, "/ciphersuites.txt") == 0) { http_serve_headers(io, 200, "OK", "text/plain"); print_ciphersuite_data(io, ssl, 0); } else if (strcasecmp(resource, "/ciphersuites.js") == 0) { long protocol = SSL_version(ssl); http_serve_headers(io, 200, "OK", "text/javascript"); if(BIO_printf(io, "$(function() {\n insert_text('%s', '", get_protocol_name(protocol)) <= 0) err_exit("Write error"); print_ciphersuite_data(io, ssl, 1); if(BIO_printf(io, "');\n});") <= 0) err_exit("Write error"); } else { http_serve_headers(io, 404, "Not Found", "text/plain"); if(BIO_puts(io, "Not found.") <= 0) err_exit("Write error"); } if((r=BIO_flush(io))<0) err_exit("Error flushing BIO"); r=SSL_shutdown(ssl); if(!r){ /* If we called SSL_shutdown() first then we always get return value of '0'. In this case, try again, but first send a TCP FIN to trigger the other side's close_notify*/ shutdown(s,1); r=SSL_shutdown(ssl); } switch(r){ case 1: break; /* Success */ case 0: case -1: default: berr_exit("Shutdown failed"); } SSL_free(ssl); close(s); return(0); }