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;
}
示例#2
0
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);
}
示例#3
0
/**
 * 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);
}
示例#4
0
文件: tls_g.c 项目: 1ack/Impala
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;
}
示例#5
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;
}
示例#6
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");
	}
}
示例#8
0
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();
}