/** * Return information about the connection. */ static int meth_info(lua_State *L) { int bits = 0; int algbits = 0; char buf[256] = {0}; const SSL_CIPHER *cipher; p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); cipher = SSL_get_current_cipher(ssl->ssl); if (!cipher) return 0; SSL_CIPHER_description(cipher, buf, sizeof(buf)); bits = SSL_CIPHER_get_bits(cipher, &algbits); lua_pushstring(L, buf); lua_pushnumber(L, bits); lua_pushnumber(L, algbits); lua_pushstring(L, SSL_get_version(ssl->ssl)); return 4; }
static void log_session_info(as_socket* sock) { if (! sock->ctx->log_session_info) return; SSL_CIPHER const* cipher = SSL_get_current_cipher(sock->ssl); if (cipher) { char desc[1024]; SSL_CIPHER_description(cipher, desc, sizeof(desc)); size_t len = strlen(desc); if (len > 0) { desc[len-1] = '\0'; // Trim trailing \n } as_log_info("TLS cipher: %s", desc); } else { as_log_warn("TLS no current cipher"); } }
const char * ssl_to_text(const SSL *ssl) { static char buf[256]; static char description[128]; char *tls_version = NULL; /* * SSL_get_cipher_version() does not know about the exact TLS version... * you have to pick it up from second field of the SSL cipher description ! */ SSL_CIPHER_description(SSL_get_current_cipher(ssl), description, sizeof description); tls_version = strchr(description, ' ') + 1; tls_version[strcspn(tls_version, " ")] = '\0'; (void)snprintf(buf, sizeof buf, "version=%s (%s), cipher=%s, bits=%d", SSL_get_cipher_version(ssl), tls_version, SSL_get_cipher_name(ssl), SSL_get_cipher_bits(ssl, NULL)); return (buf); }
static void print_cipher(CLI *c) { /* print negotiated cipher */ SSL_CIPHER *cipher; char *buf, *i, *j; cipher=(SSL_CIPHER *)SSL_get_current_cipher(c->ssl); buf=SSL_CIPHER_description(cipher, NULL, 0); i=j=buf; do { switch(*i) { case ' ': *j++=' '; while(i[1]==' ') ++i; break; case '\n': break; default: *j++=*i; } } while(*i++); s_log(LOG_INFO, "Negotiated ciphers: %s", buf); OPENSSL_free(buf); }
/* Parses the Kx, Enc, and Mac values out of the SSL_CIPHER_description and maps the values to the corresponding .NET enum value. */ static bool GetSslConnectionInfoFromDescription(const SSL_CIPHER* cipher, CipherAlgorithmType& dataCipherAlg, ExchangeAlgorithmType& keyExchangeAlg, HashAlgorithmType& dataHashAlg, DataHashSize& hashKeySize) { const int descriptionLength = 256; char description[descriptionLength] = {}; SSL_CIPHER_description(cipher, description, descriptionLength - 1); // ensure description is NULL-terminated const char* keyExchange; size_t keyExchangeLength; if (!GetDescriptionValue(description, "Kx=", 3, &keyExchange, keyExchangeLength)) { return false; } const char* encryption; size_t encryptionLength; if (!GetDescriptionValue(description, "Enc=", 4, &encryption, encryptionLength)) { return false; } const char* mac; size_t macLength; if (!GetDescriptionValue(description, "Mac=", 4, &mac, macLength)) { return false; } keyExchangeAlg = MapExchangeAlgorithmType(keyExchange, keyExchangeLength); dataCipherAlg = MapCipherAlgorithmType(encryption, encryptionLength); GetHashAlgorithmTypeAndSize(mac, macLength, dataHashAlg, hashKeySize); return true; }
/* This equivalent functionality was submitted for OpenSSL 1.1.1+ in * https://github.com/openssl/openssl/pull/1666 */ static int dtls_get_data_mtu(struct openconnect_info *vpninfo, int mtu) { int ivlen, maclen, blocksize = 0, pad = 0; #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) const SSL_CIPHER *s_ciph = SSL_get_current_cipher(vpninfo->dtls_ssl); int cipher_nid; const EVP_CIPHER *e_ciph; const EVP_MD *e_md; char wtf[128]; cipher_nid = SSL_CIPHER_get_cipher_nid(s_ciph); if (cipher_nid == NID_chacha20_poly1305) { ivlen = 0; /* Automatically derived from handshake and seqno */ maclen = 16; /* Poly1305 */ } else { e_ciph = EVP_get_cipherbynid(cipher_nid); switch (EVP_CIPHER_mode(e_ciph)) { case EVP_CIPH_GCM_MODE: ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN; maclen = EVP_GCM_TLS_TAG_LEN; break; case EVP_CIPH_CCM_MODE: ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN; SSL_CIPHER_description(s_ciph, wtf, sizeof(wtf)); if (strstr(wtf, "CCM8")) maclen = 8; else maclen = 16; break; case EVP_CIPH_CBC_MODE: blocksize = EVP_CIPHER_block_size(e_ciph); ivlen = EVP_CIPHER_iv_length(e_ciph); pad = 1; e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph)); maclen = EVP_MD_size(e_md); break; default: vpn_progress(vpninfo, PRG_ERR, _("Unable to calculate DTLS overhead for %s\n"), SSL_CIPHER_get_name(s_ciph)); ivlen = 0; maclen = DTLS_OVERHEAD; break; } } #else /* OpenSSL <= 1.0.2 only supports CBC ciphers with PSK */ ivlen = EVP_CIPHER_iv_length(EVP_CIPHER_CTX_cipher(vpninfo->dtls_ssl->enc_read_ctx)); maclen = EVP_MD_CTX_size(vpninfo->dtls_ssl->read_hash); blocksize = ivlen; pad = 1; #endif /* Even when it pretended to, OpenSSL never did encrypt-then-mac. * So the MAC is *inside* the encryption, unconditionally. * https://github.com/openssl/openssl/pull/1705 */ if (mtu < DTLS1_RT_HEADER_LENGTH + ivlen) return 0; mtu -= DTLS1_RT_HEADER_LENGTH + ivlen; /* For CBC mode round down to blocksize */ if (blocksize) mtu -= mtu % blocksize; /* Finally, CBC modes require at least one byte to indicate * padding length, as well as the MAC. */ if (mtu < pad + maclen) return 0; mtu -= pad + maclen; return mtu; }
int ciphers_main(int argc, char **argv) { char *cipherlist = NULL; STACK_OF(SSL_CIPHER) *ciphers; const SSL_CIPHER *cipher; SSL_CTX *ssl_ctx = NULL; SSL *ssl = NULL; uint16_t value; int i, rv = 0; char *desc; if (single_execution) { if (pledge("stdio rpath", NULL) == -1) { perror("pledge"); exit(1); } } memset(&ciphers_config, 0, sizeof(ciphers_config)); if (options_parse(argc, argv, ciphers_options, &cipherlist, NULL) != 0) { ciphers_usage(); return (1); } if (ciphers_config.usage) { ciphers_usage(); return (1); } if ((ssl_ctx = SSL_CTX_new(TLSv1_client_method())) == NULL) goto err; if (cipherlist != NULL) { if (SSL_CTX_set_cipher_list(ssl_ctx, cipherlist) == 0) goto err; } if ((ssl = SSL_new(ssl_ctx)) == NULL) goto err; if ((ciphers = SSL_get_ciphers(ssl)) == NULL) goto err; for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { cipher = sk_SSL_CIPHER_value(ciphers, i); if (ciphers_config.verbose == 0) { fprintf(stdout, "%s%s", (i ? ":" : ""), SSL_CIPHER_get_name(cipher)); continue; } if (ciphers_config.verbose > 1) { value = SSL_CIPHER_get_value(cipher); fprintf(stdout, "%-*s0x%02X,0x%02X - ", 10, "", ((value >> 8) & 0xff), (value & 0xff)); } desc = SSL_CIPHER_description(cipher, NULL, 0); if (strcmp(desc, "OPENSSL_malloc Error") == 0) { fprintf(stderr, "out of memory\n"); goto err; } fprintf(stdout, "%s", desc); free(desc); }
/* Switch on a filedescriptor */ int ggz_tls_enable_fd(int fd, GGZTLSType mode, GGZTLSVerificationType verify) { int ret, ret2; STACK_OF(SSL_CIPHER) *stack; SSL_CIPHER *cipher; int bits; char *cipherlist; SSL *_tls; int _tls_active; struct list_entry *entry; _state = 1; _tls_active = 0; if((mode != GGZ_TLS_CLIENT) && (mode != GGZ_TLS_SERVER)) { TLSERROR("Wrong mode."); return 0; } if(!_tlsctx) tls_init(verify); _tls = SSL_new(_tlsctx); if(_tls) { cipherlist = NULL; stack = SSL_get_ciphers(_tls); while((cipher = (SSL_CIPHER*)sk_pop(stack)) != NULL) { printf("* Cipher: %s\n", SSL_CIPHER_get_name(cipher)); printf(" Bits: %i\n", SSL_CIPHER_get_bits(cipher, &bits)); printf(" Used bits: %i\n", bits); printf(" Version: %s\n", SSL_CIPHER_get_version(cipher)); printf(" Description: %s\n", SSL_CIPHER_description(cipher, NULL, 0)); if(cipherlist) { cipherlist = (char*)realloc(cipherlist, (strlen(cipherlist) + 1) + strlen(SSL_CIPHER_get_name(cipher)) + 1); strcat(cipherlist, ":"); strcat(cipherlist, SSL_CIPHER_get_name(cipher)); } else { cipherlist = (char*)malloc(strlen(SSL_CIPHER_get_name(cipher)) + 1); strcpy(cipherlist, SSL_CIPHER_get_name(cipher)); } } printf("Available ciphers: %s\n", cipherlist); ret = SSL_set_cipher_list(_tls, cipherlist); if(!ret) TLSERROR("Cipher selection failed."); ret = SSL_set_fd(_tls, fd); if(!ret) TLSERROR("Assignment to connection failed."); else { SSL_set_read_ahead(_tls, 1); if(mode == GGZ_TLS_SERVER) { tls_certkey(_tls); if(_state) { SSL_set_accept_state(_tls); ret = SSL_accept(_tls); } } else { SSL_set_connect_state(_tls); ret = SSL_connect(_tls); } if((ret != 1) || (!_state)) { printf("Ret: %i, State: %i\n", ret, _state); TLSERROR("Handshake failed."); ret2 = ERR_get_error(); printf("EXT: %s\n%s\n%s\n%s\n%s\n", tls_exterror(_tls, ret), ERR_error_string(ret2, NULL), ERR_lib_error_string(ret2), ERR_func_error_string(ret2), ERR_reason_error_string(ret2)); } else { printf(">>>>> Handshake successful.\n"); if((mode == GGZ_TLS_SERVER) || (verify == GGZ_TLS_VERIFY_NONE)) _tls_active = 1; else { printf(">>>>> Client side, thus checking Certificate.\n"); printf("Negotiated cipher: %s\n", SSL_get_cipher(_tls)); printf("Shared ciphers: %s\n", SSL_get_shared_ciphers(_tls, NULL, 0)); if(SSL_get_peer_certificate(_tls)) { if(SSL_get_verify_result(_tls) == X509_V_OK) { _tls_active = 1; } else { printf("Error code: %li\n", SSL_get_verify_result(_tls)); TLSERROR("Invalid certificate, or certificate is not self-signed."); } } else TLSERROR("Couldn't get certificate."); } } entry = (struct list_entry*)ggz_malloc(sizeof(struct list_entry)); entry->tls = _tls; entry->fd = fd; entry->active = _tls_active; ggz_list_insert(openssllist, entry); return 1; } } return 0; }
/** Continue a TLS handshake * * Advance the TLS handshake by feeding OpenSSL data from dirty_in, * and reading data from OpenSSL into dirty_out. * * @param request The current request. * @param session The current TLS session. * @return * - 0 on error. * - 1 on success. */ int tls_session_handshake(REQUEST *request, tls_session_t *session) { int ret; /* * This is a logic error. tls_session_handshake * must not be called if the handshake is * complete tls_session_recv must be * called instead. */ if (SSL_is_init_finished(session->ssl)) { REDEBUG("Attempted to continue TLS handshake, but handshake has completed"); return 0; } if (session->invalid) { REDEBUG("Preventing invalid session from continuing"); return 0; } /* * Feed dirty data into OpenSSL, so that is can either * process it as Application data (decrypting it) * or continue the TLS handshake. */ if (session->dirty_in.used) { ret = BIO_write(session->into_ssl, session->dirty_in.data, session->dirty_in.used); if (ret != (int)session->dirty_in.used) { REDEBUG("Failed writing %zd bytes to TLS BIO: %d", session->dirty_in.used, ret); record_init(&session->dirty_in); return 0; } record_init(&session->dirty_in); } /* * Magic/More magic? Although SSL_read is normally * used to read application data, it will also * continue the TLS handshake. Removing this call will * cause the handshake to fail. * * We don't ever expect to actually *receive* application * data here. * * The reason why we call SSL_read instead of SSL_accept, * or SSL_connect, as it allows this function * to be used, irrespective or whether we're acting * as a client or a server. * * If acting as a client SSL_set_connect_state must have * been called before this function. * * If acting as a server SSL_set_accept_state must have * been called before this function. */ ret = SSL_read(session->ssl, session->clean_out.data + session->clean_out.used, sizeof(session->clean_out.data) - session->clean_out.used); if (ret > 0) { session->clean_out.used += ret; return 1; } if (!tls_log_io_error(request, session, ret, "Failed in SSL_read")) return 0; /* * This only occurs once per session, where calling * SSL_read updates the state of the SSL session, setting * this flag to true. * * Callbacks provide enough info so we don't need to * print debug statements when the handshake is in other * states. */ if (SSL_is_init_finished(session->ssl)) { SSL_CIPHER const *cipher; VALUE_PAIR *vp; char const *str_version; char cipher_desc[256], cipher_desc_clean[256]; char *p = cipher_desc, *q = cipher_desc_clean; cipher = SSL_get_current_cipher(session->ssl); SSL_CIPHER_description(cipher, cipher_desc, sizeof(cipher_desc)); /* * Cleanup the output from OpenSSL * Seems to print info in a tabular format. */ while (*p != '\0') { if (isspace(*p)) { *q++ = *p; while (isspace(*++p)); continue; } *q++ = *p++; } *q = '\0'; RDEBUG2("Cipher suite: %s", cipher_desc_clean); vp = fr_pair_afrom_num(request->state_ctx, 0, FR_TLS_SESSION_CIPHER_SUITE); if (vp) { fr_pair_value_strcpy(vp, SSL_CIPHER_get_name(cipher)); fr_pair_add(&request->state, vp); RDEBUG2(" &session-state:TLS-Session-Cipher-Suite := \"%s\"", vp->vp_strvalue); } switch (session->info.version) { case SSL2_VERSION: str_version = "SSL 2.0"; break; case SSL3_VERSION: str_version = "SSL 3.0"; break; case TLS1_VERSION: str_version = "TLS 1.0"; break; #ifdef TLS1_1_VERSION case TLS1_1_VERSION: str_version = "TLS 1.1"; break; #endif #ifdef TLS1_2_VERSION case TLS1_2_VERSION: str_version = "TLS 1.2"; break; #endif #ifdef TLS1_3_VERSON case TLS1_3_VERSION: str_version = "TLS 1.3"; break; #endif default: str_version = "UNKNOWN"; break; } vp = fr_pair_afrom_num(request->state_ctx, 0, FR_TLS_SESSION_VERSION); if (vp) { fr_pair_value_strcpy(vp, str_version); fr_pair_add(&request->state, vp); RDEBUG2(" &session-state:TLS-Session-Version := \"%s\"", str_version); } #if OPENSSL_VERSION_NUMBER >= 0x10001000L /* * Cache the SSL_SESSION pointer. * * Which contains all the data we need for session resumption. */ if (!session->ssl_session) { session->ssl_session = SSL_get_session(session->ssl); if (!session->ssl_session) { REDEBUG("Failed getting TLS session"); return 0; } } if (RDEBUG_ENABLED3) { BIO *ssl_log = BIO_new(BIO_s_mem()); if (ssl_log) { if (SSL_SESSION_print(ssl_log, session->ssl_session) == 1) { SSL_DRAIN_ERROR_QUEUE(RDEBUG3, "", ssl_log); } else { RDEBUG3("Failed retrieving session data"); } BIO_free(ssl_log); } } #endif /* * Session was resumed, add attribute to mark it as such. */ if (SSL_session_reused(session->ssl)) { /* * Mark the request as resumed. */ MEM(pair_update_request(&vp, attr_eap_session_resumed) >= 0); vp->vp_bool = true; } } /* * Get data to pack and send back to the TLS peer. */ ret = BIO_ctrl_pending(session->from_ssl); if (ret > 0) { ret = BIO_read(session->from_ssl, session->dirty_out.data, sizeof(session->dirty_out.data)); if (ret > 0) { session->dirty_out.used = ret; } else if (BIO_should_retry(session->from_ssl)) { record_init(&session->dirty_in); RDEBUG2("Asking for more data in tunnel"); return 1; } else { tls_log_error(NULL, NULL); record_init(&session->dirty_in); return 0; } } else { /* Its clean application data, do whatever we want */ record_init(&session->clean_out); } /* * W would prefer to latch on info.content_type but * (I think its...) tls_session_msg_cb() updates it * after the call to tls_session_handshake_alert() */ if (session->handshake_alert.level) { /* * FIXME RFC 4851 section 3.6.1 - peer might ACK alert and include a restarted ClientHello * which eap_tls_session_status() will fail on */ session->info.content_type = SSL3_RT_ALERT; session->dirty_out.data[0] = session->info.content_type; session->dirty_out.data[1] = 3; session->dirty_out.data[2] = 1; session->dirty_out.data[3] = 0; session->dirty_out.data[4] = 2; session->dirty_out.data[5] = session->handshake_alert.level; session->dirty_out.data[6] = session->handshake_alert.description; session->dirty_out.used = 7; session->handshake_alert.level = 0; } /* We are done with dirty_in, reinitialize it */ record_init(&session->dirty_in); return 1; }
int MAIN(int argc, char **argv) { int ret = 1, i; int verbose = 0, Verbose = 0; const char **pp; const char *p; int badops = 0; SSL_CTX *ctx = NULL; SSL *ssl = NULL; char *ciphers = NULL; const SSL_METHOD *meth = NULL; STACK_OF(SSL_CIPHER) *sk; char buf[512]; BIO *STDout = NULL; meth = SSLv23_server_method(); apps_startup(); if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); STDout = BIO_new_fp(stdout, BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); STDout = BIO_push(tmpbio, STDout); } #endif if (!load_config(bio_err, NULL)) goto end; argc--; argv++; while (argc >= 1) { if (strcmp(*argv, "-v") == 0) verbose = 1; else if (strcmp(*argv, "-V") == 0) verbose = Verbose = 1; #ifndef OPENSSL_NO_SSL2 else if (strcmp(*argv, "-ssl2") == 0) meth = SSLv2_client_method(); #endif #ifndef OPENSSL_NO_SSL3 else if (strcmp(*argv, "-ssl3") == 0) meth = SSLv3_client_method(); #endif #ifndef OPENSSL_NO_TLS1 else if (strcmp(*argv, "-tls1") == 0) meth = TLSv1_client_method(); #endif else if ((strncmp(*argv, "-h", 2) == 0) || (strcmp(*argv, "-?") == 0)) { badops = 1; break; } else { ciphers = *argv; } argc--; argv++; } if (badops) { for (pp = ciphers_usage; (*pp != NULL); pp++) BIO_printf(bio_err, "%s", *pp); goto end; } OpenSSL_add_ssl_algorithms(); ctx = SSL_CTX_new(meth); if (ctx == NULL) goto err; if (ciphers != NULL) { if (!SSL_CTX_set_cipher_list(ctx, ciphers)) { BIO_printf(bio_err, "Error in cipher list\n"); goto err; } } ssl = SSL_new(ctx); if (ssl == NULL) goto err; if (!verbose) { for (i = 0;; i++) { p = SSL_get_cipher_list(ssl, i); if (p == NULL) break; if (i != 0) BIO_printf(STDout, ":"); BIO_printf(STDout, "%s", p); } BIO_printf(STDout, "\n"); } else { /* verbose */ sk = SSL_get_ciphers(ssl); for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { SSL_CIPHER *c; c = sk_SSL_CIPHER_value(sk, i); if (Verbose) { unsigned long id = c->id; int id0 = (int)(id >> 24); int id1 = (int)((id >> 16) & 0xffL); int id2 = (int)((id >> 8) & 0xffL); int id3 = (int)(id & 0xffL); if ((id & 0xff000000L) == 0x02000000L) { /* SSL2 cipher */ BIO_printf(STDout, " 0x%02X,0x%02X,0x%02X - ", id1, id2, id3); } else if ((id & 0xff000000L) == 0x03000000L) { /* SSL3 cipher */ BIO_printf(STDout, " 0x%02X,0x%02X - ", id2, id3); } else { /* whatever */ BIO_printf(STDout, "0x%02X,0x%02X,0x%02X,0x%02X - ", id0, id1, id2, id3); } } BIO_puts(STDout, SSL_CIPHER_description(c, buf, sizeof buf)); } } ret = 0; if (0) { err: SSL_load_error_strings(); ERR_print_errors(bio_err); } end: if (ctx != NULL) SSL_CTX_free(ctx); if (ssl != NULL) SSL_free(ssl); if (STDout != NULL) BIO_free_all(STDout); apps_shutdown(); OPENSSL_EXIT(ret); }
int MAIN(int argc, char **argv) { int ret=1,i; int verbose=0; char **pp; const char *p; int badops=0; SSL_CTX *ctx=NULL; SSL *ssl=NULL; char *ciphers=NULL; SSL_METHOD *meth=NULL; STACK_OF(SSL_CIPHER) *sk; char buf[512]; BIO *STDout=NULL; #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3) meth=SSLv23_server_method(); #elif !defined(OPENSSL_NO_SSL3) meth=SSLv3_server_method(); #elif !defined(OPENSSL_NO_SSL2) meth=SSLv2_server_method(); #endif apps_startup(); if (bio_err == NULL) bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); STDout=BIO_new_fp(stdout,BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); STDout = BIO_push(tmpbio, STDout); } #endif argc--; argv++; while (argc >= 1) { if (strcmp(*argv,"-v") == 0) verbose=1; #ifndef OPENSSL_NO_SSL2 else if (strcmp(*argv,"-ssl2") == 0) meth=SSLv2_client_method(); #endif #ifndef OPENSSL_NO_SSL3 else if (strcmp(*argv,"-ssl3") == 0) meth=SSLv3_client_method(); #endif #ifndef OPENSSL_NO_TLS1 else if (strcmp(*argv,"-tls1") == 0) meth=TLSv1_client_method(); #endif else if ((strncmp(*argv,"-h",2) == 0) || (strcmp(*argv,"-?") == 0)) { badops=1; break; } else { ciphers= *argv; } argc--; argv++; } if (badops) { for (pp=ciphers_usage; (*pp != NULL); pp++) BIO_printf(bio_err,"%s",*pp); goto end; } OpenSSL_add_ssl_algorithms(); ctx=SSL_CTX_new(meth); if (ctx == NULL) goto err; if (ciphers != NULL) { if(!SSL_CTX_set_cipher_list(ctx,ciphers)) { BIO_printf(bio_err, "Error in cipher list\n"); goto err; } } ssl=SSL_new(ctx); if (ssl == NULL) goto err; if (!verbose) { for (i=0; ; i++) { p=SSL_get_cipher_list(ssl,i); if (p == NULL) break; if (i != 0) BIO_printf(STDout,":"); BIO_printf(STDout,"%s",p); } BIO_printf(STDout,"\n"); } else { sk=SSL_get_ciphers(ssl); for (i=0; i<sk_SSL_CIPHER_num(sk); i++) { BIO_puts(STDout,SSL_CIPHER_description( sk_SSL_CIPHER_value(sk,i), buf,sizeof buf)); } } ret=0; if (0) { err: SSL_load_error_strings(); ERR_print_errors(bio_err); } end: if (ctx != NULL) SSL_CTX_free(ctx); if (ssl != NULL) SSL_free(ssl); if (STDout != NULL) BIO_free_all(STDout); apps_shutdown(); OPENSSL_EXIT(ret); }
int ciphers_main(int argc, char **argv) { SSL_CTX *ctx = NULL; SSL *ssl = NULL; STACK_OF(SSL_CIPHER) *sk = NULL; const SSL_METHOD *meth = TLS_server_method(); int ret = 1, i, verbose = 0, Verbose = 0, use_supported = 0; #ifndef OPENSSL_NO_SSL_TRACE int stdname = 0; #endif #ifndef OPENSSL_NO_PSK int psk = 0; #endif #ifndef OPENSSL_NO_SRP int srp = 0; #endif const char *p; char *ciphers = NULL, *prog; char buf[512]; OPTION_CHOICE o; int min_version = 0, max_version = 0; prog = opt_init(argc, argv, ciphers_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(ciphers_options); ret = 0; goto end; case OPT_V: verbose = 1; break; case OPT_UPPER_V: verbose = Verbose = 1; break; case OPT_S: use_supported = 1; break; case OPT_STDNAME: #ifndef OPENSSL_NO_SSL_TRACE stdname = verbose = 1; #endif break; case OPT_SSL3: min_version = SSL3_VERSION; max_version = SSL3_VERSION; break; case OPT_TLS1: min_version = TLS1_VERSION; max_version = TLS1_VERSION; break; case OPT_TLS1_1: min_version = TLS1_1_VERSION; max_version = TLS1_1_VERSION; break; case OPT_TLS1_2: min_version = TLS1_2_VERSION; max_version = TLS1_2_VERSION; break; case OPT_TLS1_3: min_version = TLS1_3_VERSION; max_version = TLS1_3_VERSION; break; case OPT_PSK: #ifndef OPENSSL_NO_PSK psk = 1; #endif break; case OPT_SRP: #ifndef OPENSSL_NO_SRP srp = 1; #endif break; } } argv = opt_rest(); argc = opt_num_rest(); if (argc == 1) ciphers = *argv; else if (argc != 0) goto opthelp; ctx = SSL_CTX_new(meth); if (ctx == NULL) goto err; if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0) goto err; if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0) goto err; #ifndef OPENSSL_NO_PSK if (psk) SSL_CTX_set_psk_client_callback(ctx, dummy_psk); #endif #ifndef OPENSSL_NO_SRP if (srp) SSL_CTX_set_srp_client_pwd_callback(ctx, dummy_srp); #endif if (ciphers != NULL) { if (!SSL_CTX_set_cipher_list(ctx, ciphers)) { BIO_printf(bio_err, "Error in cipher list\n"); goto err; } } ssl = SSL_new(ctx); if (ssl == NULL) goto err; if (use_supported) sk = SSL_get1_supported_ciphers(ssl); else sk = SSL_get_ciphers(ssl); if (!verbose) { for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { const SSL_CIPHER *c = sk_SSL_CIPHER_value(sk, i); p = SSL_CIPHER_get_name(c); if (p == NULL) break; if (i != 0) BIO_printf(bio_out, ":"); BIO_printf(bio_out, "%s", p); } BIO_printf(bio_out, "\n"); } else { for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { const SSL_CIPHER *c; c = sk_SSL_CIPHER_value(sk, i); if (Verbose) { unsigned long id = SSL_CIPHER_get_id(c); int id0 = (int)(id >> 24); int id1 = (int)((id >> 16) & 0xffL); int id2 = (int)((id >> 8) & 0xffL); int id3 = (int)(id & 0xffL); if ((id & 0xff000000L) == 0x03000000L) BIO_printf(bio_out, " 0x%02X,0x%02X - ", id2, id3); /* SSL3 * cipher */ else BIO_printf(bio_out, "0x%02X,0x%02X,0x%02X,0x%02X - ", id0, id1, id2, id3); /* whatever */ } #ifndef OPENSSL_NO_SSL_TRACE if (stdname) { const char *nm = SSL_CIPHER_standard_name(c); if (nm == NULL) nm = "UNKNOWN"; BIO_printf(bio_out, "%s - ", nm); } #endif BIO_puts(bio_out, SSL_CIPHER_description(c, buf, sizeof buf)); } } ret = 0; goto end; err: ERR_print_errors(bio_err); end: if (use_supported) sk_SSL_CIPHER_free(sk); SSL_CTX_free(ctx); SSL_free(ssl); return (ret); }
bool TLS_SOCKET_CLASS::connect() // DESCRIPTION : Set up connection to the remote host. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : //<<=========================================================================== { BIO* bio_ptr; long error; ostringstream remoteHost; // make sure the socket is not already in use if (terminatingM) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - In process of terminating. Cannot connect."); } // return - in process of termintating return false; } if (connectedM) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - Already connected to \"%s\". Cannot connect again.", remoteHostnameM.c_str()); } // return - already connected return false; } else if (listeningM) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - Socket is already listening to port %d. Cannot connect to \"%s\".", localListenPortM, remoteHostnameM.c_str()); } // return - socket is already being used to listen return false; } connectedM = false; if (remoteHostnameM.length() == 0) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - No Remote Hostname defined. Can't make connection."); } // return - don't know what to connect to return false; } // create the transport object remoteHost << remoteHostnameM << ':' << remoteConnectPortM; if (loggerM_ptr) { loggerM_ptr->text(LOG_DEBUG, 1, "Secure Socket - tls::connect(%s)", remoteHost.str().c_str()); } bio_ptr = BIO_new_connect(const_cast<char *>(remoteHost.str().c_str())); if (!bio_ptr) { openSslError("creating connection"); return false; } if (BIO_do_connect(bio_ptr) <= 0) { openSslError("connecting to remote machine"); BIO_free(bio_ptr); return false; } // create the secure socket object if (sslM_ptr != NULL) { SSL_free(sslM_ptr); } sslM_ptr = SSL_new(ctxM_ptr); if (sslM_ptr == NULL) { openSslError("creating secure socket object"); BIO_free(bio_ptr); return false; } // set the 'this' pointer for the callbacks openSslMsgCallback and openSslVerifyCallback SSL_set_msg_callback_arg(sslM_ptr, static_cast<void*>(this)); // restore the session if (cacheTlsSessionsM && (savedClientSessionM_ptr != NULL)) { SSL_set_session(sslM_ptr, savedClientSessionM_ptr); SSL_SESSION_free(savedClientSessionM_ptr); // we're done with the saved session now, we'll // get a new one when the session is closed. savedClientSessionM_ptr = NULL; } // make the SSL connection SSL_set_bio(sslM_ptr, bio_ptr, bio_ptr); // the ssl takes over the mangement of the bio memory if (SSL_connect(sslM_ptr) <= 0) { openSslError("connecting to %s", remoteHost.str().c_str()); SSL_free(sslM_ptr); sslM_ptr = NULL; return false; } // make sure everything is OK error = postConnectionCheck(sslM_ptr); if (error != X509_V_OK) { openSslError("checking connection parameters after connecting to %s", remoteHost.str().c_str()); SSL_free(sslM_ptr); sslM_ptr = NULL; return false; } // socket connected to peer connectedM = true; if (loggerM_ptr && (loggerM_ptr->getLogMask() & LOG_DEBUG)) { char buffer[128]; SSL_CIPHER_description(SSL_get_current_cipher(sslM_ptr), buffer, 128); loggerM_ptr->text(LOG_DEBUG, 1, "Secure Socket - %s connection opened using cipher %s", SSL_get_version(sslM_ptr), buffer); } // return whether connected or not return connectedM; }
/* * Process the inner tunnel data */ FR_CODE eap_fast_process(eap_session_t *eap_session, tls_session_t *tls_session) { FR_CODE code; VALUE_PAIR *fast_vps = NULL; fr_cursor_t cursor; uint8_t const *data; size_t data_len; eap_fast_tunnel_t *t; REQUEST *request = eap_session->request; /* * Just look at the buffer directly, without doing * record_to_buff. */ data_len = tls_session->clean_out.used; tls_session->clean_out.used = 0; data = tls_session->clean_out.data; t = talloc_get_type_abort(tls_session->opaque, eap_fast_tunnel_t); /* * See if the tunneled data is well formed. */ if (!eap_fast_verify(request, tls_session, data, data_len)) return FR_CODE_ACCESS_REJECT; if (t->stage == EAP_FAST_TLS_SESSION_HANDSHAKE) { rad_assert(t->mode == EAP_FAST_UNKNOWN); char buf[256]; if (strstr(SSL_CIPHER_description(SSL_get_current_cipher(tls_session->ssl), buf, sizeof(buf)), "Au=None")) { /* FIXME enforce MSCHAPv2 - RFC 5422 section 3.2.2 */ RDEBUG2("Using anonymous provisioning"); t->mode = EAP_FAST_PROVISIONING_ANON; t->pac.send = true; } else { if (SSL_session_reused(tls_session->ssl)) { RDEBUG2("Session Resumed from PAC"); t->mode = EAP_FAST_NORMAL_AUTH; } else { RDEBUG2("Using authenticated provisioning"); t->mode = EAP_FAST_PROVISIONING_AUTH; } if (!t->pac.expires || t->pac.expired || t->pac.expires - time(NULL) < t->pac_lifetime * 0.6) { t->pac.send = true; } } eap_fast_init_keys(request, tls_session); eap_fast_send_identity_request(request, tls_session, eap_session); t->stage = EAP_FAST_AUTHENTICATION; return FR_CODE_ACCESS_CHALLENGE; } fr_cursor_init(&cursor, &fast_vps); if (eap_fast_decode_pair(request, &cursor, attr_eap_fast_tlv, data, data_len, NULL) < 0) return FR_CODE_ACCESS_REJECT; RDEBUG2("Got Tunneled FAST TLVs"); log_request_pair_list(L_DBG_LVL_1, request, fast_vps, NULL); code = eap_fast_process_tlvs(request, eap_session, tls_session, fast_vps); fr_pair_list_free(&fast_vps); if (code == FR_CODE_ACCESS_REJECT) return FR_CODE_ACCESS_REJECT; switch (t->stage) { case EAP_FAST_AUTHENTICATION: code = FR_CODE_ACCESS_CHALLENGE; break; case EAP_FAST_CRYPTOBIND_CHECK: { if (t->mode != EAP_FAST_PROVISIONING_ANON && !t->pac.send) t->result_final = true; eap_fast_append_result(tls_session, code); eap_fast_update_icmk(request, tls_session, (uint8_t *)&t->isk); eap_fast_append_crypto_binding(request, tls_session); code = FR_CODE_ACCESS_CHALLENGE; break; } case EAP_FAST_PROVISIONING: t->result_final = true; eap_fast_append_result(tls_session, code); if (t->pac.send) { RDEBUG2("Peer requires new PAC"); eap_fast_send_pac_tunnel(request, tls_session); code = FR_CODE_ACCESS_CHALLENGE; break; } t->stage = EAP_FAST_COMPLETE; /* fallthrough */ case EAP_FAST_COMPLETE: /* * RFC 5422 section 3.5 - Network Access after EAP-FAST Provisioning */ if (t->pac.type && t->pac.expired) { REDEBUG("Rejecting expired PAC."); code = FR_CODE_ACCESS_REJECT; break; } if (t->mode == EAP_FAST_PROVISIONING_ANON) { REDEBUG("Rejecting unauthenticated provisioning"); code = FR_CODE_ACCESS_REJECT; break; } /* * eap_crypto_mppe_keys() is unsuitable for EAP-FAST as Cisco decided * it would be a great idea to flip the recv/send keys around */ #define EAPTLS_MPPE_KEY_LEN 32 eap_add_reply(request, attr_ms_mppe_recv_key, t->msk, EAPTLS_MPPE_KEY_LEN); eap_add_reply(request, attr_ms_mppe_send_key, &t->msk[EAPTLS_MPPE_KEY_LEN], EAPTLS_MPPE_KEY_LEN); eap_add_reply(request, attr_eap_msk, t->msk, EAP_FAST_KEY_LEN); eap_add_reply(request, attr_eap_emsk, t->emsk, EAP_EMSK_LEN); break; default: RERROR("Internal sanity check failed in EAP-FAST at %d", t->stage); code = FR_CODE_ACCESS_REJECT; } return code; }
static void tls_list(rpc_t* rpc, void* c) { char buf[128]; char src_ip[IP_ADDR_MAX_STR_SIZE]; char dst_ip[IP_ADDR_MAX_STR_SIZE]; void* handle; char* tls_info; char* state; struct tls_extra_data* tls_d; struct tcp_connection* con; int i, len, timeout; TCPCONN_LOCK; for(i = 0; i < TCP_ID_HASH_SIZE; i++) { for (con = tcpconn_id_hash[i]; con; con = con->id_next) { if (con->rcv.proto != PROTO_TLS) continue; tls_d = con->extra_data; rpc->add(c, "{", &handle); /* tcp data */ if ((len = ip_addr2sbuf(&con->rcv.src_ip, src_ip, sizeof(src_ip))) == 0) BUG("failed to convert source ip"); src_ip[len] = 0; if ((len = ip_addr2sbuf(&con->rcv.dst_ip, dst_ip, sizeof(dst_ip))) == 0) BUG("failed to convert destination ip"); dst_ip[len] = 0; timeout = TICKS_TO_S(con->timeout - get_ticks_raw()); rpc->struct_add(handle, "ddsdsd", "id", con->id, "timeout", timeout, "src_ip", src_ip, "src_port", con->rcv.src_port, "dst_ip", dst_ip, "dst_port", con->rcv.dst_port); if (tls_d) { if(SSL_get_current_cipher(tls_d->ssl)) { tls_info = SSL_CIPHER_description( SSL_get_current_cipher(tls_d->ssl), buf, sizeof(buf)); len = strlen(buf); if (len && buf[len - 1] == '\n') buf[len - 1] = '\0'; } else { tls_info = "unknown"; } /* tls data */ state = "unknown/error"; lock_get(&con->write_lock); switch(tls_d->state) { case S_TLS_NONE: state = "none/init"; break; case S_TLS_ACCEPTING: state = "tls_accept"; break; case S_TLS_CONNECTING: state = "tls_connect"; break; case S_TLS_ESTABLISHED: state = "established"; break; } rpc->struct_add(handle, "sddds", "cipher", tls_info, "ct_wq_size", tls_d->ct_wq? tls_d->ct_wq->queued:0, "enc_rd_buf", tls_d->enc_rd_buf? tls_d->enc_rd_buf->size:0, "flags", tls_d->flags, "state", state ); lock_release(&con->write_lock); } else { rpc->struct_add(handle, "sddds", "cipher", "unknown", "ct_wq_size", 0, "enc_rd_buf", 0, "flags", 0, "state", "pre-init" ); } } } TCPCONN_UNLOCK; }
int main(int argc, char *argv[]) { SSL_CTX *ctx; SSL *ssl; BIO *bio; int (*callback)(char *, int, int, void *) = &password_callback; SSL_library_init(); SSL_load_error_strings(); ERR_load_BIO_strings(); ERR_load_SSL_strings(); printf("Attempting to create SSL context...\n"); ctx = SSL_CTX_new(SSLv3_client_method()); if(ctx == NULL) { printf("Failed. Aborting.\n"); ERR_print_errors_fp(stdout); return 0; } printf("\nLoading certificates...\n"); SSL_CTX_set_default_passwd_cb(ctx, callback); if (!SSL_CTX_load_verify_locations(ctx, "./CAtest/cacert.pem", NULL)) { /* Handle failed load here */ ERR_print_errors_fp(stdout); exit(1); } if (SSL_CTX_use_certificate_file(ctx, "./CAtest/client_cert.pem", SSL_FILETYPE_PEM) != 1) { //if (SSL_CTX_use_certificate_chain_file(ctx, "./CA/client_cert.pem") != 1) { /* Handle failed load here */ ERR_print_errors_fp(stdout); exit(1); } if (SSL_CTX_use_PrivateKey_file(ctx, "./CAtest/private/client_key.pem", SSL_FILETYPE_PEM) != 1) { /* Handle failed load here */ ERR_print_errors_fp(stdout); exit(1); } SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback); SSL_CTX_set_verify_depth(ctx, 5); //SSL_CTX_set_default_passwd_cb(ctx, callback); printf("Attempting to create BIO object...\n"); bio = BIO_new_ssl_connect(ctx); if(bio == NULL) { printf("Failed. Aborting.\n"); ERR_print_errors_fp(stdout); SSL_CTX_free(ctx); return 0; } printf("\nAttempting to set up BIO for SSL...\n"); BIO_get_ssl(bio, &ssl); SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); BIO_set_conn_hostname(bio, "127.0.0.1:4422"); if (BIO_do_connect(bio) <= 0) { printf("BIO_do_connect failed\n"); /* Handle failed connection */ ERR_print_errors_fp(stdout); exit (1); } if(SSL_get_verify_result(ssl) != X509_V_OK) { printf("SSL_get_verify_result failed\n"); /* Handle the failed verification */ ERR_print_errors_fp(stdout); //exit (1); } SSL_CIPHER *cipher = SSL_get_current_cipher(ssl); if (cipher) { char buf[1204]; printf("Cipher Name: %s\n", SSL_CIPHER_get_name(cipher)); printf("Cipher Desc: %s\n", SSL_CIPHER_description(cipher, buf, 1024)); } int len = 1024; char buf[len]; BIO_puts(bio, "Hello Server, this is just for test!"); BIO_flush(bio); BIO_read(bio, buf, len); printf("Received: %s\n", buf); SSL_CTX_free(ctx); /* To reuse the connection, use this line */ BIO_reset(bio); /* To free it from memory, use this line */ BIO_free_all(bio); return 0; }
bool TLS_SOCKET_CLASS::accept(BASE_SOCKET_CLASS** acceptedSocket_ptr_ptr) // DESCRIPTION : Accept connection from listen socket. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : The returned socket was new'ed so it must be deleted by the caller //<<=========================================================================== { *acceptedSocket_ptr_ptr = NULL; BIO* acceptedBio_ptr; SSL* acceptedSsl_ptr; long error; int fileDesc; struct fd_set fds; struct timeval tv = {1, 0}; // always timeout in 1 second int sel; if (terminatingM) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - In process of terminating. Cannot accept."); } // return - in process of termintating return false; } // make sure we are listening to the port if (!listeningM) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - Socket is not listening to port %d. Cannot accept a connection.", localListenPortM); } return false; } if (acceptBioM_ptr == NULL) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - Socket is listening to port %d, but not bound.", localListenPortM); } listeningM = false; return false; } if (loggerM_ptr) { loggerM_ptr->text(LOG_DEBUG, 1, "Secure Socket - tls::accept()"); } // get the file descriptor and set up the file descriptor set for select() fileDesc = BIO_get_fd(acceptBioM_ptr, NULL); if (fileDesc == -1) { openSslError("getting listen socket file descriptor"); return false; } // wait for a connection do { FD_ZERO(&fds); FD_SET(fileDesc, &fds); sel = select(fileDesc + 1, &fds, NULL, NULL, &tv); if (sel == 0) { // no data at the end of the timeout - check for terminating if (terminatingM) { return false; } } else if (sel == SOCKET_ERROR) { // socket error if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 2, "Secure Socket - Error waiting to accept connection (error code %d)", WSAGetLastError()); } return false; } else if (sel != 1) { // unknown error if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 2, "Secure Socket - Unknown error while waiting to accept connection (select returned %d)", sel); } return false; } } while (sel != 1); // accept a connection if (BIO_do_accept(acceptBioM_ptr) <= 0) { openSslError(LOG_DEBUG, "accepting connection on port %d", localListenPortM); close(); return false; } // get the new connection acceptedBio_ptr = BIO_pop(acceptBioM_ptr); // setup the socket structure acceptedSsl_ptr = SSL_new(ctxM_ptr); if (acceptedSsl_ptr == NULL) { openSslError("creating accepted secure socket object"); BIO_free(acceptedBio_ptr); return false; } // set the 'this' pointer for the callbacks openSslMsgCallback and openSslVerifyCallback SSL_set_msg_callback_arg(acceptedSsl_ptr, static_cast<void*>(this)); SSL_set_accept_state(acceptedSsl_ptr); SSL_set_bio(acceptedSsl_ptr, acceptedBio_ptr, acceptedBio_ptr); // the ssl takes over the BIO memory if (SSL_accept(acceptedSsl_ptr) <= 0) { openSslError("accepting secure connection to port %d", localListenPortM); SSL_free(acceptedSsl_ptr); return false; } // make sure everything is OK error = postConnectionCheck(acceptedSsl_ptr); if (error != X509_V_OK) { openSslError("checking connection parameters after accepting from port %d", localListenPortM); SSL_free(acceptedSsl_ptr); return false; } // create a socket for the new connection *acceptedSocket_ptr_ptr = new TLS_SOCKET_CLASS(*this, acceptedSsl_ptr); if (loggerM_ptr && (loggerM_ptr->getLogMask() & LOG_DEBUG)) { char buffer[128]; SSL_CIPHER_description(SSL_get_current_cipher(acceptedSsl_ptr), buffer, 128); loggerM_ptr->text(LOG_DEBUG, 1, "Secure Socket - %s connection opened using cipher %s", SSL_get_version(acceptedSsl_ptr), buffer); } return true; }