static int verify_certificate_callback (gnutls_session_t session) { if (trust_override) return 0; // 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; 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. */ 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; }
/* returns false (0) if not verified, or true (1) otherwise */ int cert_verify(gnutls_session_t session, const char *hostname) { int rc; unsigned int status = 0; gnutls_datum_t out; int type; rc = gnutls_certificate_verify_peers3(session, hostname, &status); if (rc == GNUTLS_E_NO_CERTIFICATE_FOUND) { printf("- Peer did not send any certificate.\n"); return 0; } if (rc < 0) { printf("- Could not verify certificate (err: %s)\n", gnutls_strerror(rc)); return 0; } type = gnutls_certificate_type_get(session); rc = gnutls_certificate_verification_status_print(status, type, &out, 0); if (rc < 0) { printf("- Could not print verification flags (err: %s)\n", gnutls_strerror(rc)); return 0; } printf("- Status: %s\n", out.data); gnutls_free(out.data); if (status) return 0; return 1; }
/* 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; }
/* 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; }
void test_cli_serv(gnutls_certificate_credentials_t server_cred, const char *prio, const gnutls_datum_t *ca_cert, const char *host) { int exit_code = EXIT_SUCCESS; int ret; /* Server stuff. */ gnutls_session_t server; int sret = GNUTLS_E_AGAIN; /* Client stuff. */ gnutls_certificate_credentials_t clientx509cred; gnutls_session_t client; int cret = GNUTLS_E_AGAIN; /* General init. */ reset_buffers(); /* Init server */ gnutls_init(&server, GNUTLS_SERVER); gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, server_cred); gnutls_priority_set_direct(server, prio, NULL); gnutls_transport_set_push_function(server, server_push); gnutls_transport_set_pull_function(server, server_pull); gnutls_transport_set_ptr(server, server); /* Init client */ ret = gnutls_certificate_allocate_credentials(&clientx509cred); if (ret < 0) exit(1); ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, ca_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) exit(1); ret = gnutls_init(&client, GNUTLS_CLIENT); if (ret < 0) exit(1); assert(gnutls_server_name_set(client, GNUTLS_NAME_DNS, host, strlen(host))>=0); ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred); if (ret < 0) exit(1); gnutls_priority_set_direct(client, prio, NULL); gnutls_transport_set_push_function(client, client_push); gnutls_transport_set_pull_function(client, client_pull); gnutls_transport_set_ptr(client, client); HANDSHAKE(client, server); /* check the number of certificates received and verify */ { gnutls_typed_vdata_st data[2]; unsigned status; memset(data, 0, sizeof(data)); data[0].type = GNUTLS_DT_DNS_HOSTNAME; data[0].data = (void*)host; data[1].type = GNUTLS_DT_KEY_PURPOSE_OID; data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER; ret = gnutls_certificate_verify_peers(client, data, 2, &status); if (ret < 0) { fail("could not verify certificate: %s\n", gnutls_strerror(ret)); exit(1); } if (status != 0) { gnutls_datum_t t; assert(gnutls_certificate_verification_status_print(status, GNUTLS_CRT_X509, &t, 0)>=0); fail("could not verify certificate for '%s': %.4x: %s\n", host, status, t.data); gnutls_free(t.data); exit(1); } /* check gnutls_certificate_verify_peers3 */ ret = gnutls_certificate_verify_peers3(client, host, &status); if (ret < 0) { fail("could not verify certificate: %s\n", gnutls_strerror(ret)); exit(1); } if (status != 0) { gnutls_datum_t t; assert(gnutls_certificate_verification_status_print(status, GNUTLS_CRT_X509, &t, 0)>=0); fail("could not verify certificate3: %.4x: %s\n", status, t.data); gnutls_free(t.data); exit(1); } } gnutls_bye(client, GNUTLS_SHUT_RDWR); gnutls_bye(server, GNUTLS_SHUT_RDWR); gnutls_deinit(client); gnutls_deinit(server); gnutls_certificate_free_credentials(clientx509cred); if (debug > 0) { if (exit_code == 0) puts("Self-test successful"); else puts("Self-test failed"); } }
int TLSClient::verify_certificate () const { if (_trust == TLSClient::allow_all) return 0; // 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; const char* hostname = _host.c_str(); #if GNUTLS_VERSION_NUMBER >= 0x030104 if (_trust == TLSClient::ignore_hostname) hostname = NULL; int ret = gnutls_certificate_verify_peers3 (_session, hostname, &status); if (ret < 0) { if (_debug) std::cout << "c: ERROR Certificate verification peers3 failed. " << gnutls_strerror (ret) << "\n"; return GNUTLS_E_CERTIFICATE_ERROR; } #else int ret = gnutls_certificate_verify_peers2 (_session, &status); if (ret < 0) { if (_debug) std::cout << "c: ERROR Certificate verification peers2 failed. " << gnutls_strerror (ret) << "\n"; return GNUTLS_E_CERTIFICATE_ERROR; } if ((status == 0) && (_trust != TLSClient::ignore_hostname)) { if (gnutls_certificate_type_get (_session) == GNUTLS_CRT_X509) { const gnutls_datum* cert_list; unsigned int cert_list_size; gnutls_x509_crt cert; cert_list = gnutls_certificate_get_peers (_session, &cert_list_size); if (cert_list_size == 0) { if (_debug) std::cout << "c: ERROR Certificate get peers failed. " << gnutls_strerror (ret) << "\n"; return GNUTLS_E_CERTIFICATE_ERROR; } ret = gnutls_x509_crt_init (&cert); if (ret < 0) { if (_debug) std::cout << "c: ERROR x509 init failed. " << gnutls_strerror (ret) << "\n"; return GNUTLS_E_CERTIFICATE_ERROR; } ret = gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER); if (ret < 0) { if (_debug) std::cout << "c: ERROR x509 cert import. " << gnutls_strerror (ret) << "\n"; gnutls_x509_crt_deinit(cert); return GNUTLS_E_CERTIFICATE_ERROR; } if (gnutls_x509_crt_check_hostname (cert, hostname) == 0) { if (_debug) std::cout << "c: ERROR x509 cert check hostname. " << gnutls_strerror (ret) << "\n"; gnutls_x509_crt_deinit(cert); return GNUTLS_E_CERTIFICATE_ERROR; } } else return GNUTLS_E_CERTIFICATE_ERROR; } #endif #if GNUTLS_VERSION_NUMBER >= 0x030104 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) { if (_debug) std::cout << "c: ERROR certificate verification status. " << gnutls_strerror (ret) << "\n"; return GNUTLS_E_CERTIFICATE_ERROR; } if (_debug) std::cout << "c: INFO " << out.data << "\n"; gnutls_free (out.data); #endif if (status != 0) return GNUTLS_E_CERTIFICATE_ERROR; // Continue handshake. 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; }
/* if @host is NULL certificate check is skipped */ static int _test_cli_serv(gnutls_certificate_credentials_t server_cred, gnutls_certificate_credentials_t client_cred, const char *serv_prio, const char *cli_prio, const char *host, void *priv, callback_func *client_cb, callback_func *server_cb, unsigned expect_verification_failure, unsigned require_cert, int serv_err, int cli_err) { int exit_code = EXIT_SUCCESS; int ret; /* Server stuff. */ gnutls_session_t server; int sret = GNUTLS_E_AGAIN; /* Client stuff. */ gnutls_session_t client; int cret = GNUTLS_E_AGAIN; /* General init. */ reset_buffers(); /* Init server */ gnutls_init(&server, GNUTLS_SERVER); gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, server_cred); gnutls_priority_set_direct(server, serv_prio, NULL); gnutls_transport_set_push_function(server, server_push); gnutls_transport_set_pull_function(server, server_pull); gnutls_transport_set_ptr(server, server); if (require_cert) gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUIRE); ret = gnutls_init(&client, GNUTLS_CLIENT); if (ret < 0) exit(1); if (host) { if (strncmp(host, "raw:", 4) == 0) { assert(_gnutls_server_name_set_raw(client, GNUTLS_NAME_DNS, host+4, strlen(host+4))>=0); host += 4; } else { assert(gnutls_server_name_set(client, GNUTLS_NAME_DNS, host, strlen(host))>=0); } } ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, client_cred); if (ret < 0) exit(1); gnutls_priority_set_direct(client, cli_prio, NULL); gnutls_transport_set_push_function(client, client_push); gnutls_transport_set_pull_function(client, client_pull); gnutls_transport_set_ptr(client, client); if (cli_err == 0 && serv_err == 0) { HANDSHAKE(client, server); } else { HANDSHAKE_EXPECT(client, server, cli_err, serv_err); } /* check the number of certificates received and verify */ if (host) { gnutls_typed_vdata_st data[2]; unsigned status; memset(data, 0, sizeof(data)); data[0].type = GNUTLS_DT_DNS_HOSTNAME; data[0].data = (void*)host; data[1].type = GNUTLS_DT_KEY_PURPOSE_OID; data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER; ret = gnutls_certificate_verify_peers(client, data, 2, &status); if (ret < 0) { fail("could not verify certificate: %s\n", gnutls_strerror(ret)); exit(1); } if (expect_verification_failure && status != 0) { ret = status; goto cleanup; } else if (expect_verification_failure && status == 0) { fail("expected verification failure but verification succeeded!\n"); } if (status != 0) { gnutls_datum_t t; assert(gnutls_certificate_verification_status_print(status, GNUTLS_CRT_X509, &t, 0)>=0); fail("could not verify certificate for '%s': %.4x: %s\n", host, status, t.data); gnutls_free(t.data); exit(1); } /* check gnutls_certificate_verify_peers3 */ ret = gnutls_certificate_verify_peers3(client, host, &status); if (ret < 0) { fail("could not verify certificate: %s\n", gnutls_strerror(ret)); exit(1); } if (status != 0) { gnutls_datum_t t; assert(gnutls_certificate_verification_status_print(status, GNUTLS_CRT_X509, &t, 0)>=0); fail("could not verify certificate3: %.4x: %s\n", status, t.data); gnutls_free(t.data); exit(1); } } ret = 0; cleanup: if (client_cb) client_cb(client, priv); if (server_cb) server_cb(server, priv); gnutls_bye(client, GNUTLS_SHUT_RDWR); gnutls_bye(server, GNUTLS_SHUT_RDWR); gnutls_deinit(client); gnutls_deinit(server); if (debug > 0) { if (exit_code == 0) puts("Self-test successful"); else puts("Self-test failed"); } return ret; }