unsigned int ma_ssl_get_finger_print(MARIADB_SSL *cssl, unsigned char *fp, unsigned int len) { MYSQL *mysql; size_t fp_len= len; const gnutls_datum_t *cert_list; unsigned int cert_list_size; if (!cssl || !cssl->ssl) return 0; mysql= (MYSQL *)gnutls_session_get_ptr(cssl->ssl); cert_list = gnutls_certificate_get_peers (cssl->ssl, &cert_list_size); if (cert_list == NULL) { my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, ER(CR_SSL_CONNECTION_ERROR), "Unable to get server certificate"); return 0; } if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &cert_list[0], fp, &fp_len) == 0) return fp_len; else { my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, ER(CR_SSL_CONNECTION_ERROR), "Finger print buffer too small"); return 0; } }
static int mailstream_gnutls_client_cert_cb(gnutls_session session, const gnutls_datum *req_ca_rdn, int nreqs, const gnutls_pk_algorithm *sign_algos, int sign_algos_length, gnutls_retr2_st *st) #endif { struct mailstream_ssl_context * ssl_context = (struct mailstream_ssl_context *)gnutls_session_get_ptr(session); gnutls_certificate_type type = gnutls_certificate_type_get(session); st->ncerts = 0; if (ssl_context == NULL) return 0; if (type == GNUTLS_CRT_X509 && ssl_context->client_x509 && ssl_context->client_pkey) { st->ncerts = 1; #if GNUTLS_VERSION_NUMBER <= 0x020c00 st->type = type; #else st->cert_type = type; st->key_type = GNUTLS_PRIVKEY_X509; #endif st->cert.x509 = &(ssl_context->client_x509); st->key.x509 = ssl_context->client_pkey; st->deinit_all = 0; } return 0; }
static int cert_callback(gnutls_session_t session) { const gnutls_datum_t *cert_list; unsigned int cert_list_size = 0; int ret; unsigned i; gnutls_datum_t t; struct priv_st *priv; cert_list = gnutls_certificate_get_peers(session, &cert_list_size); if (cert_list_size == 0) { fprintf(stderr, "no certificates sent by server!\n"); return -1; } priv = gnutls_session_get_ptr(session); for (i=0;i<cert_list_size;i++) { ret = gnutls_pem_base64_encode_alloc("CERTIFICATE", &cert_list[i], &t); if (ret < 0) { fprintf(stderr, "error[%d]: %s\n", __LINE__, gnutls_strerror(ret)); exit(1); } write(priv->fd, t.data, t.size); gnutls_free(t.data); } priv->found = 1; return -1; }
static int ticket_callback(gnutls_session_t session, unsigned int htype, unsigned post, unsigned int incoming, const gnutls_datum_t *msg) { gnutls_datum *d; static int counter = 0; int ret; assert(htype == GNUTLS_HANDSHAKE_NEW_SESSION_TICKET); counter++; if (counter <= TLS13_TICKETS_TO_SEND) /* ignore the default tickets sent */ return 0; d = gnutls_session_get_ptr(session); if (post == GNUTLS_HOOK_POST) { tickets_seen++; if (d->data) gnutls_free(d->data); ret = gnutls_session_get_data2(session, d); assert(ret >= 0); assert(d->size > 4); return 0; } return 0; }
static int handshake_hook_func(gnutls_session_t session, unsigned int htype, unsigned int post, unsigned int incoming) { if (!session) { return 0; } auto* tls = reinterpret_cast<CTlsSocket*>(gnutls_session_get_ptr(session)); if (!tls) { return 0; } char const* prefix; if (incoming) { if (post) { prefix = "Processed"; } else { prefix = "Received"; } } else { if (post) { prefix = "Sent"; } else { prefix = "About to send"; } } char const* name = gnutls_handshake_description_get_name(static_cast<gnutls_handshake_description_t>(htype)); tls->m_pOwner->LogMessage(MessageType::Debug_Debug, _T("TLS handshake: %s %s"), prefix, name); return 0; }
static ssize_t push_crippled (gnutls_transport_ptr_t tr, const void *_data, size_t len) { int fd = (long int)tr; unsigned char* data = (void*)_data; struct point_st * p; unsigned p_size; struct test_st * test = gnutls_session_get_ptr(cli_session); p = &test->points[point_idx]; p_size = test->npoints; memcpy(&data[len-32], data+5, 32); /*fprintf(stderr, "sending: %d: %d\n", (unsigned)p->byte1, (int)len);*/ data[len-17] ^= p->byte1; data[len-18] ^= p->byte2; prev_point_ptr = p; point_idx++; if (point_idx >= p_size) point_idx = 0; return send(fd, data, len, 0); }
static int verify_certificate_callback( gnutls_session_t session ) { unsigned int status; const gnutls_datum_t *cert_list; unsigned int cert_list_size; int gnutlsret; int verifyret = 0; gnutls_x509_crt_t cert; const char *hostname; hostname = gnutls_session_get_ptr( session ); gnutlsret = gnutls_certificate_verify_peers2( session, &status ); if( gnutlsret < 0 ) return VERIFY_CERT_ERROR; if( status & GNUTLS_CERT_INVALID ) verifyret |= VERIFY_CERT_INVALID; if( status & GNUTLS_CERT_REVOKED ) verifyret |= VERIFY_CERT_REVOKED; if( status & GNUTLS_CERT_SIGNER_NOT_FOUND ) verifyret |= VERIFY_CERT_SIGNER_NOT_FOUND; if( status & GNUTLS_CERT_SIGNER_NOT_CA ) verifyret |= VERIFY_CERT_SIGNER_NOT_CA; if( status & GNUTLS_CERT_INSECURE_ALGORITHM ) verifyret |= VERIFY_CERT_INSECURE_ALGORITHM; #ifdef GNUTLS_CERT_NOT_ACTIVATED /* Amusingly, the GnuTLS function used above didn't check for expiry until GnuTLS 2.8 or so. (See CVE-2009-1417) */ if( status & GNUTLS_CERT_NOT_ACTIVATED ) verifyret |= VERIFY_CERT_NOT_ACTIVATED; if( status & GNUTLS_CERT_EXPIRED ) verifyret |= VERIFY_CERT_EXPIRED; #endif if( gnutls_certificate_type_get( session ) != GNUTLS_CRT_X509 || gnutls_x509_crt_init( &cert ) < 0 ) return VERIFY_CERT_ERROR; cert_list = gnutls_certificate_get_peers( session, &cert_list_size ); if( cert_list == NULL || gnutls_x509_crt_import( cert, &cert_list[0], GNUTLS_X509_FMT_DER ) < 0 ) return VERIFY_CERT_ERROR; if( !gnutls_x509_crt_check_hostname( cert, hostname ) ) { verifyret |= VERIFY_CERT_INVALID; verifyret |= VERIFY_CERT_WRONG_HOSTNAME; } gnutls_x509_crt_deinit( cert ); return verifyret; }
int TLSSocket::verify(VerifyResult& result) { const char* hostname = (const char*) gnutls_session_get_ptr (session); unsigned int status; int ret = gnutls_certificate_verify_peers2 (session, &status); if (ret < 0) { return -1; } result.distrusted = (status & GNUTLS_CERT_INVALID); result.unknownIssuer = (status & GNUTLS_CERT_SIGNER_NOT_FOUND); result.revoked = (status & GNUTLS_CERT_REVOKED); result.expired = (status & GNUTLS_CERT_EXPIRED); result.inactive = (status & GNUTLS_CERT_NOT_ACTIVATED); result.invalidCert = false; if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) { result.invalidCert = true; return -1; } gnutls_x509_crt_t cert; if (gnutls_x509_crt_init (&cert) < 0) { return -1; } const gnutls_datum_t *cert_list; unsigned int cert_list_size; cert_list = gnutls_certificate_get_peers (session, &cert_list_size); if (cert_list == NULL) { result.invalidCert = true; gnutls_x509_crt_deinit (cert); return -1; } if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0){ result.invalidCert = true; gnutls_x509_crt_deinit (cert); return -1; } result.hostnameMismatch = !gnutls_x509_crt_check_hostname (cert, hostname); gnutls_x509_crt_deinit (cert); return 0; }
/** * Internally used gnutls callback function that gets called during handshake. */ static int internal_cert_callback(gnutls_session_t session, const gnutls_datum_t * req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t * sign_algos, int sign_algos_length, gnutls_retr_st * st) { int res = -1; gnutls_certificate_type_t type = gnutls_certificate_type_get(session); if (type == GNUTLS_CRT_X509) { ssl_data_t ssl_data = (ssl_data_t)gnutls_session_get_ptr(session); if (ssl_data && ssl_data->host_privkey && ssl_data->host_cert) { debug_info("Passing certificate"); st->type = type; st->ncerts = 1; st->cert.x509 = &ssl_data->host_cert; st->key.x509 = ssl_data->host_privkey; st->deinit_all = 0; res = 0; } } return res; }
my_bool ma_ssl_connect(MARIADB_SSL *cssl) { gnutls_session_t ssl = (gnutls_session_t)cssl->ssl; my_bool blocking; MYSQL *mysql; MARIADB_PVIO *pvio; int ret; mysql= (MYSQL *)gnutls_session_get_ptr(ssl); if (!mysql) return 1; pvio= mysql->net.pvio; /* Set socket to blocking if not already set */ if (!(blocking= pvio->methods->is_blocking(pvio))) pvio->methods->blocking(pvio, TRUE, 0); /* we don't use GnuTLS read/write functions */ gnutls_transport_set_ptr(ssl, pvio); gnutls_transport_set_push_function(ssl, ma_ssl_push); gnutls_transport_set_pull_function(ssl, ma_ssl_pull); gnutls_transport_set_pull_timeout_function(ssl, ma_ssl_pull_timeout); gnutls_handshake_set_timeout(ssl, pvio->timeout[PVIO_CONNECT_TIMEOUT]); do { ret = gnutls_handshake(ssl); } while (ret < 0 && gnutls_error_is_fatal(ret) == 0); if (ret < 0) { ma_ssl_set_error(mysql, ret); /* restore blocking mode */ if (!blocking) pvio->methods->blocking(pvio, FALSE, 0); return 1; } cssl->ssl= (void *)ssl; return 0; }
/* Callback invoked when the SSL server requests a client certificate. */ static int provide_client_cert(gnutls_session session, const gnutls_datum *req_ca_rdn, int nreqs, const gnutls_pk_algorithm *sign_algos, int sign_algos_length, gnutls_retr_st *st) { ne_session *sess = gnutls_session_get_ptr(session); if (!sess) { return -1; } if (!sess->client_cert && sess->ssl_provide_fn) { /* The dname array cannot be converted without better dname * support from GNUTLS. */ sess->ssl_provide_fn(sess->ssl_provide_ud, sess, NULL, 0); } NE_DEBUG(NE_DBG_SSL, "In client cert provider callback.\n"); if (sess->client_cert) { gnutls_certificate_type type = gnutls_certificate_type_get(session); if (type == GNUTLS_CRT_X509) { NE_DEBUG(NE_DBG_SSL, "Supplying client certificate.\n"); st->type = type; st->ncerts = 1; st->cert.x509 = &sess->client_cert->cert.subject; st->key.x509 = sess->client_cert->pkey; /* tell GNU TLS not to deallocate the certs. */ st->deinit_all = 0; } else { return -1; } } else { NE_DEBUG(NE_DBG_SSL, "No client certificate supplied.\n"); } return 0; }
int SslSocket::onClientHello(gnutls_session_t session) { TRACE("onClientHello()"); SslSocket *socket = (SslSocket *)gnutls_session_get_ptr(session); // find SNI server const int MAX_HOST_LEN = 255; std::size_t dataLen = MAX_HOST_LEN; char sniName[MAX_HOST_LEN]; unsigned int sniType; int rv = gnutls_server_name_get(session, sniName, &dataLen, &sniType, 0); if (rv != 0) { TRACE("onClientHello(): gnutls_server_name_get() failed with (%d): %s", rv, gnutls_strerror(rv)); // failed to get SNI from client, so try getting default context then. if (SslContext *cx = socket->driver_->selectContext("")) { cx->bind(socket); return 0; } return GNUTLS_E_UNIMPLEMENTED_FEATURE; } if (sniType != GNUTLS_NAME_DNS) { TRACE("onClientHello(): Unknown SNI type: %d", sniType); return GNUTLS_E_UNIMPLEMENTED_FEATURE; } TRACE("onClientHello(): SNI Name: \"%s\"", sniName); if (SslContext *cx = socket->driver_->selectContext(sniName)) cx->bind(socket); else if (SslContext* cx = socket->driver_->selectContext("")) cx->bind(socket); return 0; }
int psk_creds(gnutls_session_t session, const char *user, gnutls_datum_t *key) { struct conn *conn; int rc; uint8_t * psk; int psk_len; conn = gnutls_session_get_ptr(session); rc = conn->dtls_get_psk(conn,user, &psk,&psk_len); if (!rc) return -1; key->size=psk_len; key->data = gnutls_malloc(key->size); if (key->data == NULL) { return -1; } memcpy(key->data, psk, psk_len); return 0; }
static int handshake_callback(gnutls_session_t session, unsigned int htype, unsigned post, unsigned int incoming, const gnutls_datum_t *msg) { struct hsk_st *h = gnutls_session_get_ptr(session); if (htype == GNUTLS_HANDSHAKE_FINISHED && !incoming) { if (h->sleep_at_finished) virt_sec_sleep(h->sleep_at_finished); return 0; } else if (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO) { gnutls_ext_raw_parse(h, ext_hook_func, msg, GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO); } if (htype != GNUTLS_HANDSHAKE_NEW_SESSION_TICKET) return 0; if (h) h->sent_nst = 1; return 0; }
/* This function will verify the peer's certificate, and check * if the hostname matches, as well as the activation, expiration dates. */ extern int verify_certificate_callback (gnutls_session_t session) { unsigned int status; int ret, type; const char *hostname; gnutls_datum_t out; /* read hostname */ hostname = gnutls_session_get_ptr (session); /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ ret = gnutls_certificate_verify_peers3 (session, hostname, &status); if (ret < 0) { printf ("Error\n"); return GNUTLS_E_CERTIFICATE_ERROR; } type = gnutls_certificate_type_get (session); ret = gnutls_certificate_verification_status_print( status, type, &out, 0); if (ret < 0) { printf ("Error\n"); return GNUTLS_E_CERTIFICATE_ERROR; } printf ("%s", out.data); gnutls_free(out.data); if (status != 0) /* Certificate is not trusted */ return GNUTLS_E_CERTIFICATE_ERROR; /* notify gnutls to continue handshake normally */ return 0; }
static int verify_certificate_callback (gnutls_session_t session) { if (trust_override) return 0; // Get the hostname from the session. const char* hostname = (const char*) gnutls_session_get_ptr (session); // This verification function uses the trusted CAs in the credentials // structure. So you must have installed one or more CA certificates. unsigned int status = 0; #if GNUTLS_VERSION_NUMBER >= 0x030104 int ret = gnutls_certificate_verify_peers3 (session, NULL, &status); #else int ret = gnutls_certificate_verify_peers2 (session, &status); #endif if (ret < 0) return GNUTLS_E_CERTIFICATE_ERROR; #if GNUTLS_VERSION_NUMBER >= 0x030105 gnutls_certificate_type_t type = gnutls_certificate_type_get (session); gnutls_datum_t out; ret = gnutls_certificate_verification_status_print (status, type, &out, 0); if (ret < 0) return GNUTLS_E_CERTIFICATE_ERROR; std::cout << "c: INFO " << out.data << "\n"; gnutls_free (out.data); #endif if (status != 0) return GNUTLS_E_CERTIFICATE_ERROR; // Continue handshake. return 0; }
/* This function will verify the peer's certificate, and check * if the hostname matches, as well as the activation, expiration dates. */ static int _verify_certificate_callback (gnutls_session_t session) { unsigned int status; int ret, type; const char *hostname; gnutls_datum_t out; hostname = gnutls_session_get_ptr (session); ret = gnutls_certificate_verify_peers3 (session, NULL, &status); if (ret < 0) { return GNUTLS_E_CERTIFICATE_ERROR; } type = gnutls_certificate_type_get (session); ret = gnutls_certificate_verification_status_print( status, type, &out, 0); if (status != 0) { error = out.data; verification_result = status; return GNUTLS_E_CERTIFICATE_ERROR; } return 0; }
int SslContext::onRetrieveCert(gnutls_session_t session, gnutls_retr_st *ret) { TRACE("onRetrieveCert()"); SslSocket *socket = (SslSocket *)gnutls_session_get_ptr(session); const SslContext *cx = socket->context(); switch (gnutls_certificate_type_get(session)) { case GNUTLS_CRT_X509: if (!cx) return GNUTLS_E_INTERNAL_ERROR; ret->type = GNUTLS_CRT_X509; ret->deinit_all = 0; ret->ncerts = cx->numX509Certs_; ret->cert.x509 = const_cast<SslContext *>(cx)->x509Certs_; ret->key.x509 = cx->x509PrivateKey_; return GNUTLS_E_SUCCESS; case GNUTLS_CRT_OPENPGP: //return GNUTLS_E_SUCCESS; default: return GNUTLS_E_INTERNAL_ERROR; } }
static int post_client_hello_cb(gnutls_session_t session) { liGnuTLSFilter *f = gnutls_session_get_ptr(session); if (NULL == f->callbacks->post_client_hello_cb) return GNUTLS_E_SUCCESS; return f->callbacks->post_client_hello_cb(f, f->callback_data); }
static int verify_certificate_callback (gnutls_session_t session) { const TLSClient* client = (TLSClient*) gnutls_session_get_ptr (session); return client->verify_certificate (); }
/* This function will verify the peer's certificate, and check * if the hostname matches, as well as the activation, expiration dates. */ static int _verify_certificate_callback (gnutls_session_t session) { unsigned int status; const gnutls_datum_t *cert_list; unsigned int cert_list_size; int ret; gnutls_x509_crt_t cert; const char *hostname; /* read hostname */ hostname = gnutls_session_get_ptr (session); /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ ret = gnutls_certificate_verify_peers2 (session, &status); if (ret < 0) { printf ("Error\n"); return GNUTLS_E_CERTIFICATE_ERROR; } if (status & GNUTLS_CERT_INVALID) printf ("The certificate is not trusted.\n"); if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) printf ("The certificate hasn't got a known issuer.\n"); if (status & GNUTLS_CERT_REVOKED) printf ("The certificate has been revoked.\n"); if (status & GNUTLS_CERT_EXPIRED) printf ("The certificate has expired\n"); if (status & GNUTLS_CERT_NOT_ACTIVATED) printf ("The certificate is not yet activated\n"); /* Up to here the process is the same for X.509 certificates and * OpenPGP keys. From now on X.509 certificates are assumed. This can * be easily extended to work with openpgp keys as well. */ if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) return GNUTLS_E_CERTIFICATE_ERROR; if (gnutls_x509_crt_init (&cert) < 0) { printf ("error in initialization\n"); return GNUTLS_E_CERTIFICATE_ERROR; } cert_list = gnutls_certificate_get_peers (session, &cert_list_size); if (cert_list == NULL) { printf ("No certificate was found!\n"); return GNUTLS_E_CERTIFICATE_ERROR; } /* This is not a real world example, since we only check the first * certificate in the given chain. */ if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) { printf ("error parsing certificate\n"); return GNUTLS_E_CERTIFICATE_ERROR; } if (!gnutls_x509_crt_check_hostname (cert, hostname)) { printf ("The certificate's owner does not match hostname '%s'\n", hostname); return GNUTLS_E_CERTIFICATE_ERROR; } gnutls_x509_crt_deinit (cert); /* notify gnutls to continue handshake normally */ return 0; }
int gnutls::credentials::callbackObj::callback(gnutls_session_t sess, const gnutls_datum_t *req_ca_dn, int nreqs, const gnutls_pk_algorithm_t *pk_algos, int pk_algos_length, gnutls_retr2_st* st) { std::list<std::string> hostname_list; st->cert_type=GNUTLS_CRT_UNKNOWN; st->key_type=GNUTLS_PRIVKEY_X509; st->ncerts=0; st->deinit_all=0; credentials::callbackptr cb; try { gnutls::sessionObj *sessObj=(gnutls::sessionObj *) gnutls_session_get_ptr(sess); if (sessObj->mode == GNUTLS_SERVER) sessionObj::get_server_names(sess, hostname_list); cb=sessObj->certificateCred->certificateCallback; std::vector<gnutls_pk_algorithm_t> algos; algos.reserve(pk_algos_length); if (pk_algos) algos.insert(algos.end(), pk_algos, pk_algos+pk_algos_length); auto certkeyptr= cb->get(sessObj, hostname_list, algos, req_ca_dn, nreqs); if (!certkeyptr.null()) { int rc; gnutls::datum_t keyDatumObj=certkeyptr->key ->export_pkcs1(GNUTLS_X509_FMT_DER); gnutls_datum_t keyDatum; keyDatum.data=&*keyDatumObj->begin(); keyDatum.size=keyDatumObj->size(); gnutls_x509_privkey_t privkey; chkerr(gnutls_x509_privkey_init(&privkey), "gnutls_x509_privkey_init"); rc=gnutls_x509_privkey_import(privkey, &keyDatum, GNUTLS_X509_FMT_DER); if (rc) { gnutls_x509_privkey_deinit(privkey); chkerr(rc, "gnutls_x509_privkey_import"); } try { st->cert_type=GNUTLS_CRT_X509; st->cert.x509=init_certs(certkeyptr->cert); } catch (...) { gnutls_x509_privkey_deinit(privkey); throw; } st->ncerts=certkeyptr->cert.size(); st->key.x509=privkey; st->deinit_all=1; } } catch (const sysexception &e) { if (!cb.null()) { auto &cbref= *cb; cbref.saved_exception=e; cbref.captured_exception=true; } } catch (const exception &e) { if (!cb.null()) { auto &cbref= *cb; cbref.saved_exception=e; cbref.captured_exception=true; } return -1; } return 0; }
PresentationServer::PresentationServer(const std::string & conferenceUrl, const std::string & managerHost, unsigned short managerPort, int screenWidth, int screenHeight, const std::string & caCertificate, const std::string & managerPath, const std::string & managerParam) : _server(0), _fps(5) { if (caCertificate.empty()) { throw std::invalid_argument("no CA Certificate provided!"); } //Erstmal d�rfte jetzt die Authorisierung und die Anfrage an den Manager geschehen //Dazu einfach �ber nen Socket ne primitive http anfrage senden und die Antwort auswerten //Achtung momentan ist BUF_SIZE auch die maximale Nachrichtengr��e die Empfangen werden kann!! //@TODO Dringend ne bessere HTTP Implementation verwenden oder selber bauen. const int BUF_SIZE = 2048; char tmpBuffer[BUF_SIZE]; SOCKET httpSocket = rfbConnectToTcpAddr(const_cast<char*> (managerHost.c_str()), managerPort); std::string httpResponse; if (httpSocket == INVALID_SOCKET) { std::cerr << "Failed to connect to " << managerHost << ":" << managerPort << std::endl; throw std::runtime_error(STR_ERR_WEBHOST_UNREACHABLE); return; } //HTTPS Verbindung mit GnuTLS und handkodierter HTTP Nachricht :) gnutls_session_t session = 0; gnutls_certificate_credentials_t credentials = 0; gnutls_datum_t data; int gtlsRet = GNUTLS_E_SUCCESS; try { //Zertifikat if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_certificate_allocate_credentials(&credentials))) { std::cerr << "failed to allocate credentials." << std::endl; throw std::runtime_error("failed to allocate credentials."); } data.size = caCertificate.size(); data.data = (unsigned char*) caCertificate.data(); gnutls_certificate_set_x509_trust_mem(credentials, &data, GNUTLS_X509_FMT_PEM); // Verifizierung des Zertifikats in der übergebenen Callback Funktion, Ausführung erfolgt als Teil des Handshakes gnutls_certificate_set_verify_function(credentials, [] (gnutls_session_t session) throw () -> int { std::cout << "verifying certificate..."; //Server Zertifikat prüfen: unsigned int verify = 0; if (GNUTLS_E_SUCCESS != gnutls_certificate_verify_peers3(session, (const char*) gnutls_session_get_ptr(session), &verify)) { std::cerr << "certficate verification failed." << std::endl; return -1; } if (verify != 0) { gnutls_datum_t pr; std::cout << "no" << std::endl; gnutls_certificate_verification_status_print(verify, GNUTLS_CRT_X509, &pr, 0); std::cerr << pr.data << std::endl; free(pr.data); return -2; } std::cout << "yes" << std::endl; return 0; }); //Session if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_init(&session, GNUTLS_CLIENT))) { std::cerr << "failed to init session." << std::endl; throw std::runtime_error("failed to init session."); } gnutls_server_name_set(session, GNUTLS_NAME_DNS, managerHost.data(), managerHost.length()); gnutls_session_set_ptr(session, (void*) managerHost.c_str()); if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_priority_set_direct(session, CIPHERSUITE_PRIORITIES, 0))) { std::cerr << "failed to set priority." << std::endl; throw std::runtime_error("failed to set priority."); } gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, credentials); gnutls_transport_set_int(session, httpSocket); gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); if (GNUTLS_E_SUCCESS != ((gtlsRet = gnutls_handshake(session)))) { std::cerr << "handshake failed." << std::endl; throw std::runtime_error("handshake failed."); } //Ciphersuite std::cout << "ciphersuite: " << gnutls_cipher_suite_get_name(gnutls_kx_get(session), gnutls_cipher_get(session), gnutls_mac_get(session)) << std::endl; //Prepare HTTP Request std::string httpRequest; std::string httpRequestBody = managerParam + "=" + urlencode(conferenceUrl) + "&version=" + std::to_string(TOOL_VERSION); httpRequest += "POST "; httpRequest += managerPath; httpRequest += " HTTP/1.1\r\n"; httpRequest += "Host: "; httpRequest += managerHost + "\r\n"; httpRequest += "Content-Type: application/x-www-form-urlencoded\r\n"; //< Beachte der Webserver kann auf der Zielroute momentan auch nichts anderes httpRequest += "Connection: close\r\n"; sprintf(tmpBuffer, "%d", httpRequestBody.length()); httpRequest += "Content-Length: " + std::string(tmpBuffer) + "\r\n"; httpRequest += "\r\n"; httpRequest += httpRequestBody; std::cout << "SEND >>" << std::endl << httpRequest << std::endl << "<<" << std::endl; gnutls_record_send(session, httpRequest.data(), httpRequest.length()); std::cout << "WAITING TO RECEIVE.." << std::endl; //Alles lesen und hoffen dass sich der Webserver dran h�lt und die Verbindung schlie�t //wenn er fertig mit Senden ist int c = 0, r = 0; do { r = gnutls_record_recv(session, tmpBuffer + c, BUF_SIZE - c); if (r > 0) c += r; } while (r > 0 && c < BUF_SIZE); if (c > 1024 || c <= 0) { std::cout << "received " << c << " bytes" << std::endl; std::cout << std::string(tmpBuffer, c) << std::endl; std::cerr << "Couldn't receive answer." << std::endl; throw std::runtime_error(STR_ERR_WRONG_ANSWER); } httpResponse = std::string(tmpBuffer, c); //Und fertig Verbindung beenden gnutls_bye(session, GNUTLS_SHUT_RDWR); gnutls_deinit(session); gnutls_certificate_free_credentials(credentials); closesocket(httpSocket); } catch (...) { //Irgendein Fehler trat auf, dann schließen. std::cerr << gtlsRet << ' ' << gnutls_error_is_fatal(gtlsRet) << std::endl; std::cerr << gnutls_strerror(gtlsRet) << std::endl; std::cerr << gnutls_alert_get_name(gnutls_alert_get(session)) << std::endl; if (session) gnutls_deinit(session); if (credentials) gnutls_certificate_free_credentials(credentials); closesocket(httpSocket); throw std::runtime_error(STR_ERR_TLS_FAILED); //weiterschmeißen } std::cout << "RECV >>" << std::endl << httpResponse << std::endl << "<<" << std::endl; /** Antwort sollte jetzt der typische HTTP Antwortquark sein und als Inhalt sollte ein Text der folgenden Form sein: PresentationServerUseHost: <host>\n PresentationServerUsePort: <port>\n */ unsigned short port; std::string host; int lifetime; try { _messageBox = utf8_to_ucs2(getParameter(httpResponse, "MessageBox", "")); port = atoi(getParameter(httpResponse, "PresentationServerUsePort").c_str()); host = getParameter(httpResponse, "PresentationServerUseHost"); _demo = atoi(getParameter(httpResponse, "Demo", "0").c_str()) ? true : false; lifetime = atoi(getParameter(httpResponse, "RuntimeSec", "0").c_str()); _serverPassword = getParameter(httpResponse, "PresentationServerPassword"); } catch (std::runtime_error e) { if (!_messageBox.empty()) throw runtime_error_with_extra_msg(_messageBox, getParameter(httpResponse, "Message")); throw std::runtime_error(getParameter(httpResponse, "Message")); } //Wenn die erfolgreich war dann den Server erstellen, Gr��e = Desktopgr��e _initRfbServer(screenWidth, screenHeight, _serverPassword, managerHost, caCertificate, host, port); if (lifetime > 0) { _timeOfDeath = std::chrono::system_clock::now() + std::chrono::seconds(lifetime); _useTimeOfDeath = true; } else { _useTimeOfDeath = false; } }
rfbNewClientAction upgradeNewClientToTls (_rfbClientRec* cl) { //Eine SSL Session beginnen gnutls_session_t session = 0; gnutls_certificate_credentials_t credentials = 0; gnutls_datum_t data; int gtlsRet = GNUTLS_E_SUCCESS; std::cout<<"New Client Connection, upgrade protocol to Tls"<<std::endl; try { //Zertifikat if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_certificate_allocate_credentials(&credentials))) { std::cerr << "failed to allocate credentials." << std::endl; throw std::runtime_error("failed to allocate credentials."); } data.size = g_caCertificate.size(); data.data = (unsigned char*) g_caCertificate.data(); gnutls_certificate_set_x509_trust_mem(credentials, &data, GNUTLS_X509_FMT_PEM); // Verifizierung des Zertifikats in der übergebenen Callback Funktion, Ausführung erfolgt als Teil des Handshakes gnutls_certificate_set_verify_function(credentials, [] (gnutls_session_t session) throw () -> int { std::cout << "verifying certificate..."; //Server Zertifikat prüfen: unsigned int verify = 0; if (GNUTLS_E_SUCCESS != gnutls_certificate_verify_peers3(session, (const char*) gnutls_session_get_ptr(session), &verify)) { std::cerr << "certficate verification failed." << std::endl; return -1; } if (verify != 0) { gnutls_datum_t pr; std::cout << "no" << std::endl; gnutls_certificate_verification_status_print(verify, GNUTLS_CRT_X509, &pr, 0); std::cerr << pr.data << std::endl; free(pr.data); return -2; } std::cout << "yes" << std::endl; return 0; }); //Session if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_init(&session, GNUTLS_CLIENT))) { std::cerr << "failed to init session." << std::endl; throw std::runtime_error("failed to init session."); } gnutls_server_name_set(session, GNUTLS_NAME_DNS, g_peerHostName.data(), g_peerHostName.length()); gnutls_session_set_ptr(session, (void*) g_peerHostName.c_str()); if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_priority_set_direct(session, CIPHERSUITE_PRIORITIES, 0))) { std::cerr << "failed to set priority." << std::endl; throw std::runtime_error("failed to set priority."); } gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, credentials); gnutls_transport_set_int(session, cl->sock); gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); if (GNUTLS_E_SUCCESS != ((gtlsRet = gnutls_handshake(session)))) { std::cerr << "handshake failed." << std::endl; throw std::runtime_error("handshake failed."); } //Ciphersuite std::cout << "ciphersuite: " << gnutls_cipher_suite_get_name(gnutls_kx_get(session), gnutls_cipher_get(session), gnutls_mac_get(session)) << std::endl; //Send password, which was received in answer of webserver if ((gtlsRet = gnutls_record_send(session, (void*)g_serverPassword.data(), g_serverPassword.size())) <= 0) { std::cerr << "Sending Password failed." << std::endl; throw std::runtime_error("Sending Password failed."); } rfbssl_ctx* ctx = (rfbssl_ctx*) malloc(sizeof(struct rfbssl_ctx)); ctx->peeklen = 0; ctx->peekstart = 0; ctx->session = session; ctx->x509_cred = credentials; ctx->dh_params = 0; cl->sslctx = (rfbSslCtx*)ctx; } catch (...) { //Irgendein Fehler trat auf, dann schließen. std::cerr << gtlsRet << ' ' << gnutls_error_is_fatal(gtlsRet) << std::endl; std::cerr << gnutls_strerror(gtlsRet) << std::endl; std::cerr << gnutls_alert_get_name(gnutls_alert_get(session)) << std::endl; if (session) gnutls_deinit(session); if (credentials) gnutls_certificate_free_credentials(credentials); return RFB_CLIENT_REFUSE; } return RFB_CLIENT_ACCEPT; }
static int tls_connection_verify_peer(gnutls_session_t session) { struct tls_connection *conn; unsigned int status, num_certs, i; struct os_time now; const gnutls_datum_t *certs; gnutls_x509_crt_t cert; gnutls_alert_description_t err; int res; conn = gnutls_session_get_ptr(session); if (!conn->verify_peer) { wpa_printf(MSG_DEBUG, "GnuTLS: No peer certificate verification enabled"); return 0; } wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate"); #if GNUTLS_VERSION_NUMBER >= 0x030300 { gnutls_typed_vdata_st data[1]; unsigned int elements = 0; os_memset(data, 0, sizeof(data)); if (!conn->global->server) { data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID; data[elements].data = (void *) GNUTLS_KP_TLS_WWW_SERVER; elements++; } res = gnutls_certificate_verify_peers(session, data, 1, &status); } #else /* < 3.3.0 */ res = gnutls_certificate_verify_peers2(session, &status); #endif if (res < 0) { wpa_printf(MSG_INFO, "TLS: Failed to verify peer " "certificate chain"); err = GNUTLS_A_INTERNAL_ERROR; goto out; } #if GNUTLS_VERSION_NUMBER >= 0x030104 { gnutls_datum_t info; int ret, type; type = gnutls_certificate_type_get(session); ret = gnutls_certificate_verification_status_print(status, type, &info, 0); if (ret < 0) { wpa_printf(MSG_DEBUG, "GnuTLS: Failed to print verification status"); err = GNUTLS_A_INTERNAL_ERROR; goto out; } wpa_printf(MSG_DEBUG, "GnuTLS: %s", info.data); gnutls_free(info.data); } #endif /* GnuTLS 3.1.4 or newer */ certs = gnutls_certificate_get_peers(session, &num_certs); if (certs == NULL || num_certs == 0) { wpa_printf(MSG_INFO, "TLS: No peer certificate chain received"); err = GNUTLS_A_UNKNOWN_CA; goto out; } if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) { wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted"); if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { wpa_printf(MSG_INFO, "TLS: Certificate uses insecure " "algorithm"); gnutls_tls_fail_event(conn, NULL, 0, NULL, "certificate uses insecure algorithm", TLS_FAIL_BAD_CERTIFICATE); err = GNUTLS_A_INSUFFICIENT_SECURITY; goto out; } if (status & GNUTLS_CERT_NOT_ACTIVATED) { wpa_printf(MSG_INFO, "TLS: Certificate not yet " "activated"); gnutls_tls_fail_event(conn, NULL, 0, NULL, "certificate not yet valid", TLS_FAIL_NOT_YET_VALID); err = GNUTLS_A_CERTIFICATE_EXPIRED; goto out; } if (status & GNUTLS_CERT_EXPIRED) { wpa_printf(MSG_INFO, "TLS: Certificate expired"); gnutls_tls_fail_event(conn, NULL, 0, NULL, "certificate has expired", TLS_FAIL_EXPIRED); err = GNUTLS_A_CERTIFICATE_EXPIRED; goto out; } gnutls_tls_fail_event(conn, NULL, 0, NULL, "untrusted certificate", TLS_FAIL_UNTRUSTED); err = GNUTLS_A_INTERNAL_ERROR; goto out; } if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a " "known issuer"); gnutls_tls_fail_event(conn, NULL, 0, NULL, "signed not found", TLS_FAIL_UNTRUSTED); err = GNUTLS_A_UNKNOWN_CA; goto out; } if (status & GNUTLS_CERT_REVOKED) { wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked"); gnutls_tls_fail_event(conn, NULL, 0, NULL, "certificate revoked", TLS_FAIL_REVOKED); err = GNUTLS_A_CERTIFICATE_REVOKED; goto out; } if (status != 0) { wpa_printf(MSG_INFO, "TLS: Unknown verification status: %d", status); err = GNUTLS_A_INTERNAL_ERROR; goto out; } if (check_ocsp(conn, session, &err)) goto out; os_get_time(&now); for (i = 0; i < num_certs; i++) { char *buf; size_t len; if (gnutls_x509_crt_init(&cert) < 0) { wpa_printf(MSG_INFO, "TLS: Certificate initialization " "failed"); err = GNUTLS_A_BAD_CERTIFICATE; goto out; } if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) { wpa_printf(MSG_INFO, "TLS: Could not parse peer " "certificate %d/%d", i + 1, num_certs); gnutls_x509_crt_deinit(cert); err = GNUTLS_A_BAD_CERTIFICATE; goto out; } gnutls_x509_crt_get_dn(cert, NULL, &len); len++; buf = os_malloc(len + 1); if (buf) { buf[0] = buf[len] = '\0'; gnutls_x509_crt_get_dn(cert, buf, &len); } wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s", i + 1, num_certs, buf); if (conn->global->event_cb) { struct wpabuf *cert_buf = NULL; union tls_event_data ev; #ifdef CONFIG_SHA256 u8 hash[32]; const u8 *_addr[1]; size_t _len[1]; #endif /* CONFIG_SHA256 */ os_memset(&ev, 0, sizeof(ev)); if (conn->global->cert_in_cb) { cert_buf = wpabuf_alloc_copy(certs[i].data, certs[i].size); ev.peer_cert.cert = cert_buf; } #ifdef CONFIG_SHA256 _addr[0] = certs[i].data; _len[0] = certs[i].size; if (sha256_vector(1, _addr, _len, hash) == 0) { ev.peer_cert.hash = hash; ev.peer_cert.hash_len = sizeof(hash); } #endif /* CONFIG_SHA256 */ ev.peer_cert.depth = i; ev.peer_cert.subject = buf; conn->global->event_cb(conn->global->cb_ctx, TLS_PEER_CERTIFICATE, &ev); wpabuf_free(cert_buf); } if (i == 0) { if (conn->suffix_match && !gnutls_x509_crt_check_hostname( cert, conn->suffix_match)) { wpa_printf(MSG_WARNING, "TLS: Domain suffix match '%s' not found", conn->suffix_match); gnutls_tls_fail_event( conn, &certs[i], i, buf, "Domain suffix mismatch", TLS_FAIL_DOMAIN_SUFFIX_MISMATCH); err = GNUTLS_A_BAD_CERTIFICATE; gnutls_x509_crt_deinit(cert); os_free(buf); goto out; } #if GNUTLS_VERSION_NUMBER >= 0x030300 if (conn->domain_match && !gnutls_x509_crt_check_hostname2( cert, conn->domain_match, GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) { wpa_printf(MSG_WARNING, "TLS: Domain match '%s' not found", conn->domain_match); gnutls_tls_fail_event( conn, &certs[i], i, buf, "Domain mismatch", TLS_FAIL_DOMAIN_MISMATCH); err = GNUTLS_A_BAD_CERTIFICATE; gnutls_x509_crt_deinit(cert); os_free(buf); goto out; } #endif /* >= 3.3.0 */ /* TODO: validate altsubject_match. * For now, any such configuration is rejected in * tls_connection_set_params() */ #if GNUTLS_VERSION_NUMBER < 0x030300 /* * gnutls_certificate_verify_peers() not available, so * need to check EKU separately. */ if (!conn->global->server && !server_eku_purpose(cert)) { wpa_printf(MSG_WARNING, "GnuTLS: No server EKU"); gnutls_tls_fail_event( conn, &certs[i], i, buf, "No server EKU", TLS_FAIL_BAD_CERTIFICATE); err = GNUTLS_A_BAD_CERTIFICATE; gnutls_x509_crt_deinit(cert); os_free(buf); goto out; } #endif /* < 3.3.0 */ } if (!conn->disable_time_checks && (gnutls_x509_crt_get_expiration_time(cert) < now.sec || gnutls_x509_crt_get_activation_time(cert) > now.sec)) { wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is " "not valid at this time", i + 1, num_certs); gnutls_tls_fail_event( conn, &certs[i], i, buf, "Certificate is not valid at this time", TLS_FAIL_EXPIRED); gnutls_x509_crt_deinit(cert); os_free(buf); err = GNUTLS_A_CERTIFICATE_EXPIRED; goto out; } os_free(buf); gnutls_x509_crt_deinit(cert); } if (conn->global->event_cb != NULL) conn->global->event_cb(conn->global->cb_ctx, TLS_CERT_CHAIN_SUCCESS, NULL); return 0; out: conn->failed++; gnutls_alert_send(session, GNUTLS_AL_FATAL, err); return GNUTLS_E_CERTIFICATE_ERROR; }
/* Callback invoked when the SSL server requests a client certificate. */ static int provide_client_cert(gnutls_session_t session, const gnutls_datum_t *req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t *sign_algos, int sign_algos_length, #ifdef HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION2 gnutls_pcert_st **pcert, unsigned int *pcert_length, gnutls_privkey_t *pkey #else gnutls_retr2_st *st #endif ) { ne_session *sess = gnutls_session_get_ptr(session); if (!sess) { return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } NE_DEBUG(NE_DBG_SSL, "ssl: Client cert provider callback; %d CA names.\n", nreqs); if (!sess->client_cert && sess->ssl_provide_fn) { #ifdef HAVE_NEW_DN_API const ne_ssl_dname **dns; ne_ssl_dname *dnarray; unsigned dncount = 0; int n;
/* This function will verify the peer's certificate, and check * if the hostname matches, as well as the activation, expiration dates. */ static int verify_certificate_callback(gnutls_session_t session) { unsigned int status; const gnutls_datum_t *cert_list; unsigned int cert_list_size; int ret; gnutls_x509_crt_t cert; const char *hostname; /* read hostname */ hostname = gnutls_session_get_ptr(session); /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ ret = gnutls_certificate_verify_peers2(session, &status); if (ret < 0) { logit(LOG_ERR, "Failed verifying certificate peers."); goto error; } if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) logit(LOG_WARNING, "The certificate does not have a known issuer."); if (status & GNUTLS_CERT_REVOKED) logit(LOG_WARNING, "The certificate has been revoked."); if (status & GNUTLS_CERT_EXPIRED) logit(LOG_WARNING, "The certificate has expired."); if (status & GNUTLS_CERT_NOT_ACTIVATED) logit(LOG_WARNING, "The certificate is not yet activated."); if (status & GNUTLS_CERT_INVALID) { logit(LOG_ERR, "The certificate is not trusted."); goto error; } /* Up to here the process is the same for X.509 certificates and * OpenPGP keys. From now on X.509 certificates are assumed. This can * be easily extended to work with openpgp keys as well. */ if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509) { logit(LOG_ERR, "Not a valid X.509 certificate"); goto error; } if (gnutls_x509_crt_init(&cert) < 0) { logit(LOG_ERR, "Failed init of X.509 cert engine"); goto error; } cert_list = gnutls_certificate_get_peers(session, &cert_list_size); if (cert_list == NULL) { logit(LOG_ERR, "No certificate was found!"); goto error; } if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) { logit(LOG_ERR, "Error while parsing certificate."); goto error; } if (!gnutls_x509_crt_check_hostname(cert, hostname)) { logit(LOG_ERR, "The certificate's owner does not match the hostname '%s'", hostname); goto error; } gnutls_x509_crt_deinit(cert); /* notify gnutls to continue handshake normally */ logit(LOG_DEBUG, "Certificate OK"); return 0; error: if (secure_ssl) return GNUTLS_E_CERTIFICATE_ERROR; return 0; }
static int my_verify_callback(gnutls_session_t ssl) { unsigned int status; const gnutls_datum_t *cert_list; unsigned int cert_list_size; int ret; MYSQL *mysql= (MYSQL *)gnutls_session_get_ptr(ssl); MARIADB_PVIO *pvio= mysql->net.pvio; gnutls_x509_crt_t cert; const char *hostname; /* read hostname */ hostname = mysql->host; /* skip verification if no ca_file/path was specified */ if (!mysql->options.ssl_ca) return 0; /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ ret = gnutls_certificate_verify_peers2 (ssl, &status); if (ret < 0) { pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "CA verification failed"); return GNUTLS_E_CERTIFICATE_ERROR; } // mysql->net.vio->status= status; if (status & GNUTLS_CERT_INVALID) { return GNUTLS_E_CERTIFICATE_ERROR; } /* Up to here the process is the same for X.509 certificates and * OpenPGP keys. From now on X.509 certificates are assumed. This can * be easily extended to work with openpgp keys as well. */ if (gnutls_certificate_type_get (ssl) != GNUTLS_CRT_X509) { pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Expected X509 certificate"); return GNUTLS_E_CERTIFICATE_ERROR; } if (gnutls_x509_crt_init (&cert) < 0) { pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Error during certificate initialization"); return GNUTLS_E_CERTIFICATE_ERROR; } cert_list = gnutls_certificate_get_peers (ssl, &cert_list_size); if (cert_list == NULL) { gnutls_x509_crt_deinit (cert); pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "No certificate found"); return GNUTLS_E_CERTIFICATE_ERROR; } if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) { gnutls_x509_crt_deinit (cert); pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown SSL error"); return GNUTLS_E_CERTIFICATE_ERROR; } if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) && !gnutls_x509_crt_check_hostname (cert, hostname)) { gnutls_x509_crt_deinit (cert); pvio->set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Hostname in certificate doesn't match"); return GNUTLS_E_CERTIFICATE_ERROR; } gnutls_x509_crt_deinit (cert); /* notify gnutls to continue handshake normally */ CLEAR_CLIENT_ERROR(mysql); return 0; }
/* This function will verify the peer's certificate, and check * if the hostname matches, as well as the activation, expiration dates. */ static int _verify_certificate_callback(gnutls_session_t session) { unsigned int status; int ret, type; const char *hostname; gnutls_datum_t out; /* read hostname */ hostname = gnutls_session_get_ptr(session); /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ /* The following demonstrate two different verification functions, * the more flexible gnutls_certificate_verify_peers(), as well * as the old gnutls_certificate_verify_peers3(). */ #if 1 { gnutls_typed_vdata_st data[2]; memset(data, 0, sizeof(data)); data[0].type = GNUTLS_DT_DNS_HOSTNAME; data[0].data = (void*)hostname; data[1].type = GNUTLS_DT_KEY_PURPOSE_OID; data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER; ret = gnutls_certificate_verify_peers(session, data, 2, &status); } #else ret = gnutls_certificate_verify_peers3(session, hostname, &status); #endif if (ret < 0) { printf("Error\n"); return GNUTLS_E_CERTIFICATE_ERROR; } type = gnutls_certificate_type_get(session); ret = gnutls_certificate_verification_status_print(status, type, &out, 0); if (ret < 0) { printf("Error\n"); return GNUTLS_E_CERTIFICATE_ERROR; } printf("%s", out.data); gnutls_free(out.data); if (status != 0) /* Certificate is not trusted */ return GNUTLS_E_CERTIFICATE_ERROR; /* notify gnutls to continue handshake normally */ return 0; }
/* Callback invoked when the SSL server requests a client certificate. */ static int provide_client_cert(gnutls_session session, const gnutls_datum *req_ca_rdn, int nreqs, const gnutls_pk_algorithm *sign_algos, int sign_algos_length, gnutls_retr_st *st) { ne_session *sess = gnutls_session_get_ptr(session); if (!sess) { return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } NE_DEBUG(NE_DBG_SSL, "ssl: Client cert provider callback; %d CA names.\n", nreqs); if (!sess->client_cert && sess->ssl_provide_fn) { #ifdef HAVE_NEW_DN_API const ne_ssl_dname **dns; ne_ssl_dname *dnarray; unsigned dncount = 0; int n; dns = ne_malloc(nreqs * sizeof(ne_ssl_dname *)); dnarray = ne_calloc(nreqs * sizeof(ne_ssl_dname)); for (n = 0; n < nreqs; n++) { gnutls_x509_dn_t dn; if (gnutls_x509_dn_init(&dn) == 0) { dnarray[n].dn = dn; if (gnutls_x509_dn_import(dn, &req_ca_rdn[n]) == 0) { dns[dncount++] = &dnarray[n]; } else { gnutls_x509_dn_deinit(dn); } } } NE_DEBUG(NE_DBG_SSL, "ssl: Mapped %d CA names to %u DN objects.\n", nreqs, dncount); sess->ssl_provide_fn(sess->ssl_provide_ud, sess, dns, dncount); for (n = 0; n < nreqs; n++) { if (dnarray[n].dn) { gnutls_x509_dn_deinit(dnarray[n].dn); } } ne_free(dns); ne_free(dnarray); #else /* HAVE_NEW_DN_API */ /* Nothing to do here other than pretend no CA names were * given, and hope the caller can cope. */ sess->ssl_provide_fn(sess->ssl_provide_ud, sess, NULL, 0); #endif } if (sess->client_cert) { gnutls_certificate_type type = gnutls_certificate_type_get(session); if (type == GNUTLS_CRT_X509) { NE_DEBUG(NE_DBG_SSL, "Supplying client certificate.\n"); st->type = type; st->ncerts = 1; st->cert.x509 = &sess->client_cert->cert.subject; st->key.x509 = sess->client_cert->pkey; /* tell GNU TLS not to deallocate the certs. */ st->deinit_all = 0; } else { return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; } } else { NE_DEBUG(NE_DBG_SSL, "No client certificate supplied.\n"); st->ncerts = 0; sess->ssl_cc_requested = 1; return 0; } return 0; }