Project

General

Profile

ocsp.patch

hgb, 2010-12-10 15:15

View differences:

lighttpd-1.4.28.new/src/base.h 2010-12-10 14:38:42.000000000 +0100
275 275
	buffer *ssl_pemfile;
276 276
	buffer *ssl_ca_file;
277 277
	buffer *ssl_cipher_list;
278
	buffer *ssl_ocsp_url;
279
	buffer *ssl_ocsp_cert;
278 280
	unsigned short ssl_use_sslv2;
279 281
	unsigned short ssl_verifyclient;
280 282
	unsigned short ssl_verifyclient_enforce;
281 283
	unsigned short ssl_verifyclient_depth;
282 284
	buffer *ssl_verifyclient_username;
283 285
	unsigned short ssl_verifyclient_export_cert;
286
	unsigned short ssl_ocsp_enforce;
284 287

  
285 288
	unsigned short use_ipv6, set_v6only; /* set_v6only is only a temporary option */
286 289
	unsigned short defer_accept;
lighttpd-1.4.28.new/src/configfile.c 2010-12-10 14:43:01.000000000 +0100
78 78
		{ "debug.log-request-header-on-error", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 37 */
79 79
		{ "debug.log-state-handling",    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 38 */
80 80
		{ "ssl.ca-file",                 NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 39 */
81

  
82 81
		{ "server.errorlog-use-syslog",  NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 40 */
83 82
		{ "server.range-requests",       NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 41 */
84 83
		{ "server.stat-cache-engine",    NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 42 */
......
103 102

  
104 103
		{ "server.set-v6only",           NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 61 */
105 104

  
105
		{ "ssl.ocsp.url",                NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 62 */
106
		{ "ssl.ocsp.cert-file",          NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },      /* 63 */
107
		{ "ssl.ocsp.enforce",            NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },      /* 64 */
106 108
		{ "server.host",                 "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
107 109
		{ "server.docroot",              "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
108 110
		{ "server.virtual-root",         "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
......
161 163
		s->server_name   = buffer_init();
162 164
		s->ssl_pemfile   = buffer_init();
163 165
		s->ssl_ca_file   = buffer_init();
166
		s->ssl_ocsp_url  = buffer_init();
167
		s->ssl_ocsp_cert = buffer_init();
164 168
		s->error_handler = buffer_init();
165 169
		s->server_tag    = buffer_init();
166 170
		s->ssl_cipher_list = buffer_init();
......
193 197
		s->ssl_verifyclient_username = buffer_init();
194 198
		s->ssl_verifyclient_depth = 9;
195 199
		s->ssl_verifyclient_export_cert = 0;
200
		s->ssl_ocsp_enforce = 0;
196 201

  
197 202
		cv[2].destination = s->errorfile_prefix;
198 203

  
......
247 252
		cv[59].destination = s->ssl_verifyclient_username;
248 253
		cv[60].destination = &(s->ssl_verifyclient_export_cert);
249 254

  
255
		cv[62].destination = s->ssl_ocsp_url;
256
		cv[63].destination = s->ssl_ocsp_cert;
257
		cv[64].destination = &(s->ssl_ocsp_enforce);
258

  
250 259
		srv->config_storage[i] = s;
251 260

  
252 261
		if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) {
lighttpd-1.4.28.new/src/network.c 2010-12-10 14:49:55.000000000 +0100
25 25
# include <openssl/ssl.h>
26 26
# include <openssl/err.h>
27 27
# include <openssl/rand.h>
28
# include <openssl/ocsp.h>
28 29
#endif
29 30

  
30 31
static handler_t network_server_handle_fdevent(server *srv, void *context, int revents) {
......
474 475
	NETWORK_BACKEND_SOLARIS_SENDFILEV
475 476
} network_backend_t;
476 477

  
478
static char * get_ocsp_url(server *srv) {
479
	size_t i;
480
	for (i = 0; i < srv->config_context->used; i++) {
481
		specific_config *s = srv->config_storage[i];
482

  
483
		if (!buffer_is_empty(s->ssl_ocsp_url))
484
			return s->ssl_ocsp_url->ptr;
485
	}
486

  
487
	return NULL;
488
}
489

  
490
static BIO * get_ocsp_bio(server *srv, SSL_CTX *ctx, char **path) {
491
	char *url;
492
	char *host = NULL;
493
	char *port = NULL;
494
	int ssl;
495
	BIO *bio;
496

  
497
	url = get_ocsp_url(srv);
498
	if (!url)
499
		return NULL;
500

  
501
	if (!OCSP_parse_url(url, &host, &port, path, &ssl))
502
		return NULL;
503

  
504
	if (!(bio = BIO_new_connect(host))) {
505
		free(*path);
506
		goto out;
507
	}
508

  
509
	if (port)
510
		BIO_set_conn_port(bio, port);
511

  
512
	if (ssl) {
513
		BIO * sbio;
514

  
515
		SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
516
		sbio = BIO_new_ssl(ctx, 1);
517
		bio = BIO_push(sbio, bio);
518
	}
519
out:
520
	free(host);
521
	free(port);
522
	return bio;
523
}
524

  
525
static int check_ocsp_response(server *srv, OCSP_RESPONSE *resp, OCSP_CERTID *id) {
526
	OCSP_BASICRESP *bs;
527
	int status;
528
	int reason;
529

  
530
	if (OCSP_response_status(resp) != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
531
		log_error_write(srv, __FILE__, __LINE__, "sd", "OCSP response: ",
532
				OCSP_response_status(resp));
533
		return 0;
534
	}
535

  
536
	if (!(bs = OCSP_response_get1_basic(resp))) {
537
		log_error_write(srv, __FILE__, __LINE__, "ss", "Failed to parse OCSP response: ",
538
				ERR_error_string(ERR_get_error(), NULL));
539
		return 0;
540
	}
541

  
542
	if (!OCSP_resp_find_status(bs, id, &status, &reason, NULL, NULL, NULL)) {
543
		log_error_write(srv, __FILE__, __LINE__, "s",
544
				"Failed to find OCSP status");
545
		OCSP_BASICRESP_free(bs);
546
		return 0;
547
	}
548
	OCSP_BASICRESP_free(bs);
549

  
550
	if (status == V_OCSP_CERTSTATUS_REVOKED) {
551
		log_error_write(srv, __FILE__, __LINE__, "ss",
552
				"Certificate revoked: ",
553
				reason != -1 ?
554
				OCSP_crl_reason_str(reason) :
555
				"unknown reason");
556
		return 0;
557
	}
558

  
559
	return 1;
560
}
561

  
562
static int verify_cb(X509_STORE_CTX *ctx, void *arg) {
563
	server *srv = arg;
564
	OCSP_REQUEST *req = NULL;
565
	OCSP_CERTID *id;
566
	OCSP_RESPONSE *resp = NULL;
567
	char *path;
568
	X509 *issuer;
569
	BIO *bio = NULL;
570
	SSL_CTX *sslctx = SSL_CTX_new(SSLv3_client_method());
571
	int ret = 0;
572

  
573
	if (!sslctx)
574
		return 0;
575

  
576
	if (!X509_verify_cert(ctx))
577
		return 0;
578

  
579
	if (!ctx->get_issuer(&issuer, ctx, ctx->cert))
580
		goto err;
581

  
582
	if (!(req = OCSP_REQUEST_new()))
583
		goto err;
584

  
585
	if (!(id = OCSP_cert_to_id(EVP_sha1(), ctx->cert, issuer)))
586
		goto err;
587

  
588
	//if(!sk_OCSP_CERTID_push(ids, id)) goto err;
589
	if (!OCSP_request_add0_id(req, id)) {
590
		OCSP_CERTID_free(id);
591
		goto err;
592
	}
593

  
594
	if (!(bio = get_ocsp_bio(srv, sslctx, &path)))
595
		goto err;
596

  
597
	if (BIO_do_connect(bio) <= 0) {
598
		log_error_write(srv, __FILE__, __LINE__, "ss",
599
                                "Connect failed: ", strerror(errno));
600
		goto err;
601
	}
602

  
603
	resp = OCSP_sendreq_bio(bio, path, req);
604

  
605
	if (!resp) {
606
		log_error_write(srv, __FILE__, __LINE__, "ss",
607
                                "No OCSP response: ",
608
                                ERR_error_string(ERR_get_error(), NULL));
609
		goto err;
610
	}
611

  
612
	if (!check_ocsp_response(srv, resp, id))
613
		goto err;
614

  
615
	ret = 1;
616
err:
617
	SSL_CTX_free(sslctx);
618
	if (resp)
619
		OCSP_RESPONSE_free(resp);
620
	if (req)
621
		OCSP_REQUEST_free(req);
622
	if (bio)
623
		BIO_free(bio);
624

  
625
	if (!ret)
626
		log_error_write(srv, __FILE__, __LINE__, "ss", "OCSP:",
627
				ERR_error_string(ERR_get_error(), NULL));
628
	return ret;
629
}
630

  
477 631
int network_init(server *srv) {
478 632
	buffer *b;
479 633
	size_t i;
......
561 715
				return -1;
562 716
			}
563 717
			if (s->ssl_verifyclient) {
718
				if (!buffer_is_empty(s->ssl_ocsp_url) &&
719
				    !buffer_is_empty(s->ssl_ocsp_cert)) {
720
					SSL_CTX_set_cert_verify_callback(s->ssl_ctx, verify_cb, srv);
721
				}
722

  
564 723
				STACK_OF(X509_NAME) *certs = SSL_load_client_CA_file(s->ssl_ca_file->ptr);
565 724
				if (!certs) {
566 725
					log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",