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; }
static int verify_cert_authorized(gnutls_session_t session) { unsigned status; gnutls_certificate_type_t type; gnutls_datum_t out; int r; r = gnutls_certificate_verify_peers2(session, &status); if (r < 0) return log_error_errno(r, "gnutls_certificate_verify_peers2 failed: %m"); type = gnutls_certificate_type_get(session); r = gnutls_certificate_verification_status_print(status, type, &out, 0); if (r < 0) return log_error_errno(r, "gnutls_certificate_verification_status_print failed: %m"); log_info("Certificate status: %s", out.data); return status == 0 ? 0 : -EPERM; }
/* 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 main(void) { int ret, sd, ii; gnutls_session_t session; char buffer[MAX_BUF + 1]; gnutls_datum_t out; int type; unsigned status; #if 0 const char *err; #endif gnutls_certificate_credentials_t xcred; if (gnutls_check_version("3.4.6") == NULL) { fprintf(stderr, "GnuTLS 3.4.6 or later is required for this example\n"); exit(1); } /* for backwards compatibility with gnutls < 3.3.0 */ CHECK(gnutls_global_init()); /* X509 stuff */ CHECK(gnutls_certificate_allocate_credentials(&xcred)); /* sets the trusted cas file */ CHECK(gnutls_certificate_set_x509_trust_file(xcred, CAFILE, GNUTLS_X509_FMT_PEM)); /* If client holds a certificate it can be set using the following: * gnutls_certificate_set_x509_key_file (xcred, "cert.pem", "key.pem", GNUTLS_X509_FMT_PEM); */ /* Initialize TLS session */ CHECK(gnutls_init(&session, GNUTLS_CLIENT)); CHECK(gnutls_server_name_set(session, GNUTLS_NAME_DNS, "my_host_name", strlen("my_host_name"))); /* It is recommended to use the default priorities */ CHECK(gnutls_set_default_priority(session)); #if 0 /* if more fine-graned control is required */ ret = gnutls_priority_set_direct(session, "NORMAL", &err); if (ret < 0) { if (ret == GNUTLS_E_INVALID_REQUEST) { fprintf(stderr, "Syntax error at: %s\n", err); } exit(1); } #endif /* put the x509 credentials to the current session */ CHECK(gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred)); gnutls_session_set_verify_cert(session, "my_host_name", 0); /* connect to the peer */ sd = tcp_connect(); gnutls_transport_set_int(session, sd); gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); /* Perform the TLS handshake */ do { ret = gnutls_handshake(session); } while (ret < 0 && gnutls_error_is_fatal(ret) == 0); if (ret < 0) { if (ret == GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR) { /* check certificate verification status */ type = gnutls_certificate_type_get(session); status = gnutls_session_get_verify_cert_status(session); CHECK(gnutls_certificate_verification_status_print(status, type, &out, 0)); printf("cert verify output: %s\n", out.data); gnutls_free(out.data); } fprintf(stderr, "*** Handshake failed: %s\n", gnutls_strerror(ret)); goto end; } else { char *desc; desc = gnutls_session_get_desc(session); printf("- Session info: %s\n", desc); gnutls_free(desc); } /* send data */ CHECK(gnutls_record_send(session, MSG, strlen(MSG))); ret = gnutls_record_recv(session, buffer, MAX_BUF); if (ret == 0) { printf("- Peer has closed the TLS connection\n"); goto end; } else if (ret < 0 && gnutls_error_is_fatal(ret) == 0) { fprintf(stderr, "*** Warning: %s\n", gnutls_strerror(ret)); } else if (ret < 0) { fprintf(stderr, "*** Error: %s\n", gnutls_strerror(ret)); goto end; } if (ret > 0) { printf("- Received %d bytes: ", ret); for (ii = 0; ii < ret; ii++) { fputc(buffer[ii], stdout); } fputs("\n", stdout); } CHECK(gnutls_bye(session, GNUTLS_SHUT_RDWR)); end: tcp_close(sd); gnutls_deinit(session); gnutls_certificate_free_credentials(xcred); gnutls_global_deinit(); return 0; }
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; }
void doit(void) { int exit_val = 0; size_t i; int ret; gnutls_x509_trust_list_t tl; unsigned int verify_status; gnutls_x509_crl_t crl; gnutls_x509_crt_t ca; gnutls_datum_t tmp; /* The overloading of time() seems to work in linux (ELF?) * systems only. Disable it on windows. */ #ifdef _WIN32 exit(77); #endif ret = global_init(); if (ret != 0) { fail("%d: %s\n", ret, gnutls_strerror(ret)); exit(1); } gnutls_global_set_time_function(mytime); gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(4711); for (i = 0; crl_list[i].name; i++) { if (debug) printf("Chain '%s' (%d)...\n", crl_list[i].name, (int) i); if (debug > 2) printf("\tAdding CRL..."); ret = gnutls_x509_crl_init(&crl); if (ret < 0) { fprintf(stderr, "gnutls_x509_crl_init[%d]: %s\n", (int) i, gnutls_strerror(ret)); exit(1); } tmp.data = (unsigned char *) *crl_list[i].crl; tmp.size = strlen(*crl_list[i].crl); ret = gnutls_x509_crl_import(crl, &tmp, GNUTLS_X509_FMT_PEM); if (debug > 2) printf("done\n"); if (ret < 0) { fprintf(stderr, "gnutls_x509_crl_import[%s]: %s\n", crl_list[i].name, gnutls_strerror(ret)); exit(1); } gnutls_x509_crl_print(crl, GNUTLS_CRT_PRINT_ONELINE, &tmp); if (debug) printf("\tCRL: %.*s\n", tmp.size, tmp.data); gnutls_free(tmp.data); if (debug > 2) printf("\tAdding CA certificate..."); ret = gnutls_x509_crt_init(&ca); if (ret < 0) { fprintf(stderr, "gnutls_x509_crt_init: %s\n", gnutls_strerror(ret)); exit(1); } tmp.data = (unsigned char *) *crl_list[i].ca; tmp.size = strlen(*crl_list[i].ca); ret = gnutls_x509_crt_import(ca, &tmp, GNUTLS_X509_FMT_PEM); if (ret < 0) { fprintf(stderr, "gnutls_x509_crt_import: %s\n", gnutls_strerror(ret)); exit(1); } if (debug > 2) printf("done\n"); gnutls_x509_crt_print(ca, GNUTLS_CRT_PRINT_ONELINE, &tmp); if (debug) printf("\tCA Certificate: %.*s\n", tmp.size, tmp.data); gnutls_free(tmp.data); if (debug) printf("\tVerifying..."); ret = gnutls_x509_crl_verify(crl, &ca, 1, crl_list[i].verify_flags, &verify_status); if (ret < 0) { fprintf(stderr, "gnutls_x509_crt_list_verify[%d]: %s\n", (int) i, gnutls_strerror(ret)); exit(1); } if (verify_status != crl_list[i].expected_verify_result) { gnutls_datum_t out1, out2; gnutls_certificate_verification_status_print (verify_status, GNUTLS_CRT_X509, &out1, 0); gnutls_certificate_verification_status_print(crl_list [i]. expected_verify_result, GNUTLS_CRT_X509, &out2, 0); fail("chain[%s]:\nverify_status: %d: %s\nexpected: %d: %s\n", crl_list[i].name, verify_status, out1.data, crl_list[i].expected_verify_result, out2.data); gnutls_free(out1.data); gnutls_free(out2.data); if (!debug) exit(1); } else if (debug) printf("done\n"); gnutls_x509_trust_list_init(&tl, 0); ret = gnutls_x509_trust_list_add_cas(tl, &ca, 1, 0); if (ret != 1) { fail("gnutls_x509_trust_list_add_trust_mem\n"); exit(1); } /* make sure that the two functions don't diverge */ ret = gnutls_x509_trust_list_add_crls(tl, &crl, 1, GNUTLS_TL_VERIFY_CRL, crl_list[i].verify_flags); if (crl_list[i].expected_verify_result == 0 && ret < 0) { fprintf(stderr, "gnutls_x509_trust_list_add_crls[%d]: %s\n", (int) i, gnutls_strerror(ret)); exit(1); } if (crl_list[i].expected_verify_result != 0 && ret > 0) { fprintf(stderr, "gnutls_x509_trust_list_add_crls[%d]: succeeded when it shouldn't\n", (int) i); exit(1); } if (debug) printf("\tCleanup..."); gnutls_x509_trust_list_deinit(tl, 0); gnutls_x509_crt_deinit(ca); gnutls_x509_crl_deinit(crl); if (debug) printf("done\n\n\n"); } gnutls_global_deinit(); if (debug) printf("Exit status...%d\n", exit_val); exit(exit_val); }
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; }
int main(void) { int ret; char *line = NULL; size_t line_len; xssl_cred_t cred; xssl_t sb; unsigned int status; int fd; gnutls_global_init(); fd = tcp_connect(); ret = xssl_cred_init(&cred, GNUTLS_VMETHOD_SYSTEM_CAS, NULL, 0); if (ret < 0) exit(1); /* Initialize TLS session */ ret = xssl_client_init(&sb, "www.example.com", NULL, (gnutls_transport_ptr_t) fd, NULL, cred, &status, 0); if (ret < 0) { if (ret == GNUTLS_E_AUTH_ERROR) { gnutls_datum_t txt; gnutls_certificate_verification_status_print (status, GNUTLS_CRT_X509, &txt, 0); fprintf(stderr, "Verification error (%x): %s\n", status, txt.data); gnutls_free(txt.data); } exit(1); } #define REQ "GET / HTTP/1.0\r\n" ret = xssl_write(sb, REQ, sizeof(REQ) - 1); if (ret < 0) exit(1); do { ret = xssl_getline(sb, &line, &line_len); if (ret < 0) exit(1); fprintf(stderr, "received: %s\n", line); } while (ret >= 0); gnutls_free(line); xssl_deinit(sb); tcp_close(fd); xssl_cred_deinit(cred); gnutls_global_deinit(); return 0; }
/* 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; }