void doit (void) { gnutls_certificate_credentials_t x509_cred; int ret; unsigned int i; gnutls_x509_crt_t issuer; gnutls_x509_crt_t list[LIST_SIZE]; char dn[128]; size_t dn_size; unsigned int list_size; /* this must be called once in the program */ gnutls_global_init (); gnutls_global_set_log_function (tls_log_func); if (debug) gnutls_global_set_log_level (6); gnutls_certificate_allocate_credentials (&x509_cred); gnutls_certificate_set_x509_trust_mem (x509_cred, &ca, GNUTLS_X509_FMT_PEM); gnutls_certificate_set_x509_key_mem (x509_cred, &server_cert, &server_key, GNUTLS_X509_FMT_PEM); /* test for gnutls_certificate_get_issuer() */ list_size = LIST_SIZE; ret = gnutls_x509_crt_list_import(list, &list_size, &cert, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED); if (ret < 0) fail("gnutls_x509_crt_list_import"); ret = gnutls_certificate_get_issuer(x509_cred, list[0], &issuer, 0); if (ret < 0) fail("gnutls_certificate_get_isser"); dn_size = sizeof(dn); ret = gnutls_x509_crt_get_dn(issuer, dn, &dn_size); if (ret < 0) fail("gnutls_certificate_get_isser"); if (debug) fprintf(stderr, "Issuer's DN: %s\n", dn); for (i=0;i<list_size;i++) gnutls_x509_crt_deinit(list[i]); gnutls_certificate_free_credentials(x509_cred); gnutls_global_deinit(); if (debug) success("success"); }
void doit(void) { gnutls_certificate_credentials_t x509_cred; int ret; unsigned int i; gnutls_x509_crt_t issuer; gnutls_x509_crt_t list[LIST_SIZE]; char dn[128]; size_t dn_size; unsigned int list_size; size_t buf_size; gnutls_x509_privkey_t get_key; gnutls_x509_crt_t *get_crts; unsigned n_get_crts; gnutls_datum_t get_datum, chain_datum[2] = {server_ca3_cert, subca3_cert}; gnutls_x509_trust_list_t trust_list; gnutls_x509_trust_list_iter_t trust_iter; gnutls_x509_crt_t get_ca_crt; unsigned n_get_ca_crts; /* this must be called once in the program */ global_init(); gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(6); gnutls_certificate_allocate_credentials(&x509_cred); gnutls_certificate_set_x509_trust_mem(x509_cred, &ca3_cert, GNUTLS_X509_FMT_PEM); gnutls_certificate_set_x509_key_mem(x509_cred, &server_ca3_cert_chain, &server_ca3_key, GNUTLS_X509_FMT_PEM); /* test for gnutls_certificate_get_issuer() */ /* check whether gnutls_x509_crt_list_import will fail if given a single * certificate */ list_size = LIST_SIZE; ret = gnutls_x509_crt_list_import(list, &list_size, &ca3_cert, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED); if (ret < 0) fail("gnutls_x509_crt_list_import (failed with a single cert)"); gnutls_x509_crt_deinit(list[0]); list_size = LIST_SIZE; ret = gnutls_x509_crt_list_import(list, &list_size, &cli_ca3_cert_chain, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED); if (ret < 0) fail("gnutls_x509_crt_list_import"); ret = gnutls_certificate_get_issuer(x509_cred, list[list_size-1], &issuer, 0); if (ret < 0) fail("gnutls_certificate_get_isser"); ret = gnutls_certificate_get_issuer(x509_cred, list[list_size-1], &issuer, GNUTLS_TL_GET_COPY); if (ret < 0) fail("gnutls_certificate_get_isser"); dn_size = sizeof(dn); ret = gnutls_x509_crt_get_dn(issuer, dn, &dn_size); if (ret < 0) fail("gnutls_certificate_get_dn"); gnutls_x509_crt_deinit(issuer); if (dn_size != strlen(dn)) { fail("gnutls_x509_crt_get_dn: lengths don't match\n"); exit(1); } if (debug) fprintf(stderr, "Issuer's DN: %s\n", dn); /* test the getter functions of gnutls_certificate_credentials_t */ ret = gnutls_certificate_get_x509_key(x509_cred, 0, &get_key); if (ret < 0) fail("gnutls_certificate_get_x509_key"); ret = gnutls_x509_privkey_export2(get_key, GNUTLS_X509_FMT_PEM, &get_datum); if (ret < 0) fail("gnutls_x509_privkey_export2"); if (get_datum.size != server_ca3_key.size || memcmp(get_datum.data, server_ca3_key.data, get_datum.size) != 0) { fail( "exported key %u vs. %u\n\n%s\n\nvs.\n\n%s", get_datum.size, server_ca3_key.size, get_datum.data, server_ca3_key.data); } if (strlen((char*)get_datum.data) != get_datum.size) { fail("exported key %u vs. %u\n\n%s\n", get_datum.size, (unsigned)strlen((char*)get_datum.data), get_datum.data); } gnutls_free(get_datum.data); buf_size = sizeof(buf); ret = gnutls_x509_privkey_export(get_key, GNUTLS_X509_FMT_PEM, buf, &buf_size); if (ret < 0) fail("gnutls_x509_privkey_export"); if (buf_size != get_datum.size || buf_size != strlen(buf) || memcmp(buf, server_ca3_key.data, buf_size) != 0) { fail( "exported key %u vs. %u\n\n%s\n\nvs.\n\n%s", (int)buf_size, server_ca3_key.size, buf, server_ca3_key.data); } ret = gnutls_certificate_get_x509_crt(x509_cred, 0, &get_crts, &n_get_crts); if (ret < 0) fail("gnutls_certificate_get_x509_crt"); if (n_get_crts != 2) fail("gnutls_certificate_get_x509_crt: n_crts != 2"); for (i = 0; i < n_get_crts; i++) { ret = gnutls_x509_crt_export2(get_crts[i], GNUTLS_X509_FMT_PEM, &get_datum); if (ret < 0) fail("gnutls_x509_crt_export2"); if (get_datum.size != chain_datum[i].size || memcmp(get_datum.data, chain_datum[i].data, get_datum.size) != 0) { fail( "exported certificate %u vs. %u\n\n%s\n\nvs.\n\n%s", get_datum.size, chain_datum[i].size, get_datum.data, chain_datum[i].data); } gnutls_free(get_datum.data); } gnutls_certificate_get_trust_list(x509_cred, &trust_list); n_get_ca_crts = 0; trust_iter = NULL; while (gnutls_x509_trust_list_iter_get_ca(trust_list, &trust_iter, &get_ca_crt) != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { ret = gnutls_x509_crt_export2(get_ca_crt, GNUTLS_X509_FMT_PEM, &get_datum); if (ret < 0) fail("gnutls_x509_crt_export2"); if (get_datum.size != ca3_cert.size || memcmp(get_datum.data, ca3_cert.data, get_datum.size) != 0) { fail( "exported CA certificate %u vs. %u\n\n%s\n\nvs.\n\n%s", get_datum.size, ca3_cert.size, get_datum.data, ca3_cert.data); } gnutls_x509_crt_deinit(get_ca_crt); gnutls_free(get_datum.data); ++n_get_ca_crts; } if (n_get_ca_crts != 1) fail("gnutls_x509_trust_list_iter_get_ca: n_cas != 1"); if (trust_iter != NULL) fail("gnutls_x509_trust_list_iter_get_ca: iterator not NULL after iteration"); gnutls_x509_privkey_deinit(get_key); for (i = 0; i < n_get_crts; i++) gnutls_x509_crt_deinit(get_crts[i]); gnutls_free(get_crts); for (i = 0; i < list_size; i++) gnutls_x509_crt_deinit(list[i]); gnutls_certificate_free_credentials(x509_cred); gnutls_global_deinit(); if (debug) success("success"); }
/* OCSP check for the peer's certificate. Should be called * only after the certificate list verication is complete. * Returns: * 0: certificate is revoked * 1: certificate is ok * -1: dunno */ static int cert_verify_ocsp (gnutls_session_t session) { gnutls_x509_crt_t crt, issuer; const gnutls_datum_t *cert_list; unsigned int cert_list_size = 0; int deinit_issuer = 0; gnutls_datum_t resp; int ret; cert_list = gnutls_certificate_get_peers (session, &cert_list_size); if (cert_list_size == 0) { fprintf (stderr, "No certificates found!\n"); return -1; } gnutls_x509_crt_init (&crt); ret = gnutls_x509_crt_import (crt, &cert_list[0], GNUTLS_X509_FMT_DER); if (ret < 0) { fprintf (stderr, "Decoding error: %s\n", gnutls_strerror (ret)); return -1; } ret = gnutls_certificate_get_issuer(xcred, crt, &issuer, 0); if (ret < 0 && cert_list_size > 1) { gnutls_x509_crt_init(&issuer); ret = gnutls_x509_crt_import(issuer, &cert_list[1], GNUTLS_X509_FMT_DER); if (ret < 0) { fprintf (stderr, "Decoding error: %s\n", gnutls_strerror (ret)); return -1; } deinit_issuer = 1; } else if (ret < 0) { fprintf(stderr, "Cannot find issuer\n"); ret = -1; goto cleanup; } ret = send_ocsp_request(NULL, crt, issuer, &resp, 1); if (ret < 0) { fprintf(stderr, "Cannot contact OCSP server\n"); ret = -1; goto cleanup; } /* verify and check the response for revoked cert */ ret = check_ocsp_response(issuer, &resp); cleanup: if (deinit_issuer) gnutls_x509_crt_deinit (issuer); gnutls_x509_crt_deinit (crt); return ret; }
/* * initialize a new TLS context */ static int tlsg_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server ) { tlsg_ctx *ctx = lo->ldo_tls_ctx; int rc; if ( lo->ldo_tls_ciphersuite && tlsg_parse_ciphers( ctx, lt->lt_ciphersuite )) { Debug( LDAP_DEBUG_ANY, "TLS: could not set cipher list %s.\n", lo->ldo_tls_ciphersuite, 0, 0 ); return -1; } if (lo->ldo_tls_cacertdir != NULL) { Debug( LDAP_DEBUG_ANY, "TLS: warning: cacertdir not implemented for gnutls\n", NULL, NULL, NULL ); } if (lo->ldo_tls_cacertfile != NULL) { rc = gnutls_certificate_set_x509_trust_file( ctx->cred, lt->lt_cacertfile, GNUTLS_X509_FMT_PEM ); if ( rc < 0 ) return -1; } if ( lo->ldo_tls_certfile && lo->ldo_tls_keyfile ) { gnutls_x509_privkey_t key; gnutls_datum_t buf; gnutls_x509_crt_t certs[VERIFY_DEPTH]; unsigned int max = VERIFY_DEPTH; rc = gnutls_x509_privkey_init( &key ); if ( rc ) return -1; /* OpenSSL builds the cert chain for us, but GnuTLS * expects it to be present in the certfile. If it's * not, we have to build it ourselves. So we have to * do some special checks here... */ rc = tlsg_getfile( lt->lt_keyfile, &buf ); if ( rc ) return -1; rc = gnutls_x509_privkey_import( key, &buf, GNUTLS_X509_FMT_PEM ); LDAP_FREE( buf.data ); if ( rc < 0 ) return rc; rc = tlsg_getfile( lt->lt_certfile, &buf ); if ( rc ) return -1; rc = gnutls_x509_crt_list_import( certs, &max, &buf, GNUTLS_X509_FMT_PEM, 0 ); LDAP_FREE( buf.data ); if ( rc < 0 ) return rc; /* If there's only one cert and it's not self-signed, * then we have to build the cert chain. */ if ( max == 1 && !gnutls_x509_crt_check_issuer( certs[0], certs[0] )) { unsigned int i; for ( i = 1; i<VERIFY_DEPTH; i++ ) { if ( gnutls_certificate_get_issuer( ctx->cred, certs[i-1], &certs[i], 0 )) break; max++; /* If this CA is self-signed, we're done */ if ( gnutls_x509_crt_check_issuer( certs[i], certs[i] )) break; } } rc = gnutls_certificate_set_x509_key( ctx->cred, certs, max, key ); if ( rc ) return -1; } else if ( lo->ldo_tls_certfile || lo->ldo_tls_keyfile ) { Debug( LDAP_DEBUG_ANY, "TLS: only one of certfile and keyfile specified\n", NULL, NULL, NULL ); return -1; } if ( lo->ldo_tls_crlfile ) { rc = gnutls_certificate_set_x509_crl_file( ctx->cred, lt->lt_crlfile, GNUTLS_X509_FMT_PEM ); if ( rc < 0 ) return -1; rc = 0; } /* FIXME: ITS#5992 - this should be configurable, * and V1 CA certs should be phased out ASAP. */ gnutls_certificate_set_verify_flags( ctx->cred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT ); if ( is_server && lo->ldo_tls_dhfile ) { gnutls_datum_t buf; rc = tlsg_getfile( lo->ldo_tls_dhfile, &buf ); if ( rc ) return -1; rc = gnutls_dh_params_init( &ctx->dh_params ); if ( rc == 0 ) rc = gnutls_dh_params_import_pkcs3( ctx->dh_params, &buf, GNUTLS_X509_FMT_PEM ); LDAP_FREE( buf.data ); if ( rc ) return -1; gnutls_certificate_set_dh_params( ctx->cred, ctx->dh_params ); } return 0; }