void session::get_our_certificate (gnutls_datum_t & cert) const { const gnutls_datum_t *d; d = gnutls_certificate_get_ours (s); if (d == NULL) throw (exception (GNUTLS_E_INVALID_REQUEST)); cert = *d; }
static void tls_get_client_cert (CONNECTION* conn) { tlssockdata *data = conn->sockdata; const gnutls_datum_t* crtdata; gnutls_x509_crt_t clientcrt; char* dn; char* cn; char* cnend; size_t dnlen; /* get our cert CN if we have one */ if (!(crtdata = gnutls_certificate_get_ours (data->state))) return; if (gnutls_x509_crt_init (&clientcrt) < 0) { dprint (1, (debugfile, "Failed to init gnutls crt\n")); return; } if (gnutls_x509_crt_import (clientcrt, crtdata, GNUTLS_X509_FMT_DER) < 0) { dprint (1, (debugfile, "Failed to import gnutls client crt\n")); goto err_crt; } /* get length of DN */ dnlen = 0; gnutls_x509_crt_get_dn (clientcrt, NULL, &dnlen); if (!(dn = calloc (1, dnlen))) { dprint (1, (debugfile, "could not allocate DN\n")); goto err_crt; } gnutls_x509_crt_get_dn (clientcrt, dn, &dnlen); dprint (2, (debugfile, "client certificate DN: %s\n", dn)); /* extract CN to use as external user name */ if (!(cn = strstr (dn, "CN="))) { dprint (1, (debugfile, "no CN found in DN\n")); goto err_dn; } cn += 3; if ((cnend = strstr (dn, ",EMAIL="))) *cnend = '\0'; /* if we are using a client cert, SASL may expect an external auth name */ mutt_account_getuser (&conn->account); err_dn: FREE (&dn); err_crt: gnutls_x509_crt_deinit (clientcrt); }
/** * tls_get_client_cert - Get the client certificate for a TLS connection * @param conn Connection to a server */ static void tls_get_client_cert(struct Connection *conn) { struct TlsSockData *data = conn->sockdata; gnutls_x509_crt_t clientcrt; char *dn = NULL; char *cn = NULL; char *cnend = NULL; size_t dnlen; /* get our cert CN if we have one */ const gnutls_datum_t *crtdata = gnutls_certificate_get_ours(data->state); if (!crtdata) return; if (gnutls_x509_crt_init(&clientcrt) < 0) { mutt_debug(LL_DEBUG1, "Failed to init gnutls crt\n"); return; } if (gnutls_x509_crt_import(clientcrt, crtdata, GNUTLS_X509_FMT_DER) < 0) { mutt_debug(LL_DEBUG1, "Failed to import gnutls client crt\n"); goto err_crt; } /* get length of DN */ dnlen = 0; gnutls_x509_crt_get_dn(clientcrt, NULL, &dnlen); dn = mutt_mem_calloc(1, dnlen); gnutls_x509_crt_get_dn(clientcrt, dn, &dnlen); mutt_debug(LL_DEBUG2, "client certificate DN: %s\n", dn); /* extract CN to use as external user name */ cn = strstr(dn, "CN="); if (!cn) { mutt_debug(LL_DEBUG1, "no CN found in DN\n"); goto err_dn; } cnend = strstr(dn, ",EMAIL="); if (cnend) *cnend = '\0'; /* if we are using a client cert, SASL may expect an external auth name */ if (mutt_account_getuser(&conn->account) < 0) mutt_debug(LL_DEBUG1, "Couldn't get user info\n"); err_dn: FREE(&dn); err_crt: gnutls_x509_crt_deinit(clientcrt); }
static int tlsg_session_my_dn( tls_session *session, struct berval *der_dn ) { tlsg_session *s = (tlsg_session *)session; const gnutls_datum_t *x; struct berval bv; x = gnutls_certificate_get_ours( s->session ); if (!x) return LDAP_INVALID_CREDENTIALS; bv.bv_val = (char *) x->data; bv.bv_len = x->size; tlsg_x509_cert_dn( &bv, der_dn, 1 ); return 0; }
int tls_certificate_get_permission(gnutls_session session, requiem_connection_permission_t *permission) { int ret, tmp; char buf[1024]; gnutls_x509_crt cert; size_t size = sizeof(buf); const gnutls_datum *data; data = gnutls_certificate_get_ours(session); if ( ! data ) return requiem_error_verbose(REQUIEM_ERROR_TLS, "could not get own certificate"); ret = gnutls_x509_crt_init(&cert); if ( ret < 0 ) return requiem_error_verbose(REQUIEM_ERROR_TLS, "error initializing certificate: %s", gnutls_strerror(ret)); ret = gnutls_x509_crt_import(cert, data, GNUTLS_X509_FMT_DER); if ( ret < 0 ) { gnutls_x509_crt_deinit(cert); return requiem_error_verbose(REQUIEM_ERROR_TLS, "error importing certificate: %s", gnutls_strerror(ret)); } ret = gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, buf, &size); if ( ret < 0 ) { gnutls_x509_crt_deinit(cert); return requiem_error_verbose(REQUIEM_ERROR_TLS, "could not get certificate CN field: %s", gnutls_strerror(ret)); } ret = sscanf(buf, "%d", &tmp); if ( ret != 1 ) { gnutls_x509_crt_deinit(cert); return requiem_error_verbose(REQUIEM_ERROR_TLS, "certificate analyzerid value '%s' is invalid", buf); } *permission = (requiem_connection_permission_t) tmp; gnutls_x509_crt_deinit(cert); return 0; }
static int ctx_ocsp_response(gnutls_session_t session, void* ptr, gnutls_datum_t* ocsp_resp) { liGnuTLSOCSP* ocsp = ptr; guint i; int r; gnutls_datum_t serial = { NULL, 0 }; gnutls_datum_t issuer_name = { NULL, 0 }; char* issuer_name_hash = NULL; if (0 == ocsp->responses->len) return GNUTLS_E_NO_CERTIFICATE_STATUS; serial.size = ocsp->max_serial_length; serial.data = gnutls_malloc(serial.size); issuer_name_hash = gnutls_malloc(ocsp->max_hash_length); { gnutls_datum_t const* crt_datum; gnutls_x509_crt_t crt = NULL; size_t serial_size = ocsp->max_serial_length; crt_datum = gnutls_certificate_get_ours(session); /* memory is NOT owned */ if (GNUTLS_E_SUCCESS > (r = gnutls_x509_crt_init(&crt))) goto cleanup; if (GNUTLS_E_SUCCESS > (r = gnutls_x509_crt_import(crt, crt_datum, GNUTLS_X509_FMT_DER))) { gnutls_x509_crt_deinit(crt); goto cleanup; } ; if (GNUTLS_E_SUCCESS > (r = gnutls_x509_crt_get_serial(crt, serial.data, &serial_size))) { gnutls_x509_crt_deinit(crt); goto cleanup; } serial.size = serial_size; if (GNUTLS_E_SUCCESS > (r = gnutls_x509_crt_get_raw_issuer_dn(crt, &issuer_name))) { gnutls_x509_crt_deinit(crt); goto cleanup; } gnutls_x509_crt_deinit(crt); } for (i = 0; i < ocsp->responses->len; ++i) { ocsp_response* response = &g_array_index(ocsp->responses, ocsp_response, i); guint j; for (j = 0; j < response->certificates->len; ++j) { ocsp_response_cert_entry* entry = &g_array_index(response->certificates, ocsp_response_cert_entry, i); if (serial.size != entry->serial.size || 0 != memcmp(serial.data, entry->serial.data, serial.size)) continue; if (GNUTLS_E_SUCCESS > (r = gnutls_hash_fast(entry->digest, issuer_name.data, issuer_name.size, issuer_name_hash))) goto cleanup; if (0 != memcmp(issuer_name_hash, entry->issuer_name_hash.data, entry->issuer_name_hash.size)) continue; ocsp_resp->size = response->resp_data.size; ocsp_resp->data = gnutls_malloc(ocsp_resp->size); memcpy(ocsp_resp->data, response->resp_data.data, ocsp_resp->size); r = GNUTLS_E_SUCCESS; goto cleanup; } } r = GNUTLS_E_NO_CERTIFICATE_STATUS; cleanup: gnutls_free(issuer_name_hash); gnutls_free(issuer_name.data); gnutls_free(serial.data); return r; }
void doit(void) { int exit_code = EXIT_SUCCESS; int ret; /* Server stuff. */ gnutls_certificate_credentials_t serverx509cred; 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; gnutls_x509_crt_t *crts; unsigned int crts_size; unsigned i; gnutls_x509_privkey_t pkey; /* General init. */ global_init(); gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(2); ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &server_cert, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_privkey_init(&pkey); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_privkey_import(pkey, &server_key, GNUTLS_X509_FMT_PEM); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } /* Init server */ gnutls_certificate_allocate_credentials(&serverx509cred); gnutls_certificate_set_x509_key(serverx509cred, crts, crts_size, pkey); gnutls_x509_privkey_deinit(pkey); for (i=0;i<crts_size;i++) gnutls_x509_crt_deinit(crts[i]); gnutls_free(crts); gnutls_init(&server, GNUTLS_SERVER); gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, serverx509cred); gnutls_priority_set_direct(server, "NORMAL:-CIPHER-ALL:+AES-128-GCM", NULL); gnutls_transport_set_push_function(server, server_push); gnutls_transport_set_pull_function(server, server_pull); gnutls_transport_set_ptr(server, server); gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUEST); /* Init client */ /* 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); gnutls_certificate_set_retrieve_function2(clientx509cred, cert_callback); ret = gnutls_init(&client, GNUTLS_CLIENT); if (ret < 0) exit(1); ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred); if (ret < 0) exit(1); gnutls_priority_set_direct(client, "NORMAL", 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); if (gnutls_certificate_get_ours(client) == NULL) { fail("client certificate was not sent!\n"); exit(1); } /* check gnutls_certificate_get_ours() - server side */ { const gnutls_datum_t *mcert; gnutls_datum_t scert; gnutls_x509_crt_t crt; mcert = gnutls_certificate_get_ours(server); if (mcert == NULL) { fail("gnutls_certificate_get_ours(): failed\n"); exit(1); } gnutls_x509_crt_init(&crt); ret = gnutls_x509_crt_import(crt, &server_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) { fail("gnutls_x509_crt_import: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &scert); if (ret < 0) { fail("gnutls_x509_crt_export2: %s\n", gnutls_strerror(ret)); exit(1); } gnutls_x509_crt_deinit(crt); if (scert.size != mcert->size || memcmp(scert.data, mcert->data, mcert->size) != 0) { fail("gnutls_certificate_get_ours output doesn't match cert\n"); exit(1); } gnutls_free(scert.data); } /* check gnutls_certificate_get_ours() - client side */ { const gnutls_datum_t *mcert; gnutls_datum_t ccert; gnutls_x509_crt_t crt; mcert = gnutls_certificate_get_ours(client); if (mcert == NULL) { fail("gnutls_certificate_get_ours(): failed\n"); exit(1); } gnutls_x509_crt_init(&crt); ret = gnutls_x509_crt_import(crt, &cli_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) { fail("gnutls_x509_crt_import: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &ccert); if (ret < 0) { fail("gnutls_x509_crt_export2: %s\n", gnutls_strerror(ret)); exit(1); } gnutls_x509_crt_deinit(crt); if (ccert.size != mcert->size || memcmp(ccert.data, mcert->data, mcert->size) != 0) { fail("gnutls_certificate_get_ours output doesn't match cert\n"); exit(1); } gnutls_free(ccert.data); } /* check the number of certificates received */ { unsigned cert_list_size = 0; gnutls_typed_vdata_st data[2]; unsigned status; memset(data, 0, sizeof(data)); /* check with wrong hostname */ data[0].type = GNUTLS_DT_DNS_HOSTNAME; data[0].data = (void*)"localhost1"; data[1].type = GNUTLS_DT_KEY_PURPOSE_OID; data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER; gnutls_certificate_get_peers(client, &cert_list_size); if (cert_list_size < 2) { fprintf(stderr, "received a certificate list of %d!\n", cert_list_size); exit(1); } ret = gnutls_certificate_verify_peers(client, data, 2, &status); if (ret < 0) { fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret)); exit(1); } if (status == 0) { fprintf(stderr, "should not have accepted!\n"); exit(1); } /* check with wrong purpose */ data[0].type = GNUTLS_DT_DNS_HOSTNAME; data[0].data = (void*)"localhost"; data[1].type = GNUTLS_DT_KEY_PURPOSE_OID; data[1].data = (void*)GNUTLS_KP_TLS_WWW_CLIENT; gnutls_certificate_get_peers(client, &cert_list_size); if (cert_list_size < 2) { fprintf(stderr, "received a certificate list of %d!\n", cert_list_size); exit(1); } ret = gnutls_certificate_verify_peers(client, data, 2, &status); if (ret < 0) { fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret)); exit(1); } if (status == 0) { fprintf(stderr, "should not have accepted!\n"); exit(1); } /* check with correct purpose */ data[0].type = GNUTLS_DT_DNS_HOSTNAME; data[0].data = (void*)"localhost"; 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) { fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret)); exit(1); } if (status != 0) { fprintf(stderr, "could not verify certificate: %.4x\n", status); exit(1); } } if (gnutls_certificate_client_get_request_status(client) == 0) { fail("gnutls_certificate_client_get_request_status - 2 failed\n"); exit(1); } gnutls_bye(client, GNUTLS_SHUT_RDWR); gnutls_bye(server, GNUTLS_SHUT_RDWR); gnutls_deinit(client); gnutls_deinit(server); gnutls_certificate_free_credentials(serverx509cred); gnutls_certificate_free_credentials(clientx509cred); gnutls_global_deinit(); if (debug > 0) { if (exit_code == 0) puts("Self-test successful"); else puts("Self-test failed"); } }
static void start(struct test_st *test) { int ret; /* Server stuff. */ gnutls_priority_t cache; gnutls_certificate_credentials_t serverx509cred; gnutls_session_t server; int sret = GNUTLS_E_AGAIN; /* Client stuff. */ gnutls_certificate_credentials_t clientx509cred; gnutls_session_t client; const char *ep; int cret = GNUTLS_E_AGAIN; if (test == NULL) success("running gnutls_set_default_priority test\n"); else success("running %s\n", test->name); if (test && test->def_prio) _gnutls_default_priority_string = test->def_prio; else _gnutls_default_priority_string = "NORMAL"; /* General init. */ global_init(); gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(6); assert(gnutls_certificate_allocate_credentials(&serverx509cred)>=0); assert(gnutls_certificate_set_x509_key_mem(serverx509cred, &server_cert, &server_key, GNUTLS_X509_FMT_PEM)>=0); assert(gnutls_init(&server, GNUTLS_SERVER) >= 0); gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, serverx509cred); if (test == NULL) { ret = gnutls_priority_init(&cache, NULL, NULL); if (ret < 0) fail("error: %s\n", gnutls_strerror(ret)); } else { ret = gnutls_priority_init2(&cache, test->add_prio, &ep, GNUTLS_PRIORITY_INIT_DEF_APPEND); if (ret < 0) { if (test->exp_err == ret) { if (strchr(_gnutls_default_priority_string, '@') != 0) { if (ep != test->add_prio) { fail("error expected error on start of string[%d]: %s\n", test->err_pos, test->add_prio); } } else { if (ep-test->add_prio != test->err_pos) { fprintf(stderr, "diff: %d\n", (int)(ep-test->add_prio)); fail("error expected error on different position[%d]: %s\n", test->err_pos, test->add_prio); } } goto cleanup; } fail("error: %s\n", gnutls_strerror(ret)); } } gnutls_priority_set(server, cache); 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); ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred); if (ret < 0) exit(1); ret = gnutls_set_default_priority(client); if (ret < 0) exit(1); 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 gnutls_certificate_get_ours() - client side */ { const gnutls_datum_t *mcert; mcert = gnutls_certificate_get_ours(client); if (mcert != NULL) { fail("gnutls_certificate_get_ours(): failed\n"); exit(1); } } if (test && test->exp_vers != 0) { if (test->exp_vers != gnutls_protocol_get_version(server)) { fail("expected version %s, got %s\n", gnutls_protocol_get_name(test->exp_vers), gnutls_protocol_get_name(gnutls_protocol_get_version(server))); } } /* check the number of certificates received */ { unsigned cert_list_size = 0; gnutls_typed_vdata_st data[2]; unsigned status; memset(data, 0, sizeof(data)); data[0].type = GNUTLS_DT_DNS_HOSTNAME; data[0].data = (void*)"localhost1"; data[1].type = GNUTLS_DT_KEY_PURPOSE_OID; data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER; gnutls_certificate_get_peers(client, &cert_list_size); if (cert_list_size < 2) { fprintf(stderr, "received a certificate list of %d!\n", cert_list_size); exit(1); } ret = gnutls_certificate_verify_peers(client, data, 2, &status); if (ret < 0) { fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret)); exit(1); } if (status == 0) { fprintf(stderr, "should not have accepted!\n"); exit(1); } data[0].type = GNUTLS_DT_DNS_HOSTNAME; data[0].data = (void*)"localhost"; ret = gnutls_certificate_verify_peers(client, data, 2, &status); if (ret < 0) { fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret)); exit(1); } if (status != 0) { fprintf(stderr, "could not verify certificate: %.4x\n", status); exit(1); } } if (test && test->exp_etm) { ret = gnutls_session_ext_master_secret_status(client); if (ret != 1) { fprintf(stderr, "Extended master secret wasn't negotiated by default (client ret: %d)\n", ret); exit(1); } ret = gnutls_session_ext_master_secret_status(server); if (ret != 1) { fprintf(stderr, "Extended master secret wasn't negotiated by default (server ret: %d)\n", ret); exit(1); } } gnutls_bye(client, GNUTLS_SHUT_RDWR); gnutls_bye(server, GNUTLS_SHUT_RDWR); gnutls_deinit(client); gnutls_certificate_free_credentials(clientx509cred); cleanup: gnutls_priority_deinit(cache); gnutls_deinit(server); gnutls_certificate_free_credentials(serverx509cred); gnutls_global_deinit(); reset_buffers(); }