static SQRESULT sq_ssl_get_session_id_size(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_ssl_INSTANCE(); uint8_t result = ssl_get_session_id_size(self); sq_pushinteger(v, result); return 1; }
static SQRESULT sq_ssl_get_session_id(HSQUIRRELVM v){ SQ_FUNC_VARS_NO_TOP(v); GET_ssl_INSTANCE(); const uint8_t * result = ssl_get_session_id(self); sq_pushstring(v, (char *)result, ssl_get_session_id_size(self)); return 1; }
/*---------------------------------------------------------------------- | NPT_TlsSessionImpl::GetSessionId +---------------------------------------------------------------------*/ NPT_Result NPT_TlsSessionImpl::GetSessionId(NPT_DataBuffer& session_id) { if (m_SSL == NULL) { // no handshake done session_id.SetDataSize(0); return NPT_ERROR_INVALID_STATE; } // return the session id session_id.SetData(ssl_get_session_id(m_SSL), ssl_get_session_id_size(m_SSL)); return NPT_SUCCESS; }
/** * Display what session id we have. */ static void display_session_id(SSL *ssl) { int i; const uint8_t *session_id = ssl_get_session_id(ssl); int sess_id_size = ssl_get_session_id_size(ssl); if (sess_id_size > 0) { printf("-----BEGIN SSL SESSION PARAMETERS-----\n"); for (i = 0; i < sess_id_size; i++) { printf("%02x", session_id[i]); } printf("\n-----END SSL SESSION PARAMETERS-----\n"); } }
/* * This function is called after the TCP connect has completed. Setup the TLS * layer and do all necessary magic. */ CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex) { struct SessionHandle *data = conn->data; SSL_CTX *ssl_ctx; SSL *ssl; int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0}; int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0}; int i, ssl_fcn_return; const uint8_t *ssl_sessionid; size_t ssl_idsize; const char *peer_CN; uint32_t dns_altname_index; const char *dns_altname; int8_t found_subject_alt_names = 0; int8_t found_subject_alt_name_matching_conn = 0; /* Assuming users will not compile in custom key/cert to axTLS */ uint32_t client_option = SSL_NO_DEFAULT_KEY|SSL_SERVER_VERIFY_LATER; if(conn->ssl[sockindex].state == ssl_connection_complete) /* to make us tolerant against being called more than once for the same connection */ return CURLE_OK; /* axTLS only supports TLSv1 */ /* check to see if we've been told to use an explicit SSL/TLS version */ switch(data->set.ssl.version) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: break; default: failf(data, "axTLS only supports TLSv1"); return CURLE_SSL_CONNECT_ERROR; } #ifdef AXTLSDEBUG client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS; #endif /* AXTLSDEBUG */ /* Allocate an SSL_CTX struct */ ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS); if(ssl_ctx == NULL) { failf(data, "unable to create client SSL context"); return CURLE_SSL_CONNECT_ERROR; } /* Load the trusted CA cert bundle file */ if(data->set.ssl.CAfile) { if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL) != SSL_OK) { infof(data, "error reading ca cert file %s \n", data->set.ssl.CAfile); if(data->set.ssl.verifypeer) { Curl_axtls_close(conn, sockindex); return CURLE_SSL_CACERT_BADFILE; } } else infof(data, "found certificates in %s\n", data->set.ssl.CAfile); } /* curl_gtls.c tasks we're skipping for now: * 1) certificate revocation list checking * 2) dns name assignment to host * 3) set protocol priority. axTLS is TLSv1 only, so can probably ignore * 4) set certificate priority. axTLS ignores type and sends certs in * order added. can probably ignore this. */ /* Load client certificate */ if(data->set.str[STRING_CERT]) { i=0; /* Instead of trying to analyze cert type here, let axTLS try them all. */ while(cert_types[i] != 0) { ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i], data->set.str[STRING_CERT], NULL); if(ssl_fcn_return == SSL_OK) { infof(data, "successfully read cert file %s \n", data->set.str[STRING_CERT]); break; } i++; } /* Tried all cert types, none worked. */ if(cert_types[i] == 0) { failf(data, "%s is not x509 or pkcs12 format", data->set.str[STRING_CERT]); Curl_axtls_close(conn, sockindex); return CURLE_SSL_CERTPROBLEM; } } /* Load client key. If a pkcs12 file successfully loaded a cert, then there's nothing to do because the key has already been loaded. */ if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) { i=0; /* Instead of trying to analyze key type here, let axTLS try them all. */ while(key_types[i] != 0) { ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i], data->set.str[STRING_KEY], NULL); if(ssl_fcn_return == SSL_OK) { infof(data, "successfully read key file %s \n", data->set.str[STRING_KEY]); break; } i++; } /* Tried all key types, none worked. */ if(key_types[i] == 0) { failf(data, "Failure: %s is not a supported key file", data->set.str[STRING_KEY]); Curl_axtls_close(conn, sockindex); return CURLE_SSL_CONNECT_ERROR; } } /* curl_gtls.c does more here that is being left out for now * 1) set session credentials. can probably ignore since axtls puts this * info in the ssl_ctx struct * 2) setting up callbacks. these seem gnutls specific */ /* In axTLS, handshaking happens inside ssl_client_new. */ if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) { /* we got a session id, use it! */ infof (data, "SSL re-using session ID\n"); ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], ssl_sessionid, (uint8_t)ssl_idsize); } else ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0); /* Check to make sure handshake was ok. */ ssl_fcn_return = ssl_handshake_status(ssl); if(ssl_fcn_return != SSL_OK) { Curl_axtls_close(conn, sockindex); ssl_display_error(ssl_fcn_return); /* goes to stdout. */ return map_error_to_curl(ssl_fcn_return); } infof (data, "handshake completed successfully\n"); /* Here, curl_gtls.c gets the peer certificates and fails out depending on * settings in "data." axTLS api doesn't have get cert chain fcn, so omit? */ /* Verify server's certificate */ if(data->set.ssl.verifypeer) { if(ssl_verify_cert(ssl) != SSL_OK) { Curl_axtls_close(conn, sockindex); failf(data, "server cert verify failed"); return CURLE_SSL_CONNECT_ERROR; } } else infof(data, "\t server certificate verification SKIPPED\n"); /* Here, curl_gtls.c does issuer verification. axTLS has no straightforward * equivalent, so omitting for now.*/ /* Here, curl_gtls.c does the following * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but * it seems useful. This is now implemented, by Oscar Koeroo * 2) checks cert validity based on time. axTLS does this in ssl_verify_cert * 3) displays a bunch of cert information. axTLS doesn't support most of * this, but a couple fields are available. */ /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a risk of an inifite loop */ for(dns_altname_index = 0; ; dns_altname_index++) { dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index); if(dns_altname == NULL) { break; } found_subject_alt_names = 1; infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n", dns_altname, conn->host.name); if(Curl_cert_hostcheck(dns_altname, conn->host.name)) { found_subject_alt_name_matching_conn = 1; break; } } /* RFC2818 checks */ if(found_subject_alt_names && !found_subject_alt_name_matching_conn) { /* Break connection ! */ Curl_axtls_close(conn, sockindex); failf(data, "\tsubjectAltName(s) do not match %s\n", conn->host.dispname); return CURLE_PEER_FAILED_VERIFICATION; } else if(found_subject_alt_names == 0) { /* Per RFC2818, when no Subject Alt Names were available, examine the peer CN as a legacy fallback */ peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME); if(peer_CN == NULL) { /* Similar behaviour to the OpenSSL interface */ Curl_axtls_close(conn, sockindex); failf(data, "unable to obtain common name from peer certificate"); return CURLE_PEER_FAILED_VERIFICATION; } else { if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) { if(data->set.ssl.verifyhost) { /* Break connection ! */ Curl_axtls_close(conn, sockindex); failf(data, "\tcommon name \"%s\" does not match \"%s\"\n", peer_CN, conn->host.dispname); return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, "\tcommon name \"%s\" does not match \"%s\"\n", peer_CN, conn->host.dispname); } } } /* General housekeeping */ conn->ssl[sockindex].state = ssl_connection_complete; conn->ssl[sockindex].ssl = ssl; conn->ssl[sockindex].ssl_ctx = ssl_ctx; conn->recv[sockindex] = axtls_recv; conn->send[sockindex] = axtls_send; /* Put our freshly minted SSL session in cache */ ssl_idsize = ssl_get_session_id_size(ssl); ssl_sessionid = ssl_get_session_id(ssl); if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize) != CURLE_OK) infof (data, "failed to add session to cache\n"); return CURLE_OK; }
/* * For both blocking and non-blocking connects, this function finalizes the * SSL connection. */ static CURLcode connect_finish(struct connectdata *conn, int sockindex) { struct SessionHandle *data = conn->data; SSL *ssl = conn->ssl[sockindex].ssl; const uint8_t *ssl_sessionid; size_t ssl_idsize; const char *peer_CN; uint32_t dns_altname_index; const char *dns_altname; int8_t found_subject_alt_names = 0; int8_t found_subject_alt_name_matching_conn = 0; /* Here, gtls.c gets the peer certificates and fails out depending on * settings in "data." axTLS api doesn't have get cert chain fcn, so omit? */ /* Verify server's certificate */ if(data->set.ssl.verifypeer) { if(ssl_verify_cert(ssl) != SSL_OK) { Curl_axtls_close(conn, sockindex); failf(data, "server cert verify failed"); return CURLE_PEER_FAILED_VERIFICATION; } } else infof(data, "\t server certificate verification SKIPPED\n"); /* Here, gtls.c does issuer verification. axTLS has no straightforward * equivalent, so omitting for now.*/ /* Here, gtls.c does the following * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but * it seems useful. This is now implemented, by Oscar Koeroo * 2) checks cert validity based on time. axTLS does this in ssl_verify_cert * 3) displays a bunch of cert information. axTLS doesn't support most of * this, but a couple fields are available. */ /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a risk of an inifite loop */ for(dns_altname_index = 0; ; dns_altname_index++) { dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index); if(dns_altname == NULL) { break; } found_subject_alt_names = 1; infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n", dns_altname, conn->host.name); if(Curl_cert_hostcheck(dns_altname, conn->host.name)) { found_subject_alt_name_matching_conn = 1; break; } } /* RFC2818 checks */ if(found_subject_alt_names && !found_subject_alt_name_matching_conn) { if(data->set.ssl.verifyhost) { /* Break connection ! */ Curl_axtls_close(conn, sockindex); failf(data, "\tsubjectAltName(s) do not match %s\n", conn->host.dispname); return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, "\tsubjectAltName(s) do not match %s\n", conn->host.dispname); } else if(found_subject_alt_names == 0) { /* Per RFC2818, when no Subject Alt Names were available, examine the peer CN as a legacy fallback */ peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME); if(peer_CN == NULL) { if(data->set.ssl.verifyhost) { Curl_axtls_close(conn, sockindex); failf(data, "unable to obtain common name from peer certificate"); return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, "unable to obtain common name from peer certificate"); } else { if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) { if(data->set.ssl.verifyhost) { /* Break connection ! */ Curl_axtls_close(conn, sockindex); failf(data, "\tcommon name \"%s\" does not match \"%s\"\n", peer_CN, conn->host.dispname); return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, "\tcommon name \"%s\" does not match \"%s\"\n", peer_CN, conn->host.dispname); } } } /* General housekeeping */ conn->ssl[sockindex].state = ssl_connection_complete; conn->recv[sockindex] = axtls_recv; conn->send[sockindex] = axtls_send; /* Put our freshly minted SSL session in cache */ ssl_idsize = ssl_get_session_id_size(ssl); ssl_sessionid = ssl_get_session_id(ssl); if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize) != CURLE_OK) infof (data, "failed to add session to cache\n"); return CURLE_OK; }