static int 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_pcert_st ** pcert, unsigned int *pcert_length, gnutls_privkey_t * pkey) { int result; gnutls_x509_dn_t dn; if (nreqs != 1) { fail("client: invoked to provide client cert, but %d CAs are requested by server.\n", nreqs); return -1; } if (debug) success("client: invoked to provide client cert.\n"); result = gnutls_x509_dn_init(&dn); if (result < 0) { fail("client: could not initialize DN.\n"); return -1; } result = gnutls_x509_dn_import(dn, req_ca_rdn); if (result == 0) { gnutls_x509_ava_st val; if (debug) success("client: imported DN.\n"); if (gnutls_x509_dn_get_rdn_ava(dn, 0, 0, &val) == 0) { if (debug) success("client: got RDN 0.\n"); if (val.value.size == strlen(EXPECT_RDN0) && strncmp((char *) val.value.data, EXPECT_RDN0, val.value.size) == 0) { if (debug) success ("client: RND 0 correct.\n"); } else { fail("client: RND 0 bad: %.*s\n", val.value.size, val.value.data); return -1; } } else { fail("client: could not retrieve RDN 0.\n"); return -1; } gnutls_x509_dn_deinit(dn); } else { fail("client: failed to parse RDN: %s\n", gnutls_strerror(result)); } return 0; }
static void print_dn(gnutls_buffer_st * str, const char *prefix, const gnutls_datum_t * raw) { gnutls_x509_dn_t dn = NULL; gnutls_datum_t output = { NULL, 0 }; int ret; ret = gnutls_x509_dn_init(&dn); if (ret < 0) { addf(str, "%s: [error]\n", prefix); return; } ret = gnutls_x509_dn_import(dn, raw); if (ret < 0) { addf(str, "%s: [error]\n", prefix); goto cleanup; } ret = gnutls_x509_dn_get_str2(dn, &output, 0); if (ret < 0) { addf(str, "%s: [error]\n", prefix); goto cleanup; } addf(str, "%s: %s\n", prefix, output.data); cleanup: gnutls_x509_dn_deinit(dn); gnutls_free(output.data); }
static int cert_callback (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) { int result; gnutls_x509_dn_t dn; if (nreqs != 1) { fail ("client: invoked to provide client cert, %d CA .\n", nreqs); return -1; } success ("client: invoked to provide client cert.\n"); result = gnutls_x509_dn_init (&dn); if (result < 0) { fail ("client: could not initialize DN.\n"); return -1; } result = gnutls_x509_dn_import (dn, req_ca_rdn); if (result == 0) { gnutls_x509_ava_st val; success ("client: imported DN.\n"); if (gnutls_x509_dn_get_rdn_ava (dn, 0, 0, &val) == 0) { success ("client: got RDN 0.\n"); if (val.value.size == strlen (EXPECT_RDN0) && strncmp (val.value.data, EXPECT_RDN0, val.value.size) == 0) { success ("client: RND 0 correct.\n"); } else { fail ("client: RND 0 bad: %.*s\n", val.value.size, val.value.data); return -1; } } else { fail ("client: could not retrieve RDN 0.\n"); return -1; } gnutls_x509_dn_deinit (dn); } else { fail ("client: failed to parse RDN: %s\n", gnutls_strerror (result)); } 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; }