int main(int count, char *strings[]) { FILE * fp; clock_t begin, end; double time_spent; SSL_CTX *ctx; int server,i=0; SSL *ssl; char buf[1024]; int bytes; char *hostname, *portnum; while (i<86400) { begin = clock(); //start time measurement - harith if ( count != 3 ) { printf("usage: %s <hostname> <portnum>\n", strings[0]); exit(0); } SSL_library_init(); hostname=strings[1]; portnum=strings[2]; ctx = InitCTX(); server = OpenConnection(hostname, atoi(portnum)); ssl = SSL_new(ctx); /* create new SSL connection state */ SSL_set_fd(ssl, server); /* attach the socket descriptor */ if ( SSL_connect(ssl) == FAIL ) /* perform the connection */ ERR_print_errors_fp(stderr); else { char *msg = "Hello???"; printf("Connected with %s encryption\n", SSL_get_cipher(ssl)); ShowCerts(ssl); /* get any certs */ SSL_write(ssl, msg, strlen(msg)); /* encrypt & send message */ bytes = SSL_read(ssl, buf, sizeof(buf)); /* get reply & decrypt */ buf[bytes] = 0; printf("Received: \"%s\"\n\n", buf); SSL_free(ssl); /* release connection state */ } close(server); /* close socket */ SSL_CTX_free(ctx); /* release context */ end = clock(); // stop time measurement -- harith time_spent = (double)(end - begin) / CLOCKS_PER_SEC * 1000; //printf("Total execution time is: %f \n", time_spent); //reset time begin = 0; end = 0; fp = fopen( "logfile.txt", "a" ); // Open file for writing fprintf(fp, "Sequence %d, Time taken: %f ms \r\n",i,time_spent); fclose(fp); i++; sleep(1); } return 0; }
int s_time_main(int argc, char **argv) { char buf[1024 * 8]; SSL *scon = NULL; SSL_CTX *ctx = NULL; const SSL_METHOD *meth = NULL; char *CApath = NULL, *CAfile = NULL, *cipher = NULL, *www_path = NULL; char *host = SSL_CONNECT_NAME, *certfile = NULL, *keyfile = NULL, *prog; double totalTime = 0.0; int noCApath = 0, noCAfile = 0; int maxtime = SECONDS, nConn = 0, perform = 3, ret = 1, i, st_bugs = 0, ver; long bytes_read = 0, finishtime = 0; OPTION_CHOICE o; meth = TLS_client_method(); verify_depth = 0; verify_error = X509_V_OK; prog = opt_init(argc, argv, s_time_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(s_time_options); ret = 0; goto end; case OPT_CONNECT: host = opt_arg(); break; case OPT_REUSE: perform = 2; break; case OPT_NEW: perform = 1; break; case OPT_VERIFY: if (!opt_int(opt_arg(), &verify_depth)) goto opthelp; BIO_printf(bio_err, "%s: verify depth is %d\n", prog, verify_depth); break; case OPT_CERT: certfile = opt_arg(); break; case OPT_KEY: keyfile = opt_arg(); break; case OPT_CAPATH: CApath = opt_arg(); break; case OPT_CAFILE: CAfile = opt_arg(); break; case OPT_NOCAPATH: noCApath = 1; break; case OPT_NOCAFILE: noCAfile = 1; break; case OPT_CIPHER: cipher = opt_arg(); break; case OPT_BUGS: st_bugs = 1; break; case OPT_TIME: if (!opt_int(opt_arg(), &maxtime)) goto opthelp; break; case OPT_WWW: www_path = opt_arg(); if (strlen(www_path) > MYBUFSIZ - 100) { BIO_printf(bio_err, "%s: -www option too long\n", prog); goto end; } break; case OPT_SSL3: #ifndef OPENSSL_NO_SSL3 meth = SSLv3_client_method(); #endif break; } } argc = opt_num_rest(); if (argc != 0) goto opthelp; if (cipher == NULL) cipher = getenv("SSL_CIPHER"); if (cipher == NULL) { BIO_printf(bio_err, "No CIPHER specified\n"); goto end; } if ((ctx = SSL_CTX_new(meth)) == NULL) goto end; SSL_CTX_set_quiet_shutdown(ctx, 1); if (st_bugs) SSL_CTX_set_options(ctx, SSL_OP_ALL); if (!SSL_CTX_set_cipher_list(ctx, cipher)) goto end; if (!set_cert_stuff(ctx, certfile, keyfile)) goto end; if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) { ERR_print_errors(bio_err); goto end; } if (!(perform & 1)) goto next; printf("Collecting connection statistics for %d seconds\n", maxtime); /* Loop and time how long it takes to make connections */ bytes_read = 0; finishtime = (long)time(NULL) + maxtime; tm_Time_F(START); for (;;) { if (finishtime < (long)time(NULL)) break; if ((scon = doConnection(NULL, host, ctx)) == NULL) goto end; if (www_path != NULL) { BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n", www_path); if (SSL_write(scon, buf, strlen(buf)) <= 0) goto end; while ((i = SSL_read(scon, buf, sizeof(buf))) > 0) bytes_read += i; } #ifdef NO_SHUTDOWN SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); #else SSL_shutdown(scon); #endif SHUTDOWN2(SSL_get_fd(scon)); nConn += 1; if (SSL_session_reused(scon)) ver = 'r'; else { ver = SSL_version(scon); if (ver == TLS1_VERSION) ver = 't'; else if (ver == SSL3_VERSION) ver = '3'; else ver = '*'; } fputc(ver, stdout); fflush(stdout); SSL_free(scon); scon = NULL; } totalTime += tm_Time_F(STOP); /* Add the time for this iteration */ i = (int)((long)time(NULL) - finishtime + maxtime); printf ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double)nConn / totalTime), bytes_read); printf ("%d connections in %ld real seconds, %ld bytes read per connection\n", nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn); /* * Now loop and time connections using the same session id over and over */ next: if (!(perform & 2)) goto end; printf("\n\nNow timing with session id reuse.\n"); /* Get an SSL object so we can reuse the session id */ if ((scon = doConnection(NULL, host, ctx)) == NULL) { BIO_printf(bio_err, "Unable to get connection\n"); goto end; } if (www_path != NULL) { BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n", www_path); if (SSL_write(scon, buf, strlen(buf)) <= 0) goto end; while (SSL_read(scon, buf, sizeof(buf)) > 0) continue; } #ifdef NO_SHUTDOWN SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); #else SSL_shutdown(scon); #endif SHUTDOWN2(SSL_get_fd(scon)); nConn = 0; totalTime = 0.0; finishtime = (long)time(NULL) + maxtime; printf("starting\n"); bytes_read = 0; tm_Time_F(START); for (;;) { if (finishtime < (long)time(NULL)) break; if ((doConnection(scon, host, ctx)) == NULL) goto end; if (www_path) { BIO_snprintf(buf, sizeof buf, "GET %s HTTP/1.0\r\n\r\n", www_path); if (SSL_write(scon, buf, strlen(buf)) <= 0) goto end; while ((i = SSL_read(scon, buf, sizeof(buf))) > 0) bytes_read += i; } #ifdef NO_SHUTDOWN SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); #else SSL_shutdown(scon); #endif SHUTDOWN2(SSL_get_fd(scon)); nConn += 1; if (SSL_session_reused(scon)) ver = 'r'; else { ver = SSL_version(scon); if (ver == TLS1_VERSION) ver = 't'; else if (ver == SSL3_VERSION) ver = '3'; else ver = '*'; } fputc(ver, stdout); fflush(stdout); } totalTime += tm_Time_F(STOP); /* Add the time for this iteration */ printf ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double)nConn / totalTime), bytes_read); printf ("%d connections in %ld real seconds, %ld bytes read per connection\n", nConn, (long)time(NULL) - finishtime + maxtime, bytes_read / nConn); ret = 0; end: SSL_free(scon); SSL_CTX_free(ctx); return (ret); }
static void do_reneg_setup_step(const SSL_TEST_CTX *test_ctx, PEER *peer) { int ret; char buf; TEST_check(peer->status == PEER_RETRY); TEST_check(test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_SERVER || test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_CLIENT); /* Check if we are the peer that is going to initiate */ if ((test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_SERVER && SSL_is_server(peer->ssl)) || (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_CLIENT && !SSL_is_server(peer->ssl))) { /* * If we already asked for a renegotiation then fall through to the * SSL_read() below. */ if (!SSL_renegotiate_pending(peer->ssl)) { /* * If we are the client we will always attempt to resume the * session. The server may or may not resume dependant on the * setting of SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION */ if (SSL_is_server(peer->ssl)) ret = SSL_renegotiate(peer->ssl); else ret = SSL_renegotiate_abbreviated(peer->ssl); if (!ret) { peer->status = PEER_ERROR; return; } do_handshake_step(peer); /* * If status is PEER_RETRY it means we're waiting on the peer to * continue the handshake. As far as setting up the renegotiation is * concerned that is a success. The next step will continue the * handshake to its conclusion. * * If status is PEER_SUCCESS then we are the server and we have * successfully sent the HelloRequest. We need to continue to wait * until the handshake arrives from the client. */ if (peer->status == PEER_RETRY) peer->status = PEER_SUCCESS; else if (peer->status == PEER_SUCCESS) peer->status = PEER_RETRY; return; } } /* * The SSL object is still expecting app data, even though it's going to * get a handshake message. We try to read, and it should fail - after which * we should be in a handshake */ ret = SSL_read(peer->ssl, &buf, sizeof(buf)); if (ret >= 0) { /* * We're not actually expecting data - we're expecting a reneg to * start */ peer->status = PEER_ERROR; return; } else { int error = SSL_get_error(peer->ssl, ret); if (error != SSL_ERROR_WANT_READ) { peer->status = PEER_ERROR; return; } /* If we're no in init yet then we're not done with setup yet */ if (!SSL_in_init(peer->ssl)) return; } peer->status = PEER_SUCCESS; }
static void handle_read( int cnum, struct timeval* nowP ) { char buf[30000]; /* must be larger than throttle / 2 */ int bytes_to_read, bytes_read, bytes_handled; float elapsed; ClientData client_data; long checksum; tmr_reset( nowP, connections[cnum].idle_timer ); if ( do_throttle ) bytes_to_read = throttle / 2.0; else bytes_to_read = sizeof(buf); if ( ! connections[cnum].did_response ) { connections[cnum].did_response = 1; connections[cnum].response_at = *nowP; } #ifdef USE_SSL if ( urls[connections[cnum].url_num].protocol == PROTO_HTTPS ) bytes_read = SSL_read( connections[cnum].ssl, buf, bytes_to_read ); else bytes_read = read( connections[cnum].conn_fd, buf, bytes_to_read ); #else bytes_read = read( connections[cnum].conn_fd, buf, bytes_to_read ); #endif if ( bytes_read <= 0 ) { close_connection( cnum ); return; } for ( bytes_handled = 0; bytes_handled < bytes_read; ) { switch ( connections[cnum].conn_state ) { case CNST_HEADERS: /* State machine to read until we reach the file part. Looks for ** Content-Length header too. */ for ( ; bytes_handled < bytes_read && connections[cnum].conn_state == CNST_HEADERS; ++bytes_handled ) { switch ( connections[cnum].header_state ) { case HDST_LINE1_PROTOCOL: switch ( buf[bytes_handled] ) { case ' ': case '\t': connections[cnum].header_state = HDST_LINE1_WHITESPACE; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; } break; case HDST_LINE1_WHITESPACE: switch ( buf[bytes_handled] ) { case ' ': case '\t': break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': connections[cnum].http_status = buf[bytes_handled] - '0'; connections[cnum].header_state = HDST_LINE1_STATUS; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_LINE1_STATUS: switch ( buf[bytes_handled] ) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': connections[cnum].http_status = connections[cnum].http_status * 10 + buf[bytes_handled] - '0'; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_BOL: switch ( buf[bytes_handled] ) { case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; case 'C': case 'c': connections[cnum].header_state = HDST_C; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_TEXT: switch ( buf[bytes_handled] ) { case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: break; } break; case HDST_LF: switch ( buf[bytes_handled] ) { case '\n': connections[cnum].conn_state = CNST_READING; break; case '\r': connections[cnum].header_state = HDST_CR; break; case 'C': case 'c': connections[cnum].header_state = HDST_C; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CR: switch ( buf[bytes_handled] ) { case '\n': connections[cnum].header_state = HDST_CRLF; break; case '\r': connections[cnum].conn_state = CNST_READING; break; case 'C': case 'c': connections[cnum].header_state = HDST_C; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CRLF: switch ( buf[bytes_handled] ) { case '\n': connections[cnum].conn_state = CNST_READING; break; case '\r': connections[cnum].header_state = HDST_CRLFCR; break; case 'C': case 'c': connections[cnum].header_state = HDST_C; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CRLFCR: switch ( buf[bytes_handled] ) { case '\n': case '\r': connections[cnum].conn_state = CNST_READING; break; case 'C': case 'c': connections[cnum].header_state = HDST_C; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_C: switch ( buf[bytes_handled] ) { case 'O': case 'o': connections[cnum].header_state = HDST_CO; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CO: switch ( buf[bytes_handled] ) { case 'N': case 'n': connections[cnum].header_state = HDST_CON; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CON: switch ( buf[bytes_handled] ) { case 'T': case 't': connections[cnum].header_state = HDST_CONT; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CONT: switch ( buf[bytes_handled] ) { case 'E': case 'e': connections[cnum].header_state = HDST_CONTE; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CONTE: switch ( buf[bytes_handled] ) { case 'N': case 'n': connections[cnum].header_state = HDST_CONTEN; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CONTEN: switch ( buf[bytes_handled] ) { case 'T': case 't': connections[cnum].header_state = HDST_CONTENT; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CONTENT: switch ( buf[bytes_handled] ) { case '-': connections[cnum].header_state = HDST_CONTENT_; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CONTENT_: switch ( buf[bytes_handled] ) { case 'L': case 'l': connections[cnum].header_state = HDST_CONTENT_L; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CONTENT_L: switch ( buf[bytes_handled] ) { case 'E': case 'e': connections[cnum].header_state = HDST_CONTENT_LE; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CONTENT_LE: switch ( buf[bytes_handled] ) { case 'N': case 'n': connections[cnum].header_state = HDST_CONTENT_LEN; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CONTENT_LEN: switch ( buf[bytes_handled] ) { case 'G': case 'g': connections[cnum].header_state = HDST_CONTENT_LENG; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CONTENT_LENG: switch ( buf[bytes_handled] ) { case 'T': case 't': connections[cnum].header_state = HDST_CONTENT_LENGT; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CONTENT_LENGT: switch ( buf[bytes_handled] ) { case 'H': case 'h': connections[cnum].header_state = HDST_CONTENT_LENGTH; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CONTENT_LENGTH: switch ( buf[bytes_handled] ) { case ':': connections[cnum].header_state = HDST_CONTENT_LENGTH_COLON; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CONTENT_LENGTH_COLON: switch ( buf[bytes_handled] ) { case ' ': case '\t': connections[cnum].header_state = HDST_CONTENT_LENGTH_COLON_WHITESPACE; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CONTENT_LENGTH_COLON_WHITESPACE: switch ( buf[bytes_handled] ) { case ' ': case '\t': break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': connections[cnum].content_length = buf[bytes_handled] - '0'; connections[cnum].header_state = HDST_CONTENT_LENGTH_COLON_WHITESPACE_NUM; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; case HDST_CONTENT_LENGTH_COLON_WHITESPACE_NUM: switch ( buf[bytes_handled] ) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': connections[cnum].content_length = connections[cnum].content_length * 10 + buf[bytes_handled] - '0'; break; case '\n': connections[cnum].header_state = HDST_LF; break; case '\r': connections[cnum].header_state = HDST_CR; break; default: connections[cnum].header_state = HDST_TEXT; break; } break; } } break; case CNST_READING: connections[cnum].bytes += bytes_read - bytes_handled; if ( do_throttle ) { /* Check if we're reading too fast. */ elapsed = delta_timeval( &connections[cnum].started_at, nowP ) / 1000000.0; if ( elapsed > 0.01 && connections[cnum].bytes / elapsed > throttle ) { connections[cnum].conn_state = CNST_PAUSING; client_data.i = cnum; connections[cnum].wakeup_timer = tmr_create( nowP, wakeup_connection, client_data, 1000L, 0 ); } } if ( do_checksum ) { checksum = connections[cnum].checksum; for ( ; bytes_handled < bytes_read; ++bytes_handled ) { if ( checksum & 1 ) checksum = ( checksum >> 1 ) + 0x8000; else checksum >>= 1; checksum += buf[bytes_handled]; checksum &= 0xffff; } connections[cnum].checksum = checksum; } else bytes_handled = bytes_read; if ( connections[cnum].content_length != -1 && connections[cnum].bytes >= connections[cnum].content_length ) { close_connection( cnum ); return; } break; }
int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout) { int work_done = 0; char magic_pkt; while (1) { int len = vpninfo->mtu; unsigned char *buf; if (!dtls_pkt) { dtls_pkt = malloc(sizeof(struct pkt) + len); if (!dtls_pkt) { vpn_progress(vpninfo, PRG_ERR, "Allocation failed\n"); break; } } buf = dtls_pkt->data - 1; len = SSL_read(vpninfo->dtls_ssl, buf, len + 1); if (len <= 0) break; vpn_progress(vpninfo, PRG_TRACE, _("Received DTLS packet 0x%02x of %d bytes\n"), buf[0], len); vpninfo->dtls_times.last_rx = time(NULL); switch(buf[0]) { case AC_PKT_DATA: queue_new_packet(&vpninfo->incoming_queue, buf+1, len-1); work_done = 1; break; case AC_PKT_DPD_OUT: vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD request\n")); /* FIXME: What if the packet doesn't get through? */ magic_pkt = AC_PKT_DPD_RESP; if (SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1) != 1) vpn_progress(vpninfo, PRG_ERR, _("Failed to send DPD response. Expect disconnect\n")); continue; case AC_PKT_DPD_RESP: vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS DPD response\n")); break; case AC_PKT_KEEPALIVE: vpn_progress(vpninfo, PRG_TRACE, _("Got DTLS Keepalive\n")); break; default: vpn_progress(vpninfo, PRG_ERR, _("Unknown DTLS packet type %02x, len %d\n"), buf[0], len); if (1) { /* Some versions of OpenSSL have bugs with receiving out-of-order * packets. Not only do they wrongly decide to drop packets if * two packets get swapped in transit, but they also _fail_ to * drop the packet in non-blocking mode; instead they return * the appropriate length of garbage. So don't abort... for now. */ break; } else { vpninfo->quit_reason = "Unknown packet received"; return 1; } } } switch (keepalive_action(&vpninfo->dtls_times, timeout)) { case KA_REKEY: vpn_progress(vpninfo, PRG_INFO, _("DTLS rekey due\n")); /* There ought to be a method of rekeying DTLS without tearing down the CSTP session and restarting, but we don't (yet) know it */ if (cstp_reconnect(vpninfo)) { vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n")); vpninfo->quit_reason = "CSTP reconnect failed"; return 1; } if (dtls_restart(vpninfo)) { vpn_progress(vpninfo, PRG_ERR, _("DTLS rekey failed\n")); return 1; } work_done = 1; break; case KA_DPD_DEAD: vpn_progress(vpninfo, PRG_ERR, _("DTLS Dead Peer Detection detected dead peer!\n")); /* Fall back to SSL, and start a new DTLS connection */ dtls_restart(vpninfo); return 1; case KA_DPD: vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS DPD\n")); magic_pkt = AC_PKT_DPD_OUT; SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1); /* last_dpd will just have been set */ vpninfo->dtls_times.last_tx = vpninfo->dtls_times.last_dpd; work_done = 1; break; case KA_KEEPALIVE: /* No need to send an explicit keepalive if we have real data to send */ if (vpninfo->outgoing_queue) break; vpn_progress(vpninfo, PRG_TRACE, _("Send DTLS Keepalive\n")); magic_pkt = AC_PKT_KEEPALIVE; SSL_write(vpninfo->dtls_ssl, &magic_pkt, 1); time(&vpninfo->dtls_times.last_tx); work_done = 1; break; case KA_NONE: ; } /* Service outgoing packet queue */ while (vpninfo->outgoing_queue) { struct pkt *this = vpninfo->outgoing_queue; int ret; vpninfo->outgoing_queue = this->next; vpninfo->outgoing_qlen--; /* One byte of header */ this->hdr[7] = AC_PKT_DATA; ret = SSL_write(vpninfo->dtls_ssl, &this->hdr[7], this->len + 1); if (ret <= 0) { ret = SSL_get_error(vpninfo->dtls_ssl, ret); /* If it's a real error, kill the DTLS connection and requeue the packet to be sent over SSL */ if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE) { vpn_progress(vpninfo, PRG_ERR, _("DTLS got write error %d. Falling back to SSL\n"), ret); report_ssl_errors(vpninfo); dtls_restart(vpninfo); vpninfo->outgoing_queue = this; vpninfo->outgoing_qlen++; } return 1; } time(&vpninfo->dtls_times.last_tx); vpn_progress(vpninfo, PRG_TRACE, _("Sent DTLS packet of %d bytes; SSL_write() returned %d\n"), this->len, ret); free(this); } return work_done; }
BOOL CHTTPClient::SendSSLRequest(char *szHost, char *szHostName, char *szPath, char *szUserID, char *szPassword, long lPort, char *szProxy, long lProxyPort, char *szProxyUser, char *szProxyPswd, char *szUserAgent, char *szPost, long dwTimeout, SSL **pssl, SSL_CTX **pssl_ctx, char *szTransaction) { char *szConnectHost; char *szConnectionHeader = "Connection: close\r\n"; char *szContentLength = "Content-Length: %d\r\n"; char *szContentType = "Content-Type: application/x-www-form-urlencoded\r\n"; char *szProxyConn = "Proxy-Connection: Keep-Alive\r\n"; char *szPragma = "Pragma: no-cache\r\n"; long lConnectPort; char *szBuffer = szSendBuffer; char szWork[256]; char *lpWork; char *szGetMethod = "GET"; char *szPostMethod = "POST"; char *szMethod; BOOL RC = TRUE; BOOL bBIOset = FALSE; Base64Coder cBase64Coder; BIO *bio = 0; int done = 0, i, n; char buf[2048]; // Got to have a host if (!szHost) return(FALSE); // Initialize strings used for cookies cDomain = szHostName; cPath = szPath; if (szTransaction) cTransaction = szTransaction; else cTransaction = ""; // Clean up ssl storage try { if (ssl) { SSL_free(ssl); ssl = 0; } } catch(...) { ssl = 0; } try { // Initialise the ssl library now in rtm startup // Create the context structure. Operate in the normal default SSLv3 // in a SSLv2 header mode to maximize the number of servers // we can connect to. if (!ssl_ctx) { if (!pssl_ctx || !*pssl_ctx) { if ((ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) { bConnectFailed = TRUE; throw FALSE; } } else ssl_ctx = *pssl_ctx; } // Reset variables for response bHeader = FALSE; bReadComplete = FALSE; bHeadRequest = FALSE; lReceivedLength = 0; lContentLength = 0; cHeader = ""; cContent = ""; // turn on all vendor bug compatibility options SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL); // Create the SSL structure - defaults are inherited from the SSL_CTX if ((ssl = SSL_new(ssl_ctx)) == NULL) { bConnectFailed = TRUE; throw FALSE; }; // Set as client side SSL_set_connect_state(ssl); if (!szProxy) { // No proxy szConnectHost = szHost; lConnectPort = lPort; } else { // Proxy szConnectHost = szProxy; lConnectPort = lProxyPort; }; sprintf(szWork, "%s:%u", szConnectHost, (unsigned int) lConnectPort); // Create a BIO to handle the connect and SSL handling if ((bio = BIO_new_connect(szWork)) == NULL) { bConnectFailed = TRUE; throw FALSE; }; // If using proxy then have to tunnel through to the actual ssl server if (szProxy) { sprintf(szBuffer, "CONNECT %s:%u HTTP/1.0\r\nUser-Agent: %s\r\n", szHostName, (unsigned int) lPort, szUserAgent); if (szProxyUser && szProxyPswd && strlen(szProxyUser) > 0 && strlen(szProxyPswd) > 0) { sprintf(szWork, "%s:%s", szProxyUser, szProxyPswd); cBase64Coder.Encode(szWork); sprintf(szWork, "Proxy-Authorization: Basic %s\r\n", (LPCTSTR) cBase64Coder.EncodedMessage()); strcat(szBuffer, szWork); } strcat(szBuffer, szProxyConn); strcat(szBuffer, szPragma); strcat(szBuffer, "\r\n"); // Send connect request n = strlen(szBuffer); i = 0; do { i = BIO_write(bio, &(szBuffer[i]), n); if (i <= 0) { bConnectFailed = TRUE; BIO_free(bio); throw FALSE; } n -= i; } while(n > 0); // Read response from proxy i = BIO_read(bio, buf, sizeof(buf)); if (i <= 0) { bConnectFailed = TRUE; BIO_free(bio); throw FALSE; }; buf[i] = '\0'; lpWork = strstr(buf, "200"); if (!lpWork) { bConnectFailed = TRUE; BIO_free(bio); throw FALSE; }; }; // Use the newly created connect BIO SSL_set_bio(ssl, bio, bio); bBIOset = TRUE; if (pSession && pssl) { SSL_set_session(ssl, pSession); } else { while(!done) { int i; struct tm *ptr; time_t lt; lt = time(NULL); PROTECT_CALL ptr = localtime(<); char *pszTime = asctime(ptr); RAND_seed((unsigned char *) pszTime, strlen(pszTime)); UNPROTECT_CALL // The all important handshake i = SSL_do_handshake(ssl); switch(SSL_get_error(ssl, i)) { case SSL_ERROR_NONE: // Handshake has finished, so proceed done = 1; break; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_CONNECT: // Perform the handshake again. sleep(1); break; default: bConnectFailed = TRUE; throw FALSE; break; }; }; pSession = SSL_get_session(ssl); }; if (szPost) szMethod = szPostMethod; else szMethod = szGetMethod; // Build the request sprintf(szBuffer, "%s %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s\r\n", szMethod, szPath, szUserAgent, szHostName); if (szUserID) { sprintf(szWork, "%s:%s", szUserID, szPassword); cBase64Coder.Encode(szWork); sprintf(szWork, "Authorization: Basic %s\r\n", (LPCTSTR) cBase64Coder.EncodedMessage()); strcat(szBuffer, szWork); } if (szPost) { strcat(szBuffer, szContentType); sprintf(szWork, szContentLength, strlen(szPost)); strcat(szBuffer, szWork); strcat(szBuffer, szProxyConn); strcat(szBuffer, szPragma); } else { strcat(szBuffer, szConnectionHeader); } if (!cTransaction.empty()) SendCookie(szBuffer); // Indicate end of header strcat(szBuffer, "\r\n"); sDebugSendHeader = szBuffer; if (szPost) strcat(szBuffer, szPost); dwStartTime = ::XPlatGetMilliseconds(); // Send request n = strlen(szBuffer); i = 0; do { i = SSL_write(ssl, &(szBuffer[i]), n); if (i <= 0) { bConnectFailed = FALSE; throw FALSE; } n -= i; } while(n > 0); // Read from the other side of the protocol while(1) { i = SSL_read(ssl, buf, sizeof(buf)); if (i <= 0) break; ProcessData((unsigned char *) buf, i); if (!GetTimeLeft(dwTimeout, dwStartTime)) { // Timed out bConnectFailed = FALSE; throw FALSE; }; }; if (szPost && !strcmp(szStatus, "100")) { printf("status 100"); strcat(szBuffer, szPost); // Reset variables for response bHeader = FALSE; bReadComplete = FALSE; bHeadRequest = FALSE; lReceivedLength = 0; lContentLength = 0; cHeader = ""; cContent = ""; // Send request n = strlen(szBuffer); i = 0; do { i = SSL_write(ssl, &(szBuffer[i]), n); if (i <= 0) { bConnectFailed = FALSE; throw FALSE; } n -= i; } while(n > 0); // Read from the other side of the protocol while(1) { i = SSL_read(ssl, buf, sizeof(buf)); if (i <= 0) break; ProcessData((unsigned char *) buf, i); if (!GetTimeLeft(dwTimeout, dwStartTime)) { // Timed out bConnectFailed = FALSE; throw FALSE; }; }; }; Disconnected(); throw TRUE; } catch(BOOL rc) { RC = rc; } catch(...) { RC = FALSE; if (!bBIOset && bio) { try { BIO_free(bio); } catch(...) { } } } if (pssl && pssl_ctx) { if (*pssl == 0) { *pssl = ssl; *pssl_ctx = ssl_ctx; ssl = 0; } ssl_ctx = 0; } return RC; };
status_t POP3Protocol::SendCommand(const char *cmd) { if (fSocket < 0 || fSocket > FD_SETSIZE) return B_FILE_ERROR; //printf(cmd); // Flush any accumulated garbage data before we send our command, so we // don't misinterrpret responses from previous commands (that got left over // due to bugs) as being from this command. struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 1000; /* very short timeout, hangs with 0 in R5 */ struct fd_set readSet; FD_ZERO(&readSet); FD_SET(fSocket, &readSet); int result; #ifdef USE_SSL if (fUseSSL && SSL_pending(fSSL)) result = 1; else #endif result = select(fSocket + 1, &readSet, NULL, NULL, &tv); if (result > 0) { int amountReceived; char tempString [1025]; #ifdef USE_SSL if (fUseSSL) amountReceived = SSL_read(fSSL, tempString, sizeof(tempString) - 1); else #endif amountReceived = recv(fSocket, tempString, sizeof(tempString) - 1, 0); if (amountReceived < 0) return errno; tempString [amountReceived] = 0; printf ("POP3Protocol::SendCommand Bug! Had to flush %d bytes: %s\n", amountReceived, tempString); //if (amountReceived == 0) // break; } #ifdef USE_SSL if (fUseSSL) { SSL_write(fSSL, cmd,::strlen(cmd)); } else #endif if (send(fSocket, cmd, ::strlen(cmd), 0) < 0) { fLog = strerror(errno); printf("POP3Protocol::SendCommand Send \"%s\" failed, code %d: %s\n", cmd, errno, fLog.String()); return errno; } fLog = ""; status_t err = B_OK; while (true) { int32 len = ReceiveLine(fLog); if (len <= 0 || fLog.ICompare("+OK", 3) == 0) break; if (fLog.ICompare("-ERR", 4) == 0) { printf("POP3Protocol::SendCommand \"%s\" got error message " "from server: %s\n", cmd, fLog.String()); err = B_ERROR; break; } else { printf("POP3Protocol::SendCommand \"%s\" got nonsense message " "from server: %s\n", cmd, fLog.String()); err = B_BAD_VALUE; // If it's not +OK, and it's not -ERR, then what the heck // is it? Presume an error break; } } return err; }
tb_long_t tb_ssl_read(tb_ssl_ref_t self, tb_byte_t* data, tb_size_t size) { // the ssl tb_ssl_t* ssl = (tb_ssl_t*)self; tb_assert_and_check_return_val(ssl && ssl->ssl && ssl->bopened && data, -1); // read it tb_long_t real = SSL_read(ssl->ssl, data, size); // trace tb_trace_d("read: %ld", real); // done if (real < 0) { // the error tb_long_t error = SSL_get_error(ssl->ssl, real); // want read? continue it if (error == SSL_ERROR_WANT_READ) { // trace tb_trace_d("read: want read"); // save state ssl->state = TB_STATE_SOCK_SSL_WANT_READ; return 0; } // want writ? continue it else if (error == SSL_ERROR_WANT_WRITE) { // trace tb_trace_d("read: want writ"); // save state ssl->state = TB_STATE_SOCK_SSL_WANT_WRIT; return 0; } // failed? else { // trace tb_trace_d("read: failed: %ld, %s", real, tb_ssl_error(error)); // save state ssl->state = TB_STATE_SOCK_SSL_FAILED; return -1; } } // closed? else if (!real) { // trace tb_trace_d("read: closed"); // save state ssl->state = TB_STATE_CLOSED; return -1; } // ok return real; }
/* * Read data from a secure connection. */ ssize_t secure_read(Port *port, void *ptr, size_t len) { ssize_t n; #ifdef USE_SSL if (port->ssl) { int err; rloop: errno = 0; n = SSL_read(port->ssl, ptr, len); err = SSL_get_error(port->ssl, n); switch (err) { case SSL_ERROR_NONE: port->count += n; break; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: if (port->noblock) { errno = EWOULDBLOCK; n = -1; break; } #ifdef WIN32 pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl), (err == SSL_ERROR_WANT_READ) ? FD_READ | FD_CLOSE : FD_WRITE | FD_CLOSE, INFINITE); #endif goto rloop; case SSL_ERROR_SYSCALL: /* leave it to caller to ereport the value of errno */ if (n != -1) { errno = ECONNRESET; n = -1; } break; case SSL_ERROR_SSL: ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("SSL error: %s", SSLerrmessage()))); /* fall through */ case SSL_ERROR_ZERO_RETURN: errno = ECONNRESET; n = -1; break; default: ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("unrecognized SSL error code: %d", err))); n = -1; break; } } else #endif { prepare_for_client_read(); n = recv(port->sock, ptr, len, 0); client_read_ended(); } return n; }
void main () { int err; int listen_sd; int sd; struct sockaddr_in sa_serv; struct sockaddr_in sa_cli; size_t client_len; SSL_CTX* ctx; SSL* ssl; X509* client_cert; char* str; char buf [4096]; SSL_METHOD *meth; /* SSL preliminaries. We keep the certificate and key with the context. */ SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); meth = SSLv23_server_method(); ctx = SSL_CTX_new (meth); if (!ctx) { ERR_print_errors_fp(stderr); exit(2); } if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(3); } if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(4); } if (!SSL_CTX_check_private_key(ctx)) { fprintf(stderr,"Private key does not match the certificate public key\n"); exit(5); } /* ----------------------------------------------- */ /* Prepare TCP socket for receiving connections */ listen_sd = socket (AF_INET, SOCK_STREAM, 0); CHK_ERR(listen_sd, "socket"); memset (&sa_serv, '\0', sizeof(sa_serv)); sa_serv.sin_family = AF_INET; sa_serv.sin_addr.s_addr = INADDR_ANY; sa_serv.sin_port = htons (1111); /* Server Port number */ err = bind(listen_sd, (struct sockaddr*) &sa_serv, sizeof (sa_serv)); CHK_ERR(err, "bind"); /* Receive a TCP connection. */ err = listen (listen_sd, 5); CHK_ERR(err, "listen"); client_len = sizeof(sa_cli); sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len); CHK_ERR(sd, "accept"); close (listen_sd); printf ("Connection from %lx, port %x\n", sa_cli.sin_addr.s_addr, sa_cli.sin_port); /* ----------------------------------------------- */ /* TCP connection is ready. Do server side SSL. */ ssl = SSL_new (ctx); CHK_NULL(ssl); SSL_set_fd (ssl, sd); err = SSL_accept (ssl); CHK_SSL(err); /* Get the cipher - opt */ printf ("SSL connection using %s\n", SSL_get_cipher (ssl)); /* Get client's certificate (note: beware of dynamic allocation) - opt */ client_cert = SSL_get_peer_certificate (ssl); if (client_cert != NULL) { printf ("Client certificate:\n"); str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0); CHK_NULL(str); printf ("\t subject: %s\n", str); OPENSSL_free (str); str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0); CHK_NULL(str); printf ("\t issuer: %s\n", str); OPENSSL_free (str); /* We could do all sorts of certificate verification stuff here before deallocating the certificate. */ X509_free (client_cert); } else printf ("Client does not have certificate.\n"); /* DATA EXCHANGE - Receive message and send reply. */ err = SSL_read (ssl, buf, sizeof(buf) - 1); CHK_SSL(err); buf[err] = '\0'; printf ("Got %d chars:'%s'\n", err, buf); err = SSL_write (ssl, "I hear you.", strlen("I hear you.")); CHK_SSL(err); /* Clean up. */ close (sd); SSL_free (ssl); SSL_CTX_free (ctx); }
/* * Read from the SSL socket. Safe with either blocking or * non-blocking IO. This level of complexity is probably not * necessary, as each packet gets put into one SSL application * record. When SSL has a full record, we should be able to read * the entire packet via one SSL_read(). * * When SSL has a partial record, SSL_read() will return * WANT_READ or WANT_WRITE, and zero application data. * * Called with the mutex held. */ static ssize_t proxy_tls_read(rad_listen_t *listener) { int rcode; size_t length; uint8_t *data; listen_socket_t *sock = listener->data; if (!sock->ssn->connected) { rcode = try_connect(sock->ssn); if (rcode == 0) return 0; if (rcode < 0) { SSL_shutdown(sock->ssn->ssl); return -1; } sock->ssn->connected = true; } /* * Get the maximum size of data to receive. */ if (!sock->data) sock->data = talloc_array(sock, uint8_t, sock->ssn->mtu); data = sock->data; if (sock->partial < 4) { rcode = SSL_read(sock->ssn->ssl, data + sock->partial, 4 - sock->partial); if (rcode <= 0) { int err = SSL_get_error(sock->ssn->ssl, rcode); switch (err) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: return 0; /* do some more work later */ case SSL_ERROR_ZERO_RETURN: /* remote end sent close_notify, send one back */ SSL_shutdown(sock->ssn->ssl); /* FALL-THROUGH */ case SSL_ERROR_SYSCALL: do_close: return -1; default: tls_error_log(NULL, "Failed in proxy receive"); goto do_close; } } sock->partial = rcode; } /* try reading the packet header */ if (sock->partial < 4) return 0; /* read more data */ length = (data[2] << 8) | data[3]; /* * Do these checks only once, when we read the header. */ if (sock->partial == 4) { DEBUG3("Proxy received header saying we have a packet of %u bytes", (unsigned int) length); /* * FIXME: allocate a RADIUS_PACKET, and set * "data" to be as large as necessary. */ if (length > sock->ssn->mtu) { INFO("Received packet will be too large! Set \"fragment_size = %u\"", (data[2] << 8) | data[3]); goto do_close; } } /* * Try to read some more. */ if (sock->partial < length) { rcode = SSL_read(sock->ssn->ssl, data + sock->partial, length - sock->partial); if (rcode <= 0) { switch (SSL_get_error(sock->ssn->ssl, rcode)) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: return 0; case SSL_ERROR_ZERO_RETURN: /* remote end sent close_notify, send one back */ SSL_shutdown(sock->ssn->ssl); goto do_close; default: goto do_close; } } sock->partial += rcode; } /* * If we're not done, say so. * * Otherwise, reset the partially read data flag, and say * we have a packet. */ if (sock->partial < length) { return 0; } sock->partial = 0; /* we've now read the packet */ return length; }
static void ns_read_from_socket(struct ns_connection *conn) { char buf[NS_READ_BUFFER_SIZE]; int n = 0; if (conn->flags & NSF_CONNECTING) { int ok = 1, ret; socklen_t len = sizeof(ok); ret = getsockopt(conn->sock, SOL_SOCKET, SO_ERROR, (char *) &ok, &len); #ifdef NS_ENABLE_SSL if (ret == 0 && ok == 0 && conn->ssl != NULL) { int res = SSL_connect(conn->ssl); int ssl_err = ns_ssl_err(conn, res); if (res == 1) { conn->flags |= NSF_SSL_HANDSHAKE_DONE; } else if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) { return; /* Call us again */ } else { ok = 1; } } #endif conn->flags &= ~NSF_CONNECTING; DBG(("%p ok=%d", conn, ok)); if (ok != 0) { conn->flags |= NSF_CLOSE_IMMEDIATELY; } ns_call(conn, NS_CONNECT, &ok); return; } #ifdef NS_ENABLE_SSL if (conn->ssl != NULL) { if (conn->flags & NSF_SSL_HANDSHAKE_DONE) { /* SSL library may have more bytes ready to read then we ask to read. * Therefore, read in a loop until we read everything. Without the loop, * we skip to the next select() cycle which can just timeout. */ while ((n = SSL_read(conn->ssl, buf, sizeof(buf))) > 0) { DBG(("%p %lu <- %d bytes (SSL)", conn, conn->flags, n)); iobuf_append(&conn->recv_iobuf, buf, n); ns_call(conn, NS_RECV, &n); } ns_ssl_err(conn, n); } else { int res = SSL_accept(conn->ssl); int ssl_err = ns_ssl_err(conn, res); if (res == 1) { conn->flags |= NSF_SSL_HANDSHAKE_DONE; } else if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) { return; /* Call us again */ } else { conn->flags |= NSF_CLOSE_IMMEDIATELY; } return; } } else #endif { while ((n = (int) recv(conn->sock, buf, sizeof(buf), 0)) > 0) { DBG(("%p %lu <- %d bytes (PLAIN)", conn, conn->flags, n)); iobuf_append(&conn->recv_iobuf, buf, n); ns_call(conn, NS_RECV, &n); } } if (ns_is_error(n)) { conn->flags |= NSF_CLOSE_IMMEDIATELY; } }
/* {{{ my_recv */ int my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) { int n, nr_bytes; #ifdef HAVE_FTP_SSL int err; zend_bool retry = 0; SSL *handle = NULL; php_socket_t fd; #endif n = php_pollfd_for_ms(s, PHP_POLLREADABLE, ftp->timeout_sec * 1000); if (n < 1) { #ifdef PHP_WIN32 if (n == 0) { _set_errno(ETIMEDOUT); } #else if (n == 0) { errno = ETIMEDOUT; } #endif return -1; } #ifdef HAVE_FTP_SSL if (ftp->use_ssl && ftp->fd == s && ftp->ssl_active) { handle = ftp->ssl_handle; fd = ftp->fd; } else if (ftp->use_ssl && ftp->fd != s && ftp->use_ssl_for_data && ftp->data->ssl_active) { handle = ftp->data->ssl_handle; fd = ftp->data->fd; } if (handle) { do { nr_bytes = SSL_read(handle, buf, len); err = SSL_get_error(handle, nr_bytes); switch (err) { case SSL_ERROR_NONE: retry = 0; break; case SSL_ERROR_ZERO_RETURN: retry = 0; SSL_shutdown(handle); break; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_CONNECT: { php_pollfd p; int i; p.fd = fd; p.events = POLLIN|POLLPRI; p.revents = 0; i = php_poll2(&p, 1, 300); retry = i > 0; } break; default: php_error_docref(NULL, E_WARNING, "SSL read failed"); return -1; } } while (retry); } else { #endif nr_bytes = recv(s, buf, len, 0); #ifdef HAVE_FTP_SSL } #endif return (nr_bytes); }
static int transfer(CLI *c) { /* transfer data */ fd_set rd_set, wr_set; int num, err, fdno; int check_SSL_pending; int ssl_closing; /* 0=not closing SSL, 1=initiate SSL_shutdown, * 2=retry SSL_shutdown, 3=SSL_shutdown done */ int ready; struct timeval tv; /* fdno=max(c->sock_rfd->fd, c->sock_wfd->fd, * fdno=c->ssl_rfd->fd, fdno=c->ssl_wfd->fd)+1 */ fdno=c->sock_rfd->fd; if(c->sock_wfd->fd>fdno) fdno=c->sock_wfd->fd; if(c->ssl_rfd->fd>fdno) fdno=c->ssl_rfd->fd; if(c->ssl_wfd->fd>fdno) fdno=c->ssl_wfd->fd; fdno+=1; c->sock_ptr=c->ssl_ptr=0; sock_rd=sock_wr=ssl_rd=ssl_wr=1; c->sock_bytes=c->ssl_bytes=0; ssl_closing=0; while(((sock_rd||c->sock_ptr)&&ssl_wr)||((ssl_rd||c->ssl_ptr)&&sock_wr)) { FD_ZERO(&rd_set); /* Setup rd_set */ if(sock_rd && c->sock_ptr<BUFFSIZE) /* socket input buffer not full*/ FD_SET(c->sock_rfd->fd, &rd_set); if(ssl_rd && ( c->ssl_ptr<BUFFSIZE || /* SSL input buffer not full */ ((c->sock_ptr||ssl_closing) && SSL_want_read(c->ssl)) /* I want to SSL_write or SSL_shutdown but read from the * underlying socket needed for the SSL protocol */ )) { FD_SET(c->ssl_rfd->fd, &rd_set); } FD_ZERO(&wr_set); /* Setup wr_set */ if(sock_wr && c->ssl_ptr) /* SSL input buffer not empty */ FD_SET(c->sock_wfd->fd, &wr_set); if (ssl_wr && ( c->sock_ptr || /* socket input buffer not empty */ ssl_closing==1 || /* initiate SSL_shutdown */ ((c->ssl_ptr<BUFFSIZE || ssl_closing==2) && SSL_want_write(c->ssl)) /* I want to SSL_read or SSL_shutdown but write to the * underlying socket needed for the SSL protocol */ )) { FD_SET(c->ssl_wfd->fd, &wr_set); } tv.tv_sec=sock_rd || (ssl_wr&&c->sock_ptr) || (sock_wr&&c->ssl_ptr) ? c->opt->timeout_idle : c->opt->timeout_close; tv.tv_usec=0; ready=sselect(fdno, &rd_set, &wr_set, NULL, &tv); if(ready<0) { /* Break the connection for others */ sockerror("select"); return -1; } if(!ready) { /* Timeout */ if(sock_rd) { /* No traffic for a long time */ log(LOG_DEBUG, "select timeout: connection reset"); return -1; } else { /* Timeout waiting for SSL close_notify */ log(LOG_DEBUG, "select timeout waiting for SSL close_notify"); break; /* Leave the while() loop */ } } if(ssl_closing==1 /* initiate SSL_shutdown */ || (ssl_closing==2 && ( (SSL_want_read(c->ssl) && FD_ISSET(c->ssl_rfd->fd, &rd_set)) || (SSL_want_write(c->ssl) && FD_ISSET(c->ssl_wfd->fd, &wr_set)) ))) { switch(SSL_shutdown(c->ssl)) { /* Send close_notify */ case 1: /* the shutdown was successfully completed */ log(LOG_INFO, "SSL_shutdown successfully sent close_notify"); ssl_wr=0; /* SSL write closed */ /* TODO: It's not really closed. We need to distinguish * closed SSL and closed underlying file descriptor */ ssl_closing=3; /* done! */ break; case 0: /* the shutdown is not yet finished */ log(LOG_DEBUG, "SSL_shutdown retrying"); ssl_closing=2; /* next time just retry SSL_shutdown */ break; case -1: /* a fatal error occurred */ sslerror("SSL_shutdown"); return -1; } } /* Set flag to try and read any buffered SSL data if we made */ /* room in the buffer by writing to the socket */ check_SSL_pending = 0; if(sock_wr && FD_ISSET(c->sock_wfd->fd, &wr_set)) { switch(num=writesocket(c->sock_wfd->fd, c->ssl_buff, c->ssl_ptr)) { case -1: /* error */ switch(get_last_socket_error()) { case EINTR: log(LOG_DEBUG, "writesocket interrupted by a signal: retrying"); break; case EWOULDBLOCK: log(LOG_NOTICE, "writesocket would block: retrying"); break; default: sockerror("writesocket"); return -1; } break; case 0: log(LOG_DEBUG, "No data written to the socket: retrying"); break; default: memmove(c->ssl_buff, c->ssl_buff+num, c->ssl_ptr-num); if(c->ssl_ptr==BUFFSIZE) check_SSL_pending=1; c->ssl_ptr-=num; c->sock_bytes+=num; if(!ssl_rd && !c->ssl_ptr) { shutdown(c->sock_wfd->fd, SHUT_WR); log(LOG_DEBUG, "Socket write shutdown (no more data to send)"); sock_wr=0; } } } if(ssl_wr && ( /* SSL sockets are still open */ (c->sock_ptr && FD_ISSET(c->ssl_wfd->fd, &wr_set)) || /* See if application data can be written */ (SSL_want_read(c->ssl) && FD_ISSET(c->ssl_rfd->fd, &rd_set)) /* I want to SSL_write but read from the underlying */ /* socket needed for the SSL protocol */ )) { num=SSL_write(c->ssl, c->sock_buff, c->sock_ptr); err=SSL_get_error(c->ssl, num); switch(err) { case SSL_ERROR_NONE: memmove(c->sock_buff, c->sock_buff+num, c->sock_ptr-num); c->sock_ptr-=num; c->ssl_bytes+=num; if(!ssl_closing && !sock_rd && !c->sock_ptr && ssl_wr) { log(LOG_DEBUG, "SSL write shutdown (no more data to send)"); ssl_closing=1; } break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_X509_LOOKUP: log(LOG_DEBUG, "SSL_write returned WANT_: retrying"); break; case SSL_ERROR_SYSCALL: if(num<0) { /* really an error */ switch(get_last_socket_error()) { case EINTR: log(LOG_DEBUG, "SSL_write interrupted by a signal: retrying"); break; case EAGAIN: log(LOG_DEBUG, "SSL_write returned EAGAIN: retrying"); break; default: sockerror("SSL_write (ERROR_SYSCALL)"); return -1; } } break; case SSL_ERROR_ZERO_RETURN: /* close_notify received */ log(LOG_DEBUG, "SSL closed on SSL_write"); ssl_rd=ssl_wr=0; break; case SSL_ERROR_SSL: sslerror("SSL_write"); return -1; default: log(LOG_ERR, "SSL_write/SSL_get_error returned %d", err); return -1; } } if(sock_rd && FD_ISSET(c->sock_rfd->fd, &rd_set)) { switch(num=readsocket(c->sock_rfd->fd, c->sock_buff+c->sock_ptr, BUFFSIZE-c->sock_ptr)) { case -1: switch(get_last_socket_error()) { case EINTR: log(LOG_DEBUG, "readsocket interrupted by a signal: retrying"); break; case EWOULDBLOCK: log(LOG_NOTICE, "readsocket would block: retrying"); break; default: sockerror("readsocket"); return -1; } break; case 0: /* close */ log(LOG_DEBUG, "Socket closed on read"); sock_rd=0; if(!ssl_closing && !c->sock_ptr && ssl_wr) { log(LOG_DEBUG, "SSL write shutdown (output buffer empty)"); ssl_closing=1; } break; default: c->sock_ptr+=num; } } if(ssl_rd && ( /* SSL sockets are still open */ (c->ssl_ptr<BUFFSIZE && FD_ISSET(c->ssl_rfd->fd, &rd_set)) || /* See if there's any application data coming in */ (SSL_want_write(c->ssl) && FD_ISSET(c->ssl_wfd->fd, &wr_set)) || /* I want to SSL_read but write to the underlying */ /* socket needed for the SSL protocol */ (check_SSL_pending && SSL_pending(c->ssl)) /* Write made space from full buffer */ )) { num=SSL_read(c->ssl, c->ssl_buff+c->ssl_ptr, BUFFSIZE-c->ssl_ptr); err=SSL_get_error(c->ssl, num); switch(err) { case SSL_ERROR_NONE: c->ssl_ptr+=num; break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_X509_LOOKUP: log(LOG_DEBUG, "SSL_read returned WANT_: retrying"); break; case SSL_ERROR_SYSCALL: if(num<0) { /* not EOF */ switch(get_last_socket_error()) { case EINTR: log(LOG_DEBUG, "SSL_read interrupted by a signal: retrying"); break; case EAGAIN: log(LOG_DEBUG, "SSL_read returned EAGAIN: retrying"); break; default: sockerror("SSL_read (ERROR_SYSCALL)"); return -1; } } else { /* EOF */ log(LOG_DEBUG, "SSL socket closed on SSL_read"); ssl_rd=ssl_wr=0; } break; case SSL_ERROR_ZERO_RETURN: /* close_notify received */ log(LOG_DEBUG, "SSL closed on SSL_read"); ssl_rd=0; if(!ssl_closing && !c->sock_ptr && ssl_wr) { log(LOG_DEBUG, "SSL write shutdown (output buffer empty)"); ssl_closing=1; } if(!c->ssl_ptr && sock_wr) { shutdown(c->sock_wfd->fd, SHUT_WR); log(LOG_DEBUG, "Socket write shutdown (output buffer empty)"); sock_wr=0; } break; case SSL_ERROR_SSL: sslerror("SSL_read"); return -1; default: log(LOG_ERR, "SSL_read/SSL_get_error returned %d", err); return -1; } } } return 0; /* OK */ }
PUBLIC int HTSSL_read (HTSSL * htssl, int sd, char * buff, int len) { return htssl && htssl->ssl ? SSL_read(htssl->ssl, buff, len) : -1; }
extern "C" int32_t CryptoNative_SslRead(SSL* ssl, void* buf, int32_t num) { ERR_clear_error(); return SSL_read(ssl, buf, num); }
static ssize_t i_stream_ssl_read_real(struct istream_private *stream) { struct ssl_istream *sstream = (struct ssl_istream *)stream; struct ssl_iostream *ssl_io = sstream->ssl_io; unsigned char buffer[IO_BLOCK_SIZE]; size_t max_buffer_size = i_stream_get_max_buffer_size(&stream->istream); size_t orig_max_buffer_size = stream->max_buffer_size; size_t size; ssize_t ret, total_ret; if (sstream->seen_eof) { stream->istream.eof = TRUE; return -1; } if (stream->pos >= max_buffer_size) { i_stream_compress(stream); if (stream->pos >= max_buffer_size) return -2; } ret = openssl_iostream_more(ssl_io); if (ret <= 0) { if (ret < 0) { /* handshake failed */ i_assert(errno != 0); io_stream_set_error(&stream->iostream, "%s", ssl_io->last_error); stream->istream.stream_errno = errno; } return ret; } if (!i_stream_try_alloc(stream, 1, &size)) i_unreached(); if (stream->pos + size > max_buffer_size) { i_assert(max_buffer_size > stream->pos); size = max_buffer_size - stream->pos; } while ((ret = SSL_read(ssl_io->ssl, stream->w_buffer + stream->pos, size)) <= 0) { /* failed to read anything */ ret = openssl_iostream_handle_error(ssl_io, ret, "SSL_read"); if (ret <= 0) { if (ret == 0) return 0; if (ssl_io->last_error != NULL) { io_stream_set_error(&stream->iostream, "%s", ssl_io->last_error); } if (errno != EPIPE) stream->istream.stream_errno = errno; stream->istream.eof = TRUE; sstream->seen_eof = TRUE; return -1; } /* we did some BIO I/O, try reading again */ } stream->pos += ret; total_ret = ret; /* now make sure that we read everything already buffered in OpenSSL into the stream (without reading anything more). this makes I/O loop behave similary for ssl-istream as file-istream. */ sstream->ssl_io->input_handler = FALSE; stream->max_buffer_size = (size_t)-1; while ((ret = SSL_read(ssl_io->ssl, buffer, sizeof(buffer))) > 0) { memcpy(i_stream_alloc(stream, ret), buffer, ret); stream->pos += ret; total_ret += ret; } stream->max_buffer_size = orig_max_buffer_size; return total_ret; }
int main(int argc, char *argv[]) { SSL_library_init(); SSL_load_error_strings(); SSL * new_ssl; SSL_CTX * new_ctx; new_ctx = dh_setup_ctx(); BIO * acc, * client; char port[sizeof(argv[1])] = ""; int check = 0; long port_num; parse_port(argc,argv,port); acc = BIO_new_accept("1300"); port_num = BIO_set_accept_port(acc,port); if ( !acc ) { printf("%s \n", "Error in new bio accept"); return -1; } if ( BIO_do_accept(acc) <= 0) { printf("%s \n", "Error in do accept" ); return -1; } int get = 0; while ( 1 ) { if( BIO_do_accept(acc) <= 0 ) { printf("%s \n", "Error in accepting connections"); return -1; } client = BIO_pop(acc); if ( !(new_ssl = SSL_new(new_ctx))) { printf("%s \n", "Error in creating new SSL"); return -1; } SSL_set_bio(new_ssl,client,client); if( SSL_accept(new_ssl) <= 0 ) { get = SSL_get_error(new_ssl,get); printf("%s \n", "Error in accepting SSL connection"); printf("%d \n", get); printf("%s \n",ERR_error_string(get,NULL)); return -1; } int buf[256] = { 0 }; int count = 0; if ( SSL_read(new_ssl,buf,sizeof(buf)) > 0) { /*get = SSL_get_error(new_ssl,get); printf("%d \n", get); printf("%s \n",ERR_error_string(get,NULL)); */ while( (char)buf[count] != EOF ) { printf("%c" , (char)buf[count]); count++; } } SSL_shutdown(new_ssl); SSL_free(new_ssl); } SSL_CTX_free(new_ctx); BIO_free(acc); return 0; }
status_t POP3Protocol::RetrieveInternal(const char *command, int32 message, BPositionIO *write_to, bool post_progress) { const int bufSize = 1024 * 30; // To avoid waiting for the non-arrival of the next data packet, try to // receive only the message size, plus the 3 extra bytes for the ".\r\n" // after the message. Of course, if we get it wrong (or it is a huge // message or has lines starting with escaped periods), it will then switch // back to receiving full buffers until the message is done. int amountToReceive = MessageSize (message) + 3; if (amountToReceive >= bufSize || amountToReceive <= 0) amountToReceive = bufSize - 1; BString bufBString; // Used for auto-dealloc on return feature. char *buf = bufBString.LockBuffer (bufSize); int amountInBuffer = 0; int amountReceived; int testIndex; char *testStr; bool cont = true; bool flushWholeBuffer = false; write_to->Seek(0,SEEK_SET); if (SendCommand(command) != B_OK) return B_ERROR; struct timeval tv; tv.tv_sec = POP3_RETRIEVAL_TIMEOUT / 1000000; tv.tv_usec = POP3_RETRIEVAL_TIMEOUT % 1000000; struct fd_set readSet; FD_ZERO(&readSet); FD_SET(fSocket, &readSet); while (cont) { int result = 0; #ifdef USE_SSL if (fUseSSL && SSL_pending(fSSL)) result = 1; else #endif result = select(fSocket + 1, &readSet, NULL, NULL, &tv); if (result == 0) { // No data available, even after waiting a minute. fLog = "POP3 timeout - no data received after a long wait."; runner->Stop(true); return B_ERROR; } if (amountToReceive > bufSize - 1 - amountInBuffer) amountToReceive = bufSize - 1 - amountInBuffer; #ifdef USE_SSL if (fUseSSL) { amountReceived = SSL_read(fSSL, buf + amountInBuffer, amountToReceive); } else #endif amountReceived = recv(fSocket, buf + amountInBuffer, amountToReceive, 0); if (amountReceived < 0) { fLog = strerror(errno); return errno; } if (amountReceived == 0) { fLog = "POP3 data supposedly ready to receive but not received!"; return B_ERROR; } amountToReceive = bufSize - 1; // For next time, read a full buffer. amountInBuffer += amountReceived; buf[amountInBuffer] = 0; // NUL stops tests past the end of buffer. // Look for lines starting with a period. A single period by itself on // a line "\r\n.\r\n" marks the end of the message (thus the need for // at least five characters in the buffer for testing). A period // "\r\n.Stuff" at the start of a line get deleted "\r\nStuff", since // POP adds one as an escape code to let you have message text with // lines starting with a period. For convenience, assume that no // messages start with a period on the very first line, so we can // search for the previous line's "\r\n". for (testIndex = 0; testIndex <= amountInBuffer - 5; testIndex++) { testStr = buf + testIndex; if (testStr[0] == '\r' && testStr[1] == '\n' && testStr[2] == '.') { if (testStr[3] == '\r' && testStr[4] == '\n') { // Found the end of the message marker. Ignore remaining data. if (amountInBuffer > testIndex + 5) printf ("POP3Protocol::RetrieveInternal Ignoring %d bytes " "of extra data past message end.\n", amountInBuffer - (testIndex + 5)); amountInBuffer = testIndex + 2; // Don't include ".\r\n". buf[amountInBuffer] = 0; cont = false; } else { // Remove an extra period at the start of a line. // Inefficient, but it doesn't happen often that you have a // dot starting a line of text. Of course, a file with a // lot of double period lines will get processed very // slowly. memmove (buf + testIndex + 2, buf + testIndex + 3, amountInBuffer - (testIndex + 3) + 1 /* for NUL at end */); amountInBuffer--; // Watch out for the end of buffer case, when the POP text // is "\r\n..X". Don't want to leave the resulting // "\r\n.X" in the buffer (flush out the whole buffer), // since that will get mistakenly evaluated again in the // next loop and delete a character by mistake. if (testIndex >= amountInBuffer - 4 && testStr[2] == '.') { printf ("POP3Protocol::RetrieveInternal: Jackpot! You have " "hit the rare situation with an escaped period at the " "end of the buffer. Aren't you happy it decodes it " "correctly?\n"); flushWholeBuffer = true; } } } } if (cont && !flushWholeBuffer) { // Dump out most of the buffer, but leave the last 4 characters for // comparison continuity, in case the line starting with a period // crosses a buffer boundary. if (amountInBuffer > 4) { write_to->Write(buf, amountInBuffer - 4); if (post_progress) runner->ReportProgress(amountInBuffer - 4,0); memmove (buf, buf + amountInBuffer - 4, 4); amountInBuffer = 4; } } else { // Dump everything - end of message or flushing the whole buffer. write_to->Write(buf, amountInBuffer); if (post_progress) runner->ReportProgress(amountInBuffer,0); amountInBuffer = 0; } } return B_OK; }
int connect_ssl(char *host, char *port, int reconnect, int use_sessionid, int use_ticket, int delay, const char *client_cert, const char *client_key) { SSL_CTX* ctx; SSL* ssl; SSL_SESSION* ssl_session = NULL; int s, n; char buffer[256]; struct addrinfo* addr; start("Initialize OpenSSL library"); SSL_load_error_strings(); SSL_library_init(); if ((ctx = SSL_CTX_new(TLSv1_client_method())) == NULL) fail("Unable to initialize SSL context:\n%s", ERR_error_string(ERR_get_error(), NULL)); if (client_cert || client_key) { if (SSL_CTX_use_certificate_chain_file(ctx,client_cert)==0) { fail("failed to read X509 certificate from file %s into PEM format",client_key); } } if (client_key) { if (SSL_CTX_use_PrivateKey_file(ctx,client_key,SSL_FILETYPE_PEM)==0) { fail("failed to read private key from file %s into PEM format",client_key); } } if (!use_ticket) { start("Disable use of session tickets (RFC 5077)"); SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET); } addr = solve(host, port); do { s = connect_socket(addr, host, port); start("Start TLS renegotiation"); if ((ssl = SSL_new(ctx)) == NULL) fail("Unable to create new SSL struct:\n%s", ERR_error_string(ERR_get_error(), NULL)); SSL_set_fd(ssl, s); if (ssl_session) { if (!SSL_set_session(ssl, ssl_session)) { fail("Unable to set session to previous one:\n%s", ERR_error_string(ERR_get_error(), NULL)); } } if (SSL_connect(ssl) != 1) fail("Unable to start TLS renegotiation:\n%s", ERR_error_string(ERR_get_error(), NULL)); start("Check if session was reused"); if (!SSL_session_reused(ssl) && ssl_session) warn("No session was reused."); else if (SSL_session_reused(ssl) && !ssl_session) warn("Session was reused."); else if (SSL_session_reused(ssl)) end("SSL session correctly reused"); else end("SSL session was not used"); start("Get current session"); if (ssl_session) SSL_SESSION_free(ssl_session); ssl_session = NULL; if (!(ssl_session = SSL_get1_session(ssl))) warn("No session available"); else { BIO *mem = BIO_new(BIO_s_mem()); char *buf; if (SSL_SESSION_print(mem, ssl_session) != 1) fail("Unable to print session:\n%s", ERR_error_string(ERR_get_error(), NULL)); n = BIO_get_mem_data(mem, &buf); buf[n-1] = '\0'; end("Session content:\n%s", buf); BIO_free(mem); } if ((!use_sessionid && !use_ticket) || (!use_sessionid && !ssl_session->tlsext_tick)) { SSL_SESSION_free(ssl_session); ssl_session = NULL; } start("Send HTTP GET"); n = snprintf(buffer, sizeof(buffer), "GET / HTTP/1.0\r\n" "Host: %s\r\n" "\r\n", host); if (n == -1 || n >= sizeof(buffer)) fail("Unable to build request to send"); if (SSL_write(ssl, buffer, strlen(buffer)) != strlen(buffer)) fail("SSL write request failed:\n%s", ERR_error_string(ERR_get_error(), NULL)); start("Get HTTP answer"); if ((n = SSL_read(ssl, buffer, sizeof(buffer) - 1)) <= 0) fail("SSL read request failed:\n%s", ERR_error_string(ERR_get_error(), NULL)); buffer[n] = '\0'; if (strchr(buffer, '\r')) *strchr(buffer, '\r') = '\0'; end("%s", buffer); start("End TLS connection"); SSL_shutdown(ssl); close(s); SSL_free(ssl); --reconnect; if (reconnect < 0) break; else { start("waiting %d seconds",delay); sleep(delay); } } while (1); SSL_CTX_free(ctx); return 0; }
int main(int argc,char ** argv) { SSL *ssl; SSL_CTX *ctx; SSL_METHOD *client_method; X509 *server_cert; int sd,err; char *str,*hostname,outbuf[4096],inbuf[4096],host_header[512]; struct hostent *host_entry; struct sockaddr_in server_socket_address; struct in_addr ip; //init ssl library SSLeay_add_ssl_algorithms(); client_method = SSLv23_client_method(); SSL_load_error_strings(); ctx = SSL_CTX_new(client_method); printf("(1)ssl context init\n\n"); //convert server hostname into a ip address hostname = argv[1]; host_entry = gethostbyname(hostname); bcopy(host_entry->h_addr,&(ip.s_addr),host_entry->h_length); printf("(2)%s has ip address %s\n\n",hostname,inet_ntoa(ip)); //open a tcp connection to port 443 on server sd = socket(AF_INET,SOCK_STREAM,0); memset(&server_socket_address,'\0',sizeof(server_socket_address)); server_socket_address.sin_family = AF_INET; server_socket_address.sin_port = htons(443); memcpy(&(server_socket_address.sin_addr.s_addr),host_entry->h_addr,host_entry->h_length); err = connect(sd,(struct sockaddr *)&server_socket_address,sizeof(server_socket_address)); if(err<0) { perror("can not connect to server port"); exit(1); } printf("(3) tcp connection open to host %s,port %d\n\n",hostname,server_socket_address.sin_port); //init the ssl handshake over tcp connection ssl = SSL_new(ctx); SSL_set_fd(ssl,sd); err = SSL_connect(ssl); printf ("(4) ssl endpoint created & handshake compltete \n\n"); //print out the negotiated cipher chosen printf("(5) ssl connected with cipher: %s\n\n",SSL_get_cipher(ssl)); //print out the server's certificate server_cert = SSL_get_peer_certificate(ssl); printf("(6) server's certificate was received:\n\n"); str = X509_NAME_oneline(X509_get_subject_name(server_cert),0,0); printf("\tsubject:%s\n",str); str = X509_NAME_oneline(X509_get_issuer_name(server_cert),0,0); printf("\tissuer:%s\n\n",str); //certificate verification would happen here X509_free(server_cert); //handshake complete--send http request over ssl sprintf(host_header,"Host:%s:443\r\n",hostname); strcpy(outbuf,"GET / HTTP/1.1\r\n"); strcat(outbuf,host_header); strcat(outbuf,"Connection:close\r\n"); strcat(outbuf,"\r\n"); err=SSL_write(ssl,outbuf,strlen(outbuf)); shutdown(sd,1);//send eof to server printf("(7) send http request over encrypted channel:\n\n%s\n",outbuf); //read back http response from the ssl stack err = SSL_read(ssl,inbuf,sizeof(inbuf)-1); inbuf[err]='\0'; printf("(8)got back %d bytes of http response:\n\n%s\n",err,inbuf); //all done,so close connection & clean up SSL_shutdown(ssl); close(sd); SSL_free(ssl); SSL_CTX_free(ctx); printf("(9) all done ,cleaned up and closed connection\n\n"); return 0; }
int main(int argc, char **argv) { int sockfd, new_fd; socklen_t len; struct sockaddr_in my_addr, their_addr; unsigned int myport, lisnum; char buf[MAXBUF + 1]; SSL_CTX *ctx; /* 指定监听端口 */ if (argc > 1 && argv[1]) { myport = atoi(argv[1]); } else { myport = 8888; } /* 最大客户端连接数 */ if (argv[2]) { lisnum = atoi(argv[2]); } else { lisnum = 2; } /* SSL 库初始化 */ SSL_library_init(); /* 载入所有SSL 算法 */ OpenSSL_add_all_algorithms(); /* 载入所有SSL 错误消息 */ SSL_load_error_strings(); /* 以SSL V2 和V3 标准兼容方式产生一个SSL_CTX ,即SSL Content Text */ ctx = SSL_CTX_new(SSLv23_server_method()); /* 也可以用SSLv2_server_method() 或SSLv3_server_method() 单独表示V2 或V3标准 */ if (ctx == NULL) { ERR_print_errors_fp(stdout); exit(1); } /* 载入用户的数字证书, 此证书用来发送给客户端。证书里包含有公钥 */ if (SSL_CTX_use_certificate_file(ctx, argv[4], SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stdout); exit(1); } /* 载入用户私钥 */ if (SSL_CTX_use_PrivateKey_file(ctx, argv[5], SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stdout); exit(1); } /* 检查用户私钥是否正确 */ if (!SSL_CTX_check_private_key(ctx)) { ERR_print_errors_fp(stdout); exit(1); } /* 开启一个socket 监听 */ if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } else { printf("socket created\n"); } bzero(&my_addr, sizeof(my_addr)); my_addr.sin_family = PF_INET; my_addr.sin_port = htons(myport); /* 设置监听的IP */ if (argv[3]) { my_addr.sin_addr.s_addr = inet_addr(argv[3]); } else { /* 如果用户没有指定监听端口,则默认监听0.0.0.0(任意IP) */ my_addr.sin_addr.s_addr = INADDR_ANY; } if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } else { printf("binded\n"); } if (listen(sockfd, lisnum) == -1) { perror("listen"); exit(1); } else { printf("begin listen\n"); } while (1) { SSL *ssl; len = sizeof(struct sockaddr); /* 等待客户端连上来 */ if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &len)) == -1) { perror("accept"); exit(errno); } else { printf("server: got connection from %s, port %d, socket %d\n", inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd); } /* 基于ctx 产生一个新的SSL */ ssl = SSL_new(ctx); /* 将连接用户的socket 加入到SSL */ SSL_set_fd(ssl, new_fd); /* 建立SSL 连接 */ if (SSL_accept(ssl) == -1) { perror("accept"); close(new_fd); break; } /* 开始处理每个新连接上的数据收发 */ bzero(buf, MAXBUF + 1); strcpy(buf, "server->client"); /* 发消息给客户端 */ len = SSL_write(ssl, buf, strlen(buf)); if (len <= 0) { printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n", buf, errno, strerror(errno)); goto finish; } else { printf("消息'%s'发送成功,共发送了%d 个字节!\n", buf, len); } bzero(buf, MAXBUF + 1); /* 接收客户端的消息 */ len = SSL_read(ssl, buf, MAXBUF); if (len > 0) { printf("接收消息成功:'%s',共%d 个字节的数据\n", buf, len); } else { printf("消息接收失败!错误代码是%d,错误信息是'%s'\n", errno, strerror(errno)); } /* 处理每个新连接上的数据收发结束 */ finish: /* 关闭SSL 连接 */ SSL_shutdown(ssl); /* 释放SSL */ SSL_free(ssl); /* 关闭socket */ close(new_fd); } /* 关闭监听的socket */ close(sockfd); /* 释放CTX */ SSL_CTX_free(ctx); return 0; }
int YellHttp_ExecRequest(YellHttp_Ctx *ctx, char *url) { int retval; int i=0; int endi; int hostnamei; int porti = 0; int recvlen; int stop = 0; int headerspos = 0; int linenum = 0; int pos=0, pos2 = 0; char *hdrfield, *hdrval; struct hostent *host; struct sockaddr_in client_addr; FILE *fhttpdump; struct stat filestatus; char modifiedsincedate[512]; char hdrstr[512]; int send_modifiedsince_hdr = 0; int valid_domain_name; unsigned long serverip; char request_type[8]; unsigned int content_len; int err; char errbuffer[80]; if(url==NULL)return YELLHTTP_EINVAL; memset(ctx->url, 0, 512); strncpy(ctx->url, url, 511); ctx->server_flags &= YELLHTTP_SRVFLAG_USRFLAGS; if(strncmp(ctx->url, "https", 5)==0) { #ifdef ENABLESSL ctx->SSL = 1; #else return YELLHTTP_ESSLDISABLED; #endif i+= 8; } else if(strncmp(ctx->url, "http", 4)==0) { ctx->SSL = 0; i+= 7; } else { return YELLHTTP_EINVAL; } hostnamei = i; memset(ctx->hostname, 0, 512); while(ctx->url[i]!='/' && ctx->url[i]!=':' && i<strlen(ctx->url))i++; if(i>255)return YELLHTTP_EINVAL; strncpy(ctx->hostname, &ctx->url[hostnamei], i - hostnamei); memset(ctx->uri, 0, 512); memset(ctx->portstr, 0, 8); ctx->port = 80; if(ctx->SSL)ctx->port = 443; if(ctx->url[i]==':') { i++; memset(ctx->portstr, 0, 8); while((ctx->url[i]>('0'-1) && ctx->url[i]<('9'+1)) && porti<8 && i<strlen(ctx->url)) { ctx->portstr[porti] = ctx->url[i]; i++; porti++; } sscanf(ctx->portstr, "%hd", &ctx->port); } strcpy(ctx->uri, &ctx->url[i]); i = strlen(ctx->uri) - 1; if(i==-1) { ctx->uri[0] = '/'; i = 0; } endi = i; memset(ctx->filename, 0, 512); while(ctx->uri[i]!='/' && i>0) { if(ctx->uri[i]=='?')endi = i - 1; i--; } if(strcmp(&ctx->uri[i], "/")==0) { strncpy(ctx->filename, "index.html", 512); } else { i++; strncpy(ctx->filename, &ctx->uri[i], (endi + 1) - i); } printf("Looking up %s...\n", ctx->hostname); valid_domain_name = 0; for(hostnamei=0; hostnamei<strlen(ctx->hostname); hostnamei++) { if(ctx->hostname[hostnamei]>='A' && ctx->hostname[hostnamei]<='z') { valid_domain_name = 1; break; } } if(valid_domain_name) { if((host = gethostbyname(ctx->hostname)) == NULL) { return YELLHTTP_EDNSRESOLV; } serverip = *((unsigned long *) host->h_addr_list[0]); } else { serverip = inet_addr(ctx->hostname); } client_addr.sin_family = AF_INET; client_addr.sin_port = htons(ctx->port); client_addr.sin_addr.s_addr = serverip; ctx->sock_client = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if(ctx->sock_client<0) { if(ctx->sock_client == -1) { printf("Failed to create socket: %d\n", ctx->sock_client); return YELLHTTP_ESOCK; } else { printf("socket() returned %d, ignoring...\n", ctx->sock_client); } } printf("Connecting to %s...\n", ctx->hostname); if((retval = connect(ctx->sock_client, (struct sockaddr *)&client_addr, sizeof(client_addr)))<0) { printf("Failed: %d\n", retval); return YELLHTTP_ECONN; } #ifdef ENABLESSL SSL_METHOD* method; SSL_CTX* sslctx; SSL* ssl; if(ctx->SSL) { InitCyaSSL(); CyaSSL_Debugging_ON(); method = SSLv3_client_method(); if(method)sslctx = SSL_CTX_new(method); if(sslctx)SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, 0); if(sslctx)ssl = SSL_new(sslctx); if(ssl)SSL_set_fd(ssl, ctx->sock_client); if(method==NULL || sslctx==NULL || ssl==NULL) { if(method==NULL)printf("Method init failure "); if(method==NULL)printf("SSL ctx init failure "); if(method==NULL)printf("SSL init failure "); err = SSL_get_error(ssl, 0); printf("sslerr = %d, %s\n", err, ERR_error_string(err, errbuffer)); shutdown(ctx->sock_client,0); close(ctx->sock_client); if(sslctx)SSL_CTX_free(sslctx); if(ssl)SSL_free(ssl); FreeCyaSSL(); return err; } printf("Connecting to %s with SSL...\n", ctx->hostname); if(SSL_connect(ssl)!=SSL_SUCCESS) { err = SSL_get_error(ssl, 0); printf("sslerr = %d, %s\n", err, ERR_error_string(err, errbuffer)); shutdown(ctx->sock_client,0); close(ctx->sock_client); SSL_CTX_free(sslctx); SSL_free(ssl); FreeCyaSSL(); return err; } } #endif if(stat(ctx->filename, &filestatus)==0 && !(ctx->server_flags & YELLHTTP_SRVFLAG_NOCACHE)) { memset(modifiedsincedate, 0, 512); memset(hdrstr, 0, 512); YellHttp_GenDate(modifiedsincedate, filestatus.st_mtime, ctx); sprintf(hdrstr, "If-Modified-Since: %s\r\n", modifiedsincedate); send_modifiedsince_hdr = 1; } memset(request_type, 0, 8); if(strlen(ctx->request_type)>0) { strncpy(request_type, ctx->request_type, 8); if(strncmp(request_type, "HEAD", 4)==0)stop = 1; } else { strncpy(request_type, "GET", 8); } snprintf((char*)ctx->sendbuf, SENDBUFSZ, "%s %s HTTP/%s\r\nHost: %s\r\nUser-Agent: %s\r\nConnection: close\r\n", request_type, ctx->uri, ctx->httpversion, ctx->hostname, ctx->useragent); if(send_modifiedsince_hdr)strncat((char*)ctx->sendbuf, hdrstr, SENDBUFSZ); if(ctx->range_end!=0) { memset(hdrstr, 0, 512); snprintf(hdrstr, 512, "Range: bytes=%d-%d\r\n", ctx->range_start, ctx->range_end); strncat((char*)ctx->sendbuf, hdrstr, SENDBUFSZ); } if(ctx->authenticated) { #ifdef ENABLESSL if(ctx->auth_type==1)YellHttp_GenDigestAuthHdr(ctx); #endif strncat((char*)ctx->sendbuf, ctx->authorization_header, SENDBUFSZ); } if(strncmp(ctx->request_type, "POST", 4)==0) { if(ctx->postdata && ctx->postdata>0) { snprintf(hdrstr, 512, "Content-Type: %s\r\nContent-Length: %d\r\n", ctx->content_type, ctx->postdata_length); strncat((char*)ctx->sendbuf, hdrstr, SENDBUFSZ); } } if(strlen(ctx->headers)>0)strncat((char*)ctx->sendbuf, ctx->headers, SENDBUFSZ); strncat((char*)ctx->sendbuf, "\r\n", SENDBUFSZ); printf("Sending request...\n"); if(!ctx->SSL) { YellHttp_SendData(ctx->sock_client, ctx->sendbuf, strlen((char*)ctx->sendbuf)); } else { #ifdef ENABLESSL SSL_write(ssl, ctx->sendbuf, strlen((char*)ctx->sendbuf)); #endif } if(strncmp(ctx->request_type, "POST", 4)==0) { printf("Sending POST data...\n"); if(ctx->postdata==NULL || ctx->postdata_length==0) { printf("Ctx->postdata is NULL, or postdata_length is zero.\n"); shutdown(ctx->sock_client,0); close(ctx->sock_client); SSL_CTX_free(sslctx); SSL_free(ssl); FreeCyaSSL(); return YELLHTTP_EINVAL; } if(!ctx->SSL) { YellHttp_SendData(ctx->sock_client, ctx->postdata, ctx->postdata_length); } else { #ifdef ENABLESSL SSL_write(ssl, ctx->postdata, ctx->postdata_length); #endif } } hdrfield = (char*)malloc(512); hdrval = (char*)malloc(512); printf("Waiting for response...(Headers)\n"); fhttpdump = fopen("httpheaders", "wb"); if(fhttpdump==NULL) { #ifdef ENABLESSL if(ctx->SSL) { SSL_CTX_free(sslctx); SSL_free(ssl); FreeCyaSSL(); } #endif shutdown(ctx->sock_client,0); close(ctx->sock_client); free(hdrfield); free(hdrval); return YELLHTTP_EFILE; } while(1) { if(!ctx->SSL) { recvlen = YellHttp_RecvData(ctx->sock_client, &ctx->recvbuf[headerspos], 1); } else { #ifdef ENABLESSL recvlen = SSL_read(ssl, &ctx->recvbuf[headerspos], 1); #endif } if(recvlen<=0) { stop = 1; break; } fwrite(&ctx->recvbuf[headerspos], 1, 1, fhttpdump); if(ctx->recvbuf[headerspos]==0x0a) { ctx->recvbuf[headerspos+1]=0; if(strlen((char*)ctx->recvbuf)<3) { headerspos = 0; break; } if(headerspos>4) { if(linenum==0) { sscanf((char*)&ctx->recvbuf[9], "%d", &ctx->http_status); memcpy(ctx->httpversion, &ctx->recvbuf[5], 3); printf("HTTP status: %d\n", ctx->http_status); if(ctx->http_status==304)stop = 1; if(ctx->http_status==401) { ctx->auth_requirederrors++; } else { ctx->auth_requirederrors = 0; } } else { memset(hdrfield, 0, 512); memset(hdrval, 0, 512); pos = 0; pos2 = 0; while(ctx->recvbuf[pos]!=':' && ctx->recvbuf[pos]!=0x0d && pos2<255) { hdrfield[pos2] = ctx->recvbuf[pos]; pos++; pos2++; } if(ctx->recvbuf[pos]==':') { pos+=2; pos2 = 0; while(ctx->recvbuf[pos]!=0x0d && pos2<255) { hdrval[pos2] = ctx->recvbuf[pos]; pos++; pos2++; } } for(i=0; i<32; i++) { if(headercb_array[i].cb==NULL)continue; if(strcmp(headercb_array[i].hdrfield, hdrfield)==0) { headercb_array[i].cb((char*)ctx->recvbuf, hdrfield, hdrval, ctx, headercb_array[i].usrarg); } } } linenum++; headerspos = 0; continue; } } headerspos++; } fclose(fhttpdump); free(hdrfield); free(hdrval); if(!stop) { printf("Receiving content, filename %s ...\n", ctx->filename); fhttpdump = fopen(ctx->filename, "wb"); content_len = ctx->content_length; if(fhttpdump==NULL) { #ifdef ENABLESSL if(ctx->SSL) { SSL_CTX_free(sslctx); SSL_free(ssl); FreeCyaSSL(); } #endif shutdown(ctx->sock_client,0); close(ctx->sock_client); return YELLHTTP_EFILE; } if(!ctx->SSL) { if(content_len) { while(content_len) { recvlen = YellHttp_RecvData(ctx->sock_client, ctx->recvbuf, RECVBUFSZ); fwrite(ctx->recvbuf, 1, recvlen, fhttpdump); content_len-= recvlen; } } else { while((recvlen = YellHttp_RecvData(ctx->sock_client, ctx->recvbuf, RECVBUFSZ))!=0) { fwrite(ctx->recvbuf, 1, recvlen, fhttpdump); } } } else { #ifdef ENABLESSL if(content_len) { while(content_len) { recvlen = SSL_read(ssl, ctx->recvbuf, RECVBUFSZ); fwrite(ctx->recvbuf, 1, recvlen, fhttpdump); content_len-= recvlen; } } else { while((recvlen = SSL_read(ssl, ctx->recvbuf, RECVBUFSZ))!=0) { fwrite(ctx->recvbuf, 1, recvlen, fhttpdump); } } #endif } fclose(fhttpdump); } #ifdef ENABLESSL if(ctx->SSL) { SSL_CTX_free(sslctx); SSL_free(ssl); FreeCyaSSL(); } #endif shutdown(ctx->sock_client,0); close(ctx->sock_client); if((ctx->http_status>=301 && ctx->http_status<=303) && !(ctx->server_flags & YELLHTTP_SRVFLAG_DISABLEREDIR)) { printf("Redirected: %s\n", ctx->redirecturl); return YellHttp_ExecRequest(ctx, ctx->redirecturl); } if(ctx->http_status==401 && ctx->authenticated) { if(ctx->authenticated==1) { return YellHttp_ExecRequest(ctx, url); } } if(ctx->http_status>=400)return -ctx->http_status; if(ctx->authenticated) { ctx->auth_nc++; } return 0; }
THREAD_RETURN CYASSL_THREAD server_test(void* args) { SOCKET_T sockfd = 0; SOCKET_T clientfd = 0; SSL_METHOD* method = 0; SSL_CTX* ctx = 0; SSL* ssl = 0; char msg[] = "I hear you fa shizzle!"; char input[80]; int idx; int ch; int version = SERVER_DEFAULT_VERSION; int doCliCertCheck = 1; int useAnyAddr = 0; word16 port = wolfSSLPort; int usePsk = 0; int useAnon = 0; int doDTLS = 0; int needDH = 0; int useNtruKey = 0; int nonBlocking = 0; int trackMemory = 0; int fewerPackets = 0; int pkCallbacks = 0; int serverReadyFile = 0; int wc_shutdown = 0; int resume = 0; /* do resume, and resume count */ int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS; int ret; char* alpnList = NULL; unsigned char alpn_opt = 0; char* cipherList = NULL; const char* verifyCert = cliCert; const char* ourCert = svrCert; const char* ourKey = svrKey; const char* ourDhParam = dhParam; int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; #ifndef NO_PSK int sendPskIdentityHint = 1; #endif #ifdef HAVE_SNI char* sniHostName = NULL; #endif #ifdef HAVE_OCSP int useOcsp = 0; char* ocspUrl = NULL; #endif ((func_args*)args)->return_code = -1; /* error state */ #ifdef NO_RSA verifyCert = (char*)cliEccCert; ourCert = (char*)eccCert; ourKey = (char*)eccKey; #endif (void)trackMemory; (void)pkCallbacks; (void)needDH; (void)ourKey; (void)ourCert; (void)ourDhParam; (void)verifyCert; (void)useNtruKey; (void)doCliCertCheck; (void)minDhKeyBits; (void)alpnList; (void)alpn_opt; #ifdef CYASSL_TIRTOS fdOpenSession(Task_self()); #endif while ((ch = mygetopt(argc, argv, "?dbstnNufrRawPIp:v:l:A:c:k:Z:S:oO:D:L:")) != -1) { switch (ch) { case '?' : Usage(); exit(EXIT_SUCCESS); case 'd' : doCliCertCheck = 0; break; case 'b' : useAnyAddr = 1; break; case 's' : usePsk = 1; break; case 't' : #ifdef USE_WOLFSSL_MEMORY trackMemory = 1; #endif break; case 'n' : useNtruKey = 1; break; case 'u' : doDTLS = 1; break; case 'f' : fewerPackets = 1; break; case 'R' : serverReadyFile = 1; break; case 'r' : #ifndef NO_SESSION_CACHE resume = 1; #endif break; case 'P' : #ifdef HAVE_PK_CALLBACKS pkCallbacks = 1; #endif break; case 'p' : port = (word16)atoi(myoptarg); #if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API) if (port == 0) err_sys("port number cannot be 0"); #endif break; case 'w' : wc_shutdown = 1; break; case 'v' : version = atoi(myoptarg); if (version < 0 || version > 3) { Usage(); exit(MY_EX_USAGE); } break; case 'l' : cipherList = myoptarg; break; case 'A' : verifyCert = myoptarg; break; case 'c' : ourCert = myoptarg; break; case 'k' : ourKey = myoptarg; break; case 'D' : #ifndef NO_DH ourDhParam = myoptarg; #endif break; case 'Z' : #ifndef NO_DH minDhKeyBits = atoi(myoptarg); if (minDhKeyBits <= 0 || minDhKeyBits > 16000) { Usage(); exit(MY_EX_USAGE); } #endif break; case 'N': nonBlocking = 1; break; case 'S' : #ifdef HAVE_SNI sniHostName = myoptarg; #endif break; case 'o' : #ifdef HAVE_OCSP useOcsp = 1; #endif break; case 'O' : #ifdef HAVE_OCSP useOcsp = 1; ocspUrl = myoptarg; #endif break; case 'a' : #ifdef HAVE_ANON useAnon = 1; #endif break; case 'I': #ifndef NO_PSK sendPskIdentityHint = 0; #endif break; case 'L' : #ifdef HAVE_ALPN alpnList = myoptarg; if (alpnList[0] == 'C' && alpnList[1] == ':') alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH; else if (alpnList[0] == 'F' && alpnList[1] == ':') alpn_opt = WOLFSSL_ALPN_FAILED_ON_MISMATCH; else { Usage(); exit(MY_EX_USAGE); } alpnList += 2; #endif break; default: Usage(); exit(MY_EX_USAGE); } } myoptind = 0; /* reset for test cases */ /* sort out DTLS versus TLS versions */ if (version == CLIENT_INVALID_VERSION) { if (doDTLS) version = CLIENT_DTLS_DEFAULT_VERSION; else version = CLIENT_DEFAULT_VERSION; } else { if (doDTLS) { if (version == 3) version = -2; else version = -1; } } #ifdef USE_CYASSL_MEMORY if (trackMemory) InitMemoryTracker(); #endif switch (version) { #ifndef NO_OLD_TLS #ifdef WOLFSSL_ALLOW_SSLV3 case 0: method = SSLv3_server_method(); break; #endif #ifndef NO_TLS case 1: method = TLSv1_server_method(); break; case 2: method = TLSv1_1_server_method(); break; #endif #endif #ifndef NO_TLS case 3: method = TLSv1_2_server_method(); break; #endif #ifdef CYASSL_DTLS #ifndef NO_OLD_TLS case -1: method = DTLSv1_server_method(); break; #endif case -2: method = DTLSv1_2_server_method(); break; #endif default: err_sys("Bad SSL version"); } if (method == NULL) err_sys("unable to get method"); ctx = SSL_CTX_new(method); if (ctx == NULL) err_sys("unable to get ctx"); #if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \ defined(HAVE_POLY1305) if (TicketInit() != 0) err_sys("unable to setup Session Ticket Key context"); wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb); #endif if (cipherList) if (SSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS) err_sys("server can't set cipher list 1"); #ifdef CYASSL_LEANPSK usePsk = 1; #endif #if defined(NO_RSA) && !defined(HAVE_ECC) usePsk = 1; #endif if (fewerPackets) CyaSSL_CTX_set_group_messages(ctx); #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) if (!usePsk && !useAnon) { if (SSL_CTX_use_certificate_file(ctx, ourCert, SSL_FILETYPE_PEM) != SSL_SUCCESS) err_sys("can't load server cert file, check file and run from" " wolfSSL home dir"); } #endif #ifndef NO_DH wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits); #endif #ifdef HAVE_NTRU if (useNtruKey) { if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ourKey) != SSL_SUCCESS) err_sys("can't load ntru key file, " "Please run from wolfSSL home dir"); } #endif #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) if (!useNtruKey && !usePsk && !useAnon) { if (SSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM) != SSL_SUCCESS) err_sys("can't load server private key file, check file and run " "from wolfSSL home dir"); } #endif if (usePsk) { #ifndef NO_PSK SSL_CTX_set_psk_server_callback(ctx, my_psk_server_cb); if (sendPskIdentityHint == 1) SSL_CTX_use_psk_identity_hint(ctx, "cyassl server"); if (cipherList == NULL) { const char *defaultCipherList; #if defined(HAVE_AESGCM) && !defined(NO_DH) defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; needDH = 1; #elif defined(HAVE_NULL_CIPHER) defaultCipherList = "PSK-NULL-SHA256"; #else defaultCipherList = "PSK-AES128-CBC-SHA256"; #endif if (SSL_CTX_set_cipher_list(ctx, defaultCipherList) != SSL_SUCCESS) err_sys("server can't set cipher list 2"); } #endif } if (useAnon) { #ifdef HAVE_ANON CyaSSL_CTX_allow_anon_cipher(ctx); if (cipherList == NULL) { if (SSL_CTX_set_cipher_list(ctx, "ADH-AES128-SHA") != SSL_SUCCESS) err_sys("server can't set cipher list 4"); } #endif } #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) /* if not using PSK, verify peer with certs */ if (doCliCertCheck && usePsk == 0 && useAnon == 0) { SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0); if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) != SSL_SUCCESS) err_sys("can't load ca file, Please run from wolfSSL home dir"); } #endif #if defined(CYASSL_SNIFFER) /* don't use EDH, can't sniff tmp keys */ if (cipherList == NULL) { if (SSL_CTX_set_cipher_list(ctx, "AES256-SHA256") != SSL_SUCCESS) err_sys("server can't set cipher list 3"); } #endif #ifdef HAVE_SNI if (sniHostName) if (CyaSSL_CTX_UseSNI(ctx, CYASSL_SNI_HOST_NAME, sniHostName, XSTRLEN(sniHostName)) != SSL_SUCCESS) err_sys("UseSNI failed"); #endif while (1) { /* allow resume option */ if (resume > 1) { /* already did listen, just do accept */ if (doDTLS == 0) { SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); clientfd = accept(sockfd, (struct sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); } else { tcp_listen(&sockfd, &port, useAnyAddr, doDTLS); clientfd = sockfd; } #ifdef USE_WINDOWS_API if (clientfd == INVALID_SOCKET) err_sys("tcp accept failed"); #else if (clientfd == -1) err_sys("tcp accept failed"); #endif } ssl = SSL_new(ctx); if (ssl == NULL) err_sys("unable to get SSL"); #ifndef NO_HANDSHAKE_DONE_CB wolfSSL_SetHsDoneCb(ssl, myHsDoneCb, NULL); #endif #ifdef HAVE_CRL CyaSSL_EnableCRL(ssl, 0); CyaSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, CYASSL_CRL_MONITOR | CYASSL_CRL_START_MON); CyaSSL_SetCRL_Cb(ssl, CRL_CallBack); #endif #ifdef HAVE_OCSP if (useOcsp) { if (ocspUrl != NULL) { CyaSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl); CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE | CYASSL_OCSP_URL_OVERRIDE); } else CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE); } #endif #ifdef HAVE_PK_CALLBACKS if (pkCallbacks) SetupPkCallbacks(ctx, ssl); #endif if (resume < 2) { /* do listen and accept */ tcp_accept(&sockfd, &clientfd, (func_args*)args, port, useAnyAddr, doDTLS, serverReadyFile); } SSL_set_fd(ssl, clientfd); #ifdef HAVE_ALPN if (alpnList != NULL) { printf("ALPN accepted protocols list : %s\n", alpnList); wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList), alpn_opt); } #endif #ifdef WOLFSSL_DTLS if (doDTLS) { SOCKADDR_IN_T cliaddr; byte b[1500]; int n; socklen_t len = sizeof(cliaddr); /* For DTLS, peek at the next datagram so we can get the client's * address and set it into the ssl object later to generate the * cookie. */ n = (int)recvfrom(sockfd, (char*)b, sizeof(b), MSG_PEEK, (struct sockaddr*)&cliaddr, &len); if (n <= 0) err_sys("recvfrom failed"); wolfSSL_dtls_set_peer(ssl, &cliaddr, len); } #endif if (usePsk == 0 || useAnon == 1 || cipherList != NULL || needDH == 1) { #if !defined(NO_FILESYSTEM) && !defined(NO_DH) && !defined(NO_ASN) CyaSSL_SetTmpDH_file(ssl, ourDhParam, SSL_FILETYPE_PEM); #elif !defined(NO_DH) SetDH(ssl); /* repick suites with DHE, higher priority than PSK */ #endif } #ifndef CYASSL_CALLBACKS if (nonBlocking) { CyaSSL_set_using_nonblock(ssl, 1); tcp_set_nonblocking(&clientfd); NonBlockingSSL_Accept(ssl); } else if (SSL_accept(ssl) != SSL_SUCCESS) { int err = SSL_get_error(ssl, 0); char buffer[CYASSL_MAX_ERROR_SZ]; printf("error = %d, %s\n", err, ERR_error_string(err, buffer)); err_sys("SSL_accept failed"); } #else NonBlockingSSL_Accept(ssl); #endif showPeer(ssl); #ifdef HAVE_ALPN if (alpnList != NULL) { int err; char *protocol_name = NULL; word16 protocol_nameSz = 0; err = wolfSSL_ALPN_GetProtocol(ssl, &protocol_name, &protocol_nameSz); if (err == SSL_SUCCESS) printf("Sent ALPN protocol : %s (%d)\n", protocol_name, protocol_nameSz); else if (err == SSL_ALPN_NOT_FOUND) printf("No ALPN response sent (no match)\n"); else printf("Getting ALPN protocol name failed\n"); } #endif idx = SSL_read(ssl, input, sizeof(input)-1); if (idx > 0) { input[idx] = 0; printf("Client message: %s\n", input); } else if (idx < 0) { int readErr = SSL_get_error(ssl, 0); if (readErr != SSL_ERROR_WANT_READ) err_sys("SSL_read failed"); } if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) err_sys("SSL_write failed"); #if defined(WOLFSSL_MDK_SHELL) && defined(HAVE_MDK_RTX) os_dly_wait(500) ; #elif defined (CYASSL_TIRTOS) Task_yield(); #endif if (doDTLS == 0) { ret = SSL_shutdown(ssl); if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) SSL_shutdown(ssl); /* bidirectional shutdown */ } SSL_free(ssl); if (resume == 1) { CloseSocket(clientfd); resume++; /* only do one resume for testing */ continue; } break; /* out of while loop, done with normal and resume option */ } SSL_CTX_free(ctx); CloseSocket(clientfd); CloseSocket(sockfd); ((func_args*)args)->return_code = 0; #if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \ && defined(HAVE_THREAD_LS) ecc_fp_free(); /* free per thread cache */ #endif #ifdef USE_WOLFSSL_MEMORY if (trackMemory) ShowMemoryTracker(); #endif #ifdef CYASSL_TIRTOS fdCloseSession(Task_self()); #endif #if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \ defined(HAVE_POLY1305) TicketCleanup(); #endif #ifndef CYASSL_TIRTOS return 0; #endif }
ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block) { ssize_t r; int err = 0; wsh->x++; if (wsh->x > 250) ms_sleep(1); if (wsh->ssl) { do { r = SSL_read(wsh->ssl, data, bytes); if (r == -1) { err = SSL_get_error(wsh->ssl, r); if (!block && err == SSL_ERROR_WANT_READ) { r = -2; goto end; } if (block) { wsh->x++; ms_sleep(10); } } } while (r == -1 && err == SSL_ERROR_WANT_READ && wsh->x < 100); goto end; } do { r = recv(wsh->sock, data, bytes, 0); if (r == -1) { if (!block && xp_is_blocking(xp_errno())) { r = -2; goto end; } if (block) { wsh->x++; ms_sleep(10); } } } while (r == -1 && xp_is_blocking(xp_errno()) && wsh->x < 100); if (wsh->x >= 1000 || (block && wsh->x >= 100)) { r = -1; } end: if (r > 0) { *((char *)data + r) = '\0'; } if (r >= 0) { wsh->x = 0; } return r; }
int MAIN(int argc, char **argv) { double totalTime = 0.0; int nConn = 0; SSL *scon=NULL; long finishtime=0; int ret=1,i; MS_STATIC char buf[1024*8]; int ver; apps_startup(); s_time_init(); if (bio_err == NULL) bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); s_time_meth=SSLv23_client_method(); /* parse the command line arguments */ if( parseArgs( argc, argv ) < 0 ) goto end; OpenSSL_add_ssl_algorithms(); if ((tm_ctx=SSL_CTX_new(s_time_meth)) == NULL) return(1); SSL_CTX_set_quiet_shutdown(tm_ctx,1); if (st_bugs) SSL_CTX_set_options(tm_ctx,SSL_OP_ALL); SSL_CTX_set_cipher_list(tm_ctx,tm_cipher); if(!set_cert_stuff(tm_ctx,t_cert_file,t_key_file)) goto end; SSL_load_error_strings(); if ((!SSL_CTX_load_verify_locations(tm_ctx,CAfile,CApath)) || (!SSL_CTX_set_default_verify_paths(tm_ctx))) { /* BIO_printf(bio_err,"error setting default verify locations\n"); */ ERR_print_errors(bio_err); /* goto end; */ } if (tm_cipher == NULL) tm_cipher = getenv("SSL_CIPHER"); if (tm_cipher == NULL ) { fprintf( stderr, "No CIPHER specified\n" ); } if (!(perform & 1)) goto next; printf( "Collecting connection statistics for %d seconds\n", maxTime ); /* Loop and time how long it takes to make connections */ bytes_read=0; finishtime=(long)time(NULL)+maxTime; tm_Time_F(START); for (;;) { if (finishtime < (long)time(NULL)) break; #ifdef WIN32_STUFF if( flushWinMsgs(0) == -1 ) goto end; if( waitingToDie || exitNow ) /* we're dead */ goto end; #endif if( (scon = doConnection( NULL )) == NULL ) goto end; if (s_www_path != NULL) { BIO_snprintf(buf,sizeof buf,"GET %s HTTP/1.0\r\n\r\n",s_www_path); SSL_write(scon,buf,strlen(buf)); while ((i=SSL_read(scon,buf,sizeof(buf))) > 0) bytes_read+=i; } #ifdef NO_SHUTDOWN SSL_set_shutdown(scon,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); #else SSL_shutdown(scon); #endif SHUTDOWN2(SSL_get_fd(scon)); nConn += 1; if (SSL_session_reused(scon)) ver='r'; else { ver=SSL_version(scon); if (ver == TLS1_VERSION) ver='t'; else if (ver == SSL3_VERSION) ver='3'; else ver='*'; } fputc(ver,stdout); fflush(stdout); SSL_free( scon ); scon=NULL; } totalTime += tm_Time_F(STOP); /* Add the time for this iteration */ i=(int)((long)time(NULL)-finishtime+maxTime); printf( "\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double)nConn/totalTime),bytes_read); printf( "%d connections in %ld real seconds, %ld bytes read per connection\n",nConn,(long)time(NULL)-finishtime+maxTime,bytes_read/nConn); /* Now loop and time connections using the same session id over and over */ next: if (!(perform & 2)) goto end; printf( "\n\nNow timing with session id reuse.\n" ); /* Get an SSL object so we can reuse the session id */ if( (scon = doConnection( NULL )) == NULL ) { fprintf( stderr, "Unable to get connection\n" ); goto end; } if (s_www_path != NULL) { BIO_snprintf(buf,sizeof buf,"GET %s HTTP/1.0\r\n\r\n",s_www_path); SSL_write(scon,buf,strlen(buf)); while (SSL_read(scon,buf,sizeof(buf)) > 0) ; } #ifdef NO_SHUTDOWN SSL_set_shutdown(scon,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); #else SSL_shutdown(scon); #endif SHUTDOWN2(SSL_get_fd(scon)); nConn = 0; totalTime = 0.0; finishtime=(long)time(NULL)+maxTime; printf( "starting\n" ); bytes_read=0; tm_Time_F(START); for (;;) { if (finishtime < (long)time(NULL)) break; #ifdef WIN32_STUFF if( flushWinMsgs(0) == -1 ) goto end; if( waitingToDie || exitNow ) /* we're dead */ goto end; #endif if( (doConnection( scon )) == NULL ) goto end; if (s_www_path) { BIO_snprintf(buf,sizeof buf,"GET %s HTTP/1.0\r\n\r\n",s_www_path); SSL_write(scon,buf,strlen(buf)); while ((i=SSL_read(scon,buf,sizeof(buf))) > 0) bytes_read+=i; } #ifdef NO_SHUTDOWN SSL_set_shutdown(scon,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); #else SSL_shutdown(scon); #endif SHUTDOWN2(SSL_get_fd(scon)); nConn += 1; if (SSL_session_reused(scon)) ver='r'; else { ver=SSL_version(scon); if (ver == TLS1_VERSION) ver='t'; else if (ver == SSL3_VERSION) ver='3'; else ver='*'; } fputc(ver,stdout); fflush(stdout); } totalTime += tm_Time_F(STOP); /* Add the time for this iteration*/ printf( "\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double)nConn/totalTime),bytes_read); printf( "%d connections in %ld real seconds, %ld bytes read per connection\n",nConn,(long)time(NULL)-finishtime+maxTime,bytes_read/nConn); ret=0; end: if (scon != NULL) SSL_free(scon); if (tm_ctx != NULL) { SSL_CTX_free(tm_ctx); tm_ctx=NULL; } apps_shutdown(); OPENSSL_EXIT(ret); }
static int connection_handle_read_ssl(server *srv, connection *con) { #ifdef USE_OPENSSL int r, ssl_err, len, count = 0, read_offset, toread; buffer *b = NULL; if (!con->conf.is_ssl) return -1; ERR_clear_error(); do { if (NULL != con->read_queue->last) { b = con->read_queue->last->mem; } if (NULL == b || b->size - b->used < 1024) { b = chunkqueue_get_append_buffer(con->read_queue); len = SSL_pending(con->ssl); if (len < 4*1024) len = 4*1024; /* always alloc >= 4k buffer */ buffer_prepare_copy(b, len + 1); /* overwrite everything with 0 */ memset(b->ptr, 0, b->size); } read_offset = (b->used > 0) ? b->used - 1 : 0; toread = b->size - 1 - read_offset; len = SSL_read(con->ssl, b->ptr + read_offset, toread); if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) { connection_set_state(srv, con, CON_STATE_ERROR); log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client"); return -1; } if (len > 0) { if (b->used > 0) b->used--; b->used += len; b->ptr[b->used++] = '\0'; con->bytes_read += len; count += len; } } while (len == toread && count < MAX_READ_LIMIT); if (len < 0) { int oerrno = errno; switch ((r = SSL_get_error(con->ssl, len))) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: con->is_readable = 0; /* the manual says we have to call SSL_read with the same arguments next time. * we ignore this restriction; no one has complained about it in 1.5 yet, so it probably works anyway. */ return 0; case SSL_ERROR_SYSCALL: /** * man SSL_get_error() * * SSL_ERROR_SYSCALL * Some I/O error occurred. The OpenSSL error queue may contain more * information on the error. If the error queue is empty (i.e. * ERR_get_error() returns 0), ret can be used to find out more about * the error: If ret == 0, an EOF was observed that violates the * protocol. If ret == -1, the underlying BIO reported an I/O error * (for socket I/O on Unix systems, consult errno for details). * */ while((ssl_err = ERR_get_error())) { /* get all errors from the error-queue */ log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", r, ERR_error_string(ssl_err, NULL)); } switch(oerrno) { default: log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", len, r, oerrno, strerror(oerrno)); break; } break; case SSL_ERROR_ZERO_RETURN: /* clean shutdown on the remote side */ if (r == 0) { /* FIXME: later */ } /* fall thourgh */ default: while((ssl_err = ERR_get_error())) { switch (ERR_GET_REASON(ssl_err)) { case SSL_R_SSL_HANDSHAKE_FAILURE: case SSL_R_TLSV1_ALERT_UNKNOWN_CA: case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN: case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE: if (!con->conf.log_ssl_noise) continue; break; default: break; } /* get all errors from the error-queue */ log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", r, ERR_error_string(ssl_err, NULL)); } break; } connection_set_state(srv, con, CON_STATE_ERROR); return -1; } else if (len == 0) { con->is_readable = 0; /* the other end close the connection -> KEEP-ALIVE */ return -2; } else { joblist_append(srv, con); } return 0; #else UNUSED(srv); UNUSED(con); return -1; #endif }
void client_test(void* args) { SOCKET_T sockfd = 0; SSL_METHOD* method = 0; SSL_CTX* ctx = 0; SSL* ssl = 0; #ifdef TEST_RESUME SSL* sslResume = 0; SSL_SESSION* session = 0; char resumeMsg[] = "resuming cyassl!"; int resumeSz = sizeof(resumeMsg); #endif char msg[64] = "hello cyassl!"; char reply[1024]; int input; int msgSz = strlen(msg); int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; ((func_args*)args)->return_code = -1; /* error state */ #if defined(CYASSL_DTLS) method = DTLSv1_client_method(); #elif !defined(NO_TLS) method = SSLv23_client_method(); #else method = SSLv3_client_method(); #endif ctx = SSL_CTX_new(method); #ifndef NO_PSK SSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb); #endif #ifdef OPENSSL_EXTRA SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif #ifdef CYASSL_SNIFFER /* don't use EDH, can't sniff tmp keys */ SSL_CTX_set_cipher_list(ctx, "AES256-SHA"); #endif #ifndef NO_FILESYSTEM if (SSL_CTX_load_verify_locations(ctx, caCert, 0) != SSL_SUCCESS) err_sys("can't load ca file"); #ifdef HAVE_ECC if (SSL_CTX_load_verify_locations(ctx, eccCert, 0) != SSL_SUCCESS) err_sys("can't load ca file"); #endif #else load_buffer(ctx, caCert, CYASSL_CA); #endif #ifdef VERIFY_CALLBACK SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify); #endif if (argc == 3) { /* ./client server securePort */ SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); /* TODO: add ca cert */ /* this is just to allow easy testing of other servers */ tcp_connect(&sockfd, argv[1], (short)atoi(argv[2])); } else if (argc == 1) { /* ./client // plain mode */ /* for client cert authentication if server requests */ #ifndef NO_FILESYSTEM if (SSL_CTX_use_certificate_file(ctx, cliCert, SSL_FILETYPE_PEM) != SSL_SUCCESS) err_sys("can't load client cert file"); if (SSL_CTX_use_PrivateKey_file(ctx, cliKey, SSL_FILETYPE_PEM) != SSL_SUCCESS) err_sys("can't load client key file"); #else load_buffer(ctx, cliCert, CYASSL_CERT); load_buffer(ctx, cliKey, CYASSL_KEY); #endif tcp_connect(&sockfd, yasslIP, yasslPort); } else if (argc == 2) { /* time passed in number of connects give average */ int times = atoi(argv[1]); int i = 0; double start = current_time(), avg; for (i = 0; i < times; i++) { tcp_connect(&sockfd, yasslIP, yasslPort); ssl = SSL_new(ctx); SSL_set_fd(ssl, sockfd); if (SSL_connect(ssl) != SSL_SUCCESS) err_sys("SSL_connect failed"); SSL_shutdown(ssl); SSL_free(ssl); CloseSocket(sockfd); } avg = current_time() - start; avg /= times; avg *= 1000; /* milliseconds */ printf("SSL_connect avg took:%6.3f milliseconds\n", avg); SSL_CTX_free(ctx); ((func_args*)args)->return_code = 0; return; } else err_sys("usage: ./client server securePort"); ssl = SSL_new(ctx); SSL_set_fd(ssl, sockfd); if (argc != 3) CyaSSL_check_domain_name(ssl, "www.yassl.com"); #ifdef NON_BLOCKING tcp_set_nonblocking(&sockfd); NonBlockingSSL_Connect(ssl); #else #ifndef CYASSL_CALLBACKS if (SSL_connect(ssl) != SSL_SUCCESS) { /* see note at top of README */ int err = SSL_get_error(ssl, 0); char buffer[80]; printf("err = %d, %s\n", err, ERR_error_string(err, buffer)); err_sys("SSL_connect failed");/* if you're getting an error here */ } #else timeout.tv_sec = 2; timeout.tv_usec = 0; NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */ #endif #endif showPeer(ssl); if (argc == 3) { printf("SSL connect ok, sending GET...\n"); msgSz = 28; strncpy(msg, "GET /index.html HTTP/1.0\r\n\r\n", msgSz); } if (SSL_write(ssl, msg, msgSz) != msgSz) err_sys("SSL_write failed"); input = SSL_read(ssl, reply, sizeof(reply)); if (input > 0) { reply[input] = 0; printf("Server response: %s\n", reply); if (argc == 3) { /* get html */ while (1) { input = SSL_read(ssl, reply, sizeof(reply)); if (input > 0) { reply[input] = 0; printf("%s\n", reply); } else break; } } } #ifdef TEST_RESUME #ifdef CYASSL_DTLS strncpy(msg, "break", 6); msgSz = (int)strlen(msg); /* try to send session close */ SSL_write(ssl, msg, msgSz); #endif session = SSL_get_session(ssl); sslResume = SSL_new(ctx); #endif SSL_shutdown(ssl); SSL_free(ssl); CloseSocket(sockfd); #ifdef TEST_RESUME #ifdef CYASSL_DTLS #ifdef USE_WINDOWS_API Sleep(500); #else sleep(1); #endif #endif if (argc == 3) tcp_connect(&sockfd, argv[1], (short)atoi(argv[2])); else tcp_connect(&sockfd, yasslIP, yasslPort); SSL_set_fd(sslResume, sockfd); SSL_set_session(sslResume, session); showPeer(sslResume); if (SSL_connect(sslResume) != SSL_SUCCESS) err_sys("SSL resume failed"); #ifdef OPENSSL_EXTRA if (SSL_session_reused(sslResume)) printf("reused session id\n"); else printf("didn't reuse session id!!!\n"); #endif if (SSL_write(sslResume, resumeMsg, resumeSz) != resumeSz) err_sys("SSL_write failed"); input = SSL_read(sslResume, reply, sizeof(reply)); if (input > 0) { reply[input] = 0; printf("Server resume response: %s\n", reply); } /* try to send session break */ SSL_write(sslResume, msg, msgSz); SSL_shutdown(sslResume); SSL_free(sslResume); #endif /* TEST_RESUME */ SSL_CTX_free(ctx); CloseSocket(sockfd); ((func_args*)args)->return_code = 0; }
static ssize_t read_socket_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out) { fd_set fds; int selrtn; ssize_t readret; size_t nread = 0; struct timeval timeout; /* just checking .... */ if (maxcnt <= 0) return(0); smb_read_error = 0; /* Blocking read */ if (time_out <= 0) { if (mincnt == 0) mincnt = maxcnt; while (nread < mincnt) { #ifdef WITH_SSL if(fd == sslFd){ readret = SSL_read(ssl, buf + nread, maxcnt - nread); }else{ readret = read(fd, buf + nread, maxcnt - nread); } #else /* WITH_SSL */ readret = read(fd, buf + nread, maxcnt - nread); #endif /* WITH_SSL */ if (readret == 0) { DEBUG(5,("read_socket_with_timeout: blocking read. EOF from client.\n")); smb_read_error = READ_EOF; return -1; } if (readret == -1) { DEBUG(0,("read_socket_with_timeout: read error = %s.\n", strerror(errno) )); smb_read_error = READ_ERROR; return -1; } nread += readret; } return((ssize_t)nread); } /* Most difficult - timeout read */ /* If this is ever called on a disk file and mincnt is greater then the filesize then system performance will suffer severely as select always returns true on disk files */ /* Set initial timeout */ timeout.tv_sec = (time_t)(time_out / 1000); timeout.tv_usec = (long)(1000 * (time_out % 1000)); for (nread=0; nread < mincnt; ) { FD_ZERO(&fds); FD_SET(fd,&fds); selrtn = sys_select(fd+1,&fds,&timeout); /* Check if error */ if(selrtn == -1) { /* something is wrong. Maybe the socket is dead? */ DEBUG(0,("read_socket_with_timeout: timeout read. select error = %s.\n", strerror(errno) )); smb_read_error = READ_ERROR; return -1; } /* Did we timeout ? */ if (selrtn == 0) { DEBUG(10,("read_socket_with_timeout: timeout read. select timed out.\n")); smb_read_error = READ_TIMEOUT; return -1; } #ifdef WITH_SSL if(fd == sslFd){ readret = SSL_read(ssl, buf + nread, maxcnt - nread); }else{ readret = read(fd, buf + nread, maxcnt - nread); } #else /* WITH_SSL */ readret = read(fd, buf+nread, maxcnt-nread); #endif /* WITH_SSL */ if (readret == 0) { /* we got EOF on the file descriptor */ DEBUG(5,("read_socket_with_timeout: timeout read. EOF from client.\n")); smb_read_error = READ_EOF; return -1; } if (readret == -1) { /* the descriptor is probably dead */ DEBUG(0,("read_socket_with_timeout: timeout read. read error = %s.\n", strerror(errno) )); smb_read_error = READ_ERROR; return -1; } nread += readret; } /* Return the number we got */ return((ssize_t)nread); }
/* * Process an EAP request */ eaptls_status_t eaptls_process(EAP_HANDLER *handler) { tls_session_t *tls_session = (tls_session_t *) handler->opaque; EAPTLS_PACKET *tlspacket; eaptls_status_t status; REQUEST *request = handler->request; RDEBUG2("processing EAP-TLS"); if (handler->certs) pairadd(&request->packet->vps, paircopy(handler->certs)); /* This case is when SSL generates Alert then we * send that alert to the client and then send the EAP-Failure */ status = eaptls_verify(handler); RDEBUG2("eaptls_verify returned %d\n", status); switch (status) { default: case EAPTLS_INVALID: case EAPTLS_FAIL: /* * Success means that we're done the initial * handshake. For TTLS, this means send stuff * back to the client, and the client sends us * more tunneled data. */ case EAPTLS_SUCCESS: return status; break; /* * Normal TLS request, continue with the "get rest * of fragments" phase. */ case EAPTLS_REQUEST: eaptls_request(handler->eap_ds, tls_session); return EAPTLS_HANDLED; break; /* * The handshake is done, and we're in the "tunnel * data" phase. */ case EAPTLS_OK: RDEBUG2("Done initial handshake"); /* * Get the rest of the fragments. */ case EAPTLS_FIRST_FRAGMENT: case EAPTLS_MORE_FRAGMENTS: case EAPTLS_LENGTH_INCLUDED: case EAPTLS_MORE_FRAGMENTS_WITH_LENGTH: break; } /* * Extract the TLS packet from the buffer. */ if ((tlspacket = eaptls_extract(request, handler->eap_ds, status)) == NULL) return EAPTLS_FAIL; /* * Get the session struct from the handler * * update the dirty_in buffer * * NOTE: This buffer will contain partial data when M bit is set. * * CAUTION while reinitializing this buffer, it should be * reinitialized only when this M bit is NOT set. */ if (tlspacket->dlen != (tls_session->record_plus)(&tls_session->dirty_in, tlspacket->data, tlspacket->dlen)) { eaptls_free(&tlspacket); RDEBUG("Exceeded maximum record size"); return EAPTLS_FAIL; } /* * No longer needed. */ eaptls_free(&tlspacket); /* * SSL initalization is done. Return. * * The TLS data will be in the tls_session structure. */ if (SSL_is_init_finished(tls_session->ssl)) { int err; /* * The initialization may be finished, but if * there more fragments coming, then send ACK, * and get the caller to continue the * conversation. */ if ((status == EAPTLS_MORE_FRAGMENTS) || (status == EAPTLS_MORE_FRAGMENTS_WITH_LENGTH) || (status == EAPTLS_FIRST_FRAGMENT)) { /* * Send the ACK. */ eaptls_send_ack(handler->eap_ds, tls_session->peap_flag); RDEBUG2("Init is done, but tunneled data is fragmented"); return EAPTLS_HANDLED; } /* * Decrypt the complete record. */ BIO_write(tls_session->into_ssl, tls_session->dirty_in.data, tls_session->dirty_in.used); /* * Clear the dirty buffer now that we are done with it * and init the clean_out buffer to store decrypted data */ (tls_session->record_init)(&tls_session->dirty_in); (tls_session->record_init)(&tls_session->clean_out); /* * Read (and decrypt) the tunneled data from the * SSL session, and put it into the decrypted * data buffer. */ err = SSL_read(tls_session->ssl, tls_session->clean_out.data, sizeof(tls_session->clean_out.data)); if (err < 0) { RDEBUG("SSL_read Error"); switch (SSL_get_error(tls_session->ssl, err)) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: RDEBUG("Error in fragmentation logic"); break; default: /* * FIXME: Call int_ssl_check? */ break; } return EAPTLS_FAIL; } if (err == 0) { RDEBUG("WARNING: No data inside of the tunnel."); } /* * Passed all checks, successfully decrypted data */ tls_session->clean_out.used = err; return EAPTLS_OK; } /* * Continue the handshake. */ return eaptls_operation(status, handler); }