Project

General

Profile

Download (20.1 KB) Statistics
| Branch: | Tag: | Revision:
1 d43ad788 Scott Ullrich
<?php
2
/* $Id$ */
3
/*
4 c5f010aa jim-p
	Copyright (C) 2008 Shrew Soft Inc
5
	Copyright (C) 2010 Jim Pingle <jimp@pfsense.org>
6
	All rights reserved.
7 d43ad788 Scott Ullrich
8
        Redistribution and use in source and binary forms, with or without
9
        modification, are permitted provided that the following conditions are met:
10
11
        1. Redistributions of source code must retain the above copyright notice,
12
           this list of conditions and the following disclaimer.
13
14
        2. Redistributions in binary form must reproduce the above copyright
15
           notice, this list of conditions and the following disclaimer in the
16
           documentation and/or other materials provided with the distribution.
17
18
        THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19
        INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20
        AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21
        AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
22
        OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
        INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
        CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
        ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
        POSSIBILITY OF SUCH DAMAGE.
28
29 523855b0 Scott Ullrich
		pfSense_MODULE:	certificate_managaer
30 d43ad788 Scott Ullrich
*/
31
32 87b4deb2 jim-p
define("OPEN_SSL_CONF_PATH", "/etc/ssl/openssl.cnf");
33
34 d43ad788 Scott Ullrich
require_once("functions.inc");
35
36 e09b941d jim-p
global $openssl_digest_algs;
37 ca621902 jim-p
$openssl_digest_algs = array("sha1", "sha224", "sha256", "sha384", "sha512");
38
39 e09b941d jim-p
global $openssl_crl_status;
40
$openssl_crl_status = array(
41
	OCSP_REVOKED_STATUS_NOSTATUS              => "No Status (default)",
42
	OCSP_REVOKED_STATUS_UNSPECIFIED           => "Unspecified",
43
	OCSP_REVOKED_STATUS_KEYCOMPROMISE         => "Key Compromise",
44
	OCSP_REVOKED_STATUS_CACOMPROMISE          => "CA Compromise",
45
	OCSP_REVOKED_STATUS_AFFILIATIONCHANGED    => "Affiliation Changed",
46
	OCSP_REVOKED_STATUS_SUPERSEDED            => "Superseded",
47
	OCSP_REVOKED_STATUS_CESSATIONOFOPERATION  => "Cessation of Operation",
48
	OCSP_REVOKED_STATUS_CERTIFICATEHOLD       => "Certificate Hold"
49
);
50
51 d43ad788 Scott Ullrich
function & lookup_ca($refid) {
52
	global $config;
53
54 1e332e98 jim-p
	if (is_array($config['ca']))
55
		foreach ($config['ca'] as & $ca)
56 d43ad788 Scott Ullrich
			if ($ca['refid'] == $refid)
57
				return $ca;
58
59
	return false;
60
}
61
62
function & lookup_ca_by_subject($subject) {
63
	global $config;
64
65 1e332e98 jim-p
	if (is_array($config['ca']))
66
		foreach ($config['ca'] as & $ca)
67 d43ad788 Scott Ullrich
		{
68
			$ca_subject = cert_get_subject($ca['crt']);
69
			if ($ca_subject == $subject)
70
				return $ca;
71
		}
72
73
	return false;
74
}
75
76
function & lookup_cert($refid) {
77
	global $config;
78
79 1e332e98 jim-p
	if (is_array($config['cert']))
80
		foreach ($config['cert'] as & $cert)
81 d43ad788 Scott Ullrich
			if ($cert['refid'] == $refid)
82
				return $cert;
83
84
	return false;
85
}
86
87 c5f010aa jim-p
function & lookup_cert_by_name($name) {
88
	global $config;
89
	if (is_array($config['cert']))
90
		foreach ($config['cert'] as & $cert)
91 f2a86ca9 jim-p
			if ($cert['descr'] == $name)
92 c5f010aa jim-p
				return $cert;
93
}
94
95
function & lookup_crl($refid) {
96
	global $config;
97
98
	if (is_array($config['crl']))
99
		foreach ($config['crl'] as & $crl)
100
			if ($crl['refid'] == $refid)
101
				return $crl;
102
103
	return false;
104
}
105
106 d43ad788 Scott Ullrich
function ca_chain_array(& $cert) {
107
	if($cert['caref']) {
108
		$chain = array();
109 5289dc57 jim-p
		$crt = lookup_ca($cert['caref']);
110 d43ad788 Scott Ullrich
		$chain[] = $crt;
111
		while ($crt) {
112
			$caref = $crt['caref'];
113
			if($caref)
114 5289dc57 jim-p
				$crt = lookup_ca($caref);
115 d43ad788 Scott Ullrich
			else
116
				$crt = false;
117
			if($crt)
118
				$chain[] = $crt;
119
		}
120
		return $chain;
121
	}
122
	return false;
123
}
124
125
function ca_chain(& $cert) {
126
	if($cert['caref']) {
127
		$ca = "";
128
		$cas = ca_chain_array($cert);
129
		if (is_array($cas))
130
			foreach ($cas as & $ca_cert)
131
			{
132
				$ca .= base64_decode($ca_cert['crt']);
133
				$ca .= "\n";
134
			}
135
		return $ca;
136
	}
137
	return "";
138
}
139
140 bfa992bc jim-p
function ca_import(& $ca, $str, $key="", $serial=0) {
141 d43ad788 Scott Ullrich
	global $config;
142
143
	$ca['crt'] = base64_encode($str);
144 ecefc738 jim-p
	if (!empty($key))
145
		$ca['prv'] = base64_encode($key);
146 bfa992bc jim-p
	if (!empty($serial))
147
		$ca['serial'] = $serial;
148 d43ad788 Scott Ullrich
	$subject = cert_get_subject($str, false);
149
	$issuer = cert_get_issuer($str, false);
150
	
151
	// Find my issuer unless self-signed
152
	if($issuer <> $subject) {
153
		$issuer_crt =& lookup_ca_by_subject($issuer);
154
		if($issuer_crt)
155
			$ca['caref'] = $issuer_crt['refid'];
156
	}
157
158
	/* Correct if child certificate was loaded first */
159 1e332e98 jim-p
	if (is_array($config['ca']))
160
		foreach ($config['ca'] as & $oca)
161 d43ad788 Scott Ullrich
		{
162
			$issuer = cert_get_issuer($oca['crt']);
163
			if($ca['refid']<>$oca['refid'] && $issuer==$subject)
164
				$oca['caref'] = $ca['refid'];
165
		}
166 1e332e98 jim-p
	if (is_array($config['cert']))
167
		foreach ($config['cert'] as & $cert)
168 d43ad788 Scott Ullrich
		{
169
			$issuer = cert_get_issuer($cert['crt']);
170
			if($issuer==$subject)
171
				$cert['caref'] = $ca['refid'];
172
		}
173
	return true;
174
}
175
176 ca621902 jim-p
function ca_create(& $ca, $keylen, $lifetime, $dn, $digest_alg = "sha256") {
177 d43ad788 Scott Ullrich
178
	$args = array(
179 87b4deb2 jim-p
		"x509_extensions" => "v3_ca",
180 ca621902 jim-p
		"digest_alg" => $digest_alg,
181 51dbdcde Ermal Lu?i
		"private_key_bits" => (int)$keylen,
182 d43ad788 Scott Ullrich
		"private_key_type" => OPENSSL_KEYTYPE_RSA,
183
		"encrypt_key" => false);
184
185
	// generate a new key pair
186 838e27bf jim-p
	$res_key = openssl_pkey_new($args);
187 1b6d9fa5 Evgeny Yurchenko
	if (!$res_key) return false;
188 d43ad788 Scott Ullrich
189
	// generate a certificate signing request
190
	$res_csr = openssl_csr_new($dn, $res_key, $args);
191 1b6d9fa5 Evgeny Yurchenko
	if (!$res_csr) return false;
192 d43ad788 Scott Ullrich
193
	// self sign the certificate
194
	$res_crt = openssl_csr_sign($res_csr, null, $res_key, $lifetime, $args);
195 1b6d9fa5 Evgeny Yurchenko
	if (!$res_crt) return false;
196 d43ad788 Scott Ullrich
197
	// export our certificate data
198 1b6d9fa5 Evgeny Yurchenko
	if (!openssl_pkey_export($res_key, $str_key) ||
199
	    !openssl_x509_export($res_crt, $str_crt))
200
		return false;
201 d43ad788 Scott Ullrich
202
	// return our ca information
203
	$ca['crt'] = base64_encode($str_crt);
204
	$ca['prv'] = base64_encode($str_key);
205
	$ca['serial'] = 0;
206
207
	return true;
208
}
209
210 ca621902 jim-p
function ca_inter_create(& $ca, $keylen, $lifetime, $dn, $caref, $digest_alg = "sha256") {
211 95c8cf48 Evgeny Yurchenko
	// Create Intermediate Certificate Authority
212
	$signing_ca =& lookup_ca($caref);
213
	if (!$signing_ca)
214
		return false;
215
216
	$signing_ca_res_crt = openssl_x509_read(base64_decode($signing_ca['crt']));
217
	$signing_ca_res_key = openssl_pkey_get_private(array(0 => base64_decode($signing_ca['prv']) , 1 => ""));
218
	if (!$signing_ca_res_crt || !$signing_ca_res_key) return false;
219
	$signing_ca_serial = ++$signing_ca['serial'];
220
221
	$args = array(
222 87b4deb2 jim-p
		"x509_extensions" => "v3_ca",
223 ca621902 jim-p
		"digest_alg" => $digest_alg,
224 95c8cf48 Evgeny Yurchenko
		"private_key_bits" => (int)$keylen,
225
		"private_key_type" => OPENSSL_KEYTYPE_RSA,
226
		"encrypt_key" => false);
227
228
	// generate a new key pair
229
	$res_key = openssl_pkey_new($args);
230
	if (!$res_key) return false;
231
232
	// generate a certificate signing request
233
	$res_csr = openssl_csr_new($dn, $res_key, $args);
234
	if (!$res_csr) return false;
235
236
	// Sign the certificate
237
	$res_crt = openssl_csr_sign($res_csr, $signing_ca_res_crt, $signing_ca_res_key, $lifetime, $args, $signing_ca_serial);
238
	if (!$res_crt) return false;
239
240
	// export our certificate data
241
	if (!openssl_pkey_export($res_key, $str_key) ||
242
	    !openssl_x509_export($res_crt, $str_crt))
243
		return false;
244
245
	// return our ca information
246
	$ca['crt'] = base64_encode($str_crt);
247
	$ca['prv'] = base64_encode($str_key);
248
	$ca['serial'] = 0;
249
250
	return true;
251
}
252
253 d43ad788 Scott Ullrich
function cert_import(& $cert, $crt_str, $key_str) {
254
255
	$cert['crt'] = base64_encode($crt_str);
256
	$cert['prv'] = base64_encode($key_str);
257
258
	$subject = cert_get_subject($crt_str, false);
259
	$issuer = cert_get_issuer($crt_str, false);
260
	
261
	// Find my issuer unless self-signed
262
	if($issuer <> $subject) {
263
		$issuer_crt =& lookup_ca_by_subject($issuer);
264
		if($issuer_crt)
265
			$cert['caref'] = $issuer_crt['refid'];
266
	}
267
	return true;
268
}
269
270 ca621902 jim-p
function cert_create(& $cert, $caref, $keylen, $lifetime, $dn, $type="user", $digest_alg = "sha256") {
271 d43ad788 Scott Ullrich
272 7c4c77ee jim-p
	$cert['type'] = $type;
273 d43ad788 Scott Ullrich
274 7c4c77ee jim-p
	if ($type != "self-signed") {
275
		$cert['caref'] = $caref;
276
		$ca =& lookup_ca($caref);
277
		if (!$ca)
278
			return false;
279
280
		$ca_str_crt = base64_decode($ca['crt']);
281
		$ca_str_key = base64_decode($ca['prv']);
282
		$ca_res_crt = openssl_x509_read($ca_str_crt);
283
		$ca_res_key = openssl_pkey_get_private(array(0 => $ca_str_key, 1 => ""));
284
		if(!$ca_res_key) return false;
285
		$ca_serial = ++$ca['serial'];
286
	}
287 d43ad788 Scott Ullrich
288 7aaabd69 jim-p
	switch ($type) {
289
		case "ca":
290
			$cert_type = "v3_ca";
291
			break;
292
		case "server":
293 7c4c77ee jim-p
		case "self-signed":
294 7aaabd69 jim-p
			$cert_type = "server";
295
			break;
296
		default:
297
			$cert_type = "usr_cert";
298
			break;
299
	}
300
301 3cb773da yarick123
	// in case of using Subject Alternative Names use other sections (with postfix '_san')
302
	// pass subjectAltName over environment variable 'SAN'
303
	if ($dn['subjectAltName']) {
304
		putenv("SAN={$dn['subjectAltName']}"); // subjectAltName can be set _only_ via configuration file
305
		$cert_type .= '_san';
306
		unset($dn['subjectAltName']);
307
	}
308
309 d43ad788 Scott Ullrich
	$args = array(
310 7aaabd69 jim-p
		"x509_extensions" => $cert_type,
311 ca621902 jim-p
		"digest_alg" => $digest_alg,
312 51dbdcde Ermal Lu?i
		"private_key_bits" => (int)$keylen,
313 d43ad788 Scott Ullrich
		"private_key_type" => OPENSSL_KEYTYPE_RSA,
314
		"encrypt_key" => false);
315
316
	// generate a new key pair
317 838e27bf jim-p
	$res_key = openssl_pkey_new($args);
318 22b380aa Evgeny Yurchenko
	if(!$res_key) return false;
319 d43ad788 Scott Ullrich
320 7c4c77ee jim-p
	// If this is a self-signed cert, blank out the CA and sign with the cert's key
321
	if ($type == "self-signed") {
322
		$ca           = null;
323
		$ca_res_crt   = null;
324
		$ca_res_key   = $res_key;
325
		$ca_serial    = 0;
326
		$cert['type'] = "server";
327
	}
328
329 d43ad788 Scott Ullrich
	// generate a certificate signing request
330
	$res_csr = openssl_csr_new($dn, $res_key, $args);
331 22b380aa Evgeny Yurchenko
	if(!$res_csr) return false;
332 d43ad788 Scott Ullrich
333 7c4c77ee jim-p
	// sign the certificate using an internal CA
334 d43ad788 Scott Ullrich
	$res_crt = openssl_csr_sign($res_csr, $ca_res_crt, $ca_res_key, $lifetime,
335
				 $args, $ca_serial);
336 22b380aa Evgeny Yurchenko
	if(!$res_crt) return false;
337 d43ad788 Scott Ullrich
338
	// export our certificate data
339 22b380aa Evgeny Yurchenko
	if (!openssl_pkey_export($res_key, $str_key) ||
340
	    !openssl_x509_export($res_crt, $str_crt))
341
		return false;
342 d43ad788 Scott Ullrich
343
	// return our certificate information
344
	$cert['crt'] = base64_encode($str_crt);
345
	$cert['prv'] = base64_encode($str_key);
346
347
	return true;
348
}
349
350 ca621902 jim-p
function csr_generate(& $cert, $keylen, $dn, $digest_alg = "sha256") {
351 d43ad788 Scott Ullrich
352
	$args = array(
353 87b4deb2 jim-p
		"x509_extensions" => "v3_req",
354 ca621902 jim-p
		"digest_alg" => $digest_alg,
355 3198b8d3 Ermal Lu?i
		"private_key_bits" => (int)$keylen,
356 d43ad788 Scott Ullrich
		"private_key_type" => OPENSSL_KEYTYPE_RSA,
357
		"encrypt_key" => false);
358
359
	// generate a new key pair
360 838e27bf jim-p
	$res_key = openssl_pkey_new($args);
361 22b380aa Evgeny Yurchenko
	if(!$res_key) return false;
362 d43ad788 Scott Ullrich
363
	// generate a certificate signing request
364
	$res_csr = openssl_csr_new($dn, $res_key, $args);
365 22b380aa Evgeny Yurchenko
	if(!$res_csr) return false;
366 d43ad788 Scott Ullrich
367
	// export our request data
368 22b380aa Evgeny Yurchenko
	if (!openssl_pkey_export($res_key, $str_key) ||
369
	    !openssl_csr_export($res_csr, $str_csr))
370
		return false;
371 d43ad788 Scott Ullrich
372
	// return our request information
373
	$cert['csr'] = base64_encode($str_csr);
374
	$cert['prv'] = base64_encode($str_key);
375
376
	return true;
377
}
378
379
function csr_complete(& $cert, $str_crt) {
380
381
	// return our request information
382
	$cert['crt'] = base64_encode($str_crt);
383
	unset($cert['csr']);
384
385
	return true;
386
}
387
388
function csr_get_subject($str_crt, $decode = true) {
389
390
	if ($decode)
391
		$str_crt = base64_decode($str_crt);
392
393
	$components = openssl_csr_get_subject($str_crt);
394
395 5ca13f69 Ermal
	if (empty($components) || !is_array($components))
396 d43ad788 Scott Ullrich
		return "unknown";
397
398 311f93cd Ermal
	ksort($components);
399 d43ad788 Scott Ullrich
	foreach ($components as $a => $v) {
400
		if (!strlen($subject))
401
			$subject = "{$a}={$v}";
402
		else
403
			$subject = "{$a}={$v}, {$subject}";
404
	}
405
406
	return $subject;
407
}
408
409
function cert_get_subject($str_crt, $decode = true) {
410
411
	if ($decode)
412
		$str_crt = base64_decode($str_crt);
413
414
	$inf_crt = openssl_x509_parse($str_crt);
415
	$components = $inf_crt['subject'];
416
417 5ca13f69 Ermal
	if (empty($components) || !is_array($components))
418 d43ad788 Scott Ullrich
		return "unknown";
419
420 b89c34aa Ermal
	ksort($components);
421 d43ad788 Scott Ullrich
	foreach ($components as $a => $v) {
422 b89c34aa Ermal
		if (is_array($v)) {
423
			ksort($v);
424 5479df47 jim-p
			foreach ($v as $w) {
425
				$asubject = "{$a}={$w}";
426
				$subject = (strlen($subject)) ? "{$asubject}, {$subject}" : $asubject;
427
			}
428 b89c34aa Ermal
		} else {
429 5479df47 jim-p
			$asubject = "{$a}={$v}";
430
			$subject = (strlen($subject)) ? "{$asubject}, {$subject}" : $asubject;
431
		}
432 d43ad788 Scott Ullrich
	}
433
434
	return $subject;
435
}
436
437
function cert_get_subject_array($crt) {
438
	$str_crt = base64_decode($crt);
439
	$inf_crt = openssl_x509_parse($str_crt);
440
	$components = $inf_crt['subject'];
441 e4d7a064 jim-p
442
	if (!is_array($components))
443
		return;
444
445 d43ad788 Scott Ullrich
	$subject_array = array();
446
447
	foreach($components as $a => $v)
448
		$subject_array[] = array('a' => $a, 'v' => $v);
449
450
	return $subject_array;
451
}
452
453 a84eb838 jim-p
function cert_get_subject_hash($crt) {
454
	$str_crt = base64_decode($crt);
455
	$inf_crt = openssl_x509_parse($str_crt);
456
	return $inf_crt['subject'];
457
}
458
459 d43ad788 Scott Ullrich
function cert_get_issuer($str_crt, $decode = true) {
460
461
	if ($decode)
462
		$str_crt = base64_decode($str_crt);
463
464
	$inf_crt = openssl_x509_parse($str_crt);
465
	$components = $inf_crt['issuer'];
466
	
467 5ca13f69 Ermal
	if (empty($components) || !is_array($components))
468 d43ad788 Scott Ullrich
		return "unknown";
469 5ca13f69 Ermal
470
	ksort($components);
471 d43ad788 Scott Ullrich
	foreach ($components as $a => $v) {
472 2a08b814 vsquared56
		if (is_array($v)) {
473
			ksort($v);
474
			foreach ($v as $w) {
475
				$aissuer = "{$a}={$w}";
476
				$issuer = (strlen($issuer)) ? "{$aissuer}, {$issuer}" : $aissuer;
477
			}
478
		} else {
479
			$aissuer = "{$a}={$v}";
480
			$issuer = (strlen($issuer)) ? "{$aissuer}, {$issuer}" : $aissuer;
481
		}
482 d43ad788 Scott Ullrich
	}
483
484
	return $issuer;
485
}
486
487 a828210b yakatz
/* this function works on x509 (crt), rsa key (prv), and req(csr) */
488
function cert_get_modulus($str_crt, $decode = true, $type = "crt"){
489
	if ($decode)
490
		$str_crt = base64_decode($str_crt);
491
492
	$modulus = "";
493
	if ( in_array($type, array("crt", "prv", "csr")) ) {
494
			$type = str_replace( array("crt","prv","csr"), array("x509","rsa","req"), $type);
495
			$modulus = exec("echo \"{$str_crt}\" | openssl {$type} -noout -modulus");
496
	}
497
	return $modulus;
498
}
499
function csr_get_modulus($str_crt, $decode = true){
500
	return cert_get_modulus($str_crt, $decode, "csr");
501
}
502 1379d66f jim-p
503
function cert_get_purpose($str_crt, $decode = true) {
504
	if ($decode)
505
		$str_crt = base64_decode($str_crt);
506
	$crt_details = openssl_x509_parse($str_crt);
507
	$purpose = array();
508
	$purpose['ca'] = (stristr($crt_details['extensions']['basicConstraints'], 'CA:TRUE') === false) ? 'No': 'Yes';
509
	$purpose['server'] = ($crt_details['extensions']['nsCertType'] == "SSL Server") ? 'Yes': 'No';
510
	return $purpose;
511
}
512
513 2b333210 jim-p
function cert_get_dates($str_crt, $decode = true) {
514
	if ($decode)
515
		$str_crt = base64_decode($str_crt);
516
	$crt_details = openssl_x509_parse($str_crt);
517
	if ($crt_details['validFrom_time_t'] > 0)
518
		$start = date('r', $crt_details['validFrom_time_t']);
519
	if ($crt_details['validTo_time_t'] > 0)
520
		$end = date('r', $crt_details['validTo_time_t']);
521
	return array($start, $end);
522
}
523
524 04761344 jim-p
function cert_get_serial($str_crt, $decode = true) {
525
	if ($decode)
526
		$str_crt = base64_decode($str_crt);
527
	$crt_details = openssl_x509_parse($str_crt);
528
	if (isset($crt_details['serialNumber']) && !empty($crt_details['serialNumber']))
529
		return $crt_details['serialNumber'];
530
	else
531
		return NULL;
532
}
533
534 a828210b yakatz
function prv_get_modulus($str_crt, $decode = true){
535
	return cert_get_modulus($str_crt, $decode, "prv");
536
}
537
538 dea98903 jim-p
function is_user_cert($certref) {
539 dab2e769 jim-p
	global $config;
540
	if (!is_array($config['system']['user']))
541
		return;
542
	foreach ($config['system']['user'] as $user) {
543
		if (!is_array($user['cert']))
544
			continue;
545
		foreach ($user['cert'] as $cert) {
546 dea98903 jim-p
			if ($certref == $cert)
547
				return true;
548 dab2e769 jim-p
		}
549
	}
550 dea98903 jim-p
	return false;
551 dab2e769 jim-p
}
552
553 dea98903 jim-p
function is_openvpn_server_cert($certref) {
554 dab2e769 jim-p
	global $config;
555 dea98903 jim-p
	if (!is_array($config['openvpn']['openvpn-server']))
556
		return;
557
	foreach ($config['openvpn']['openvpn-server'] as $ovpns) {
558
		if ($ovpns['certref'] == $certref)
559
			return true;
560
	}
561
	return false;
562
}
563
564
function is_openvpn_client_cert($certref) {
565
	global $config;
566
	if (!is_array($config['openvpn']['openvpn-client']))
567
		return;
568
	foreach ($config['openvpn']['openvpn-client'] as $ovpnc) {
569
		if ($ovpnc['certref'] == $certref)
570
			return true;
571
	}
572
	return false;
573
}
574
575
function is_ipsec_cert($certref) {
576
	global $config;
577
	if (!is_array($config['ipsec']['phase1']))
578
		return;
579
	foreach ($config['ipsec']['phase1'] as $ipsec) {
580
		if ($ipsec['certref'] == $certref)
581
			return true;
582
	}
583
	return false;
584
}
585
586
function is_webgui_cert($certref) {
587
	global $config;
588 8364184a jim-p
	if (($config['system']['webgui']['ssl-certref'] == $certref)
589
		&& ($config['system']['webgui']['protocol'] != "http"))
590 dea98903 jim-p
		return true;
591
}
592
593 36f6ed35 bcyrill
function is_captiveportal_cert($certref) {
594
	global $config;
595
	if (!is_array($config['captiveportal']))
596
		return;
597
	foreach ($config['captiveportal'] as $portal) {
598 adca02c4 bcyrill
		if (isset($portal['enable']) && isset($portal['httpslogin']) && ($portal['certref'] == $certref))
599 36f6ed35 bcyrill
			return true;
600
	}
601
	return false;
602
}
603
604 dea98903 jim-p
function cert_in_use($certref) {
605
	return (is_webgui_cert($certref) ||
606
		is_user_cert($certref) ||
607
		is_openvpn_server_cert($certref) ||
608
		is_openvpn_client_cert($certref) ||
609 36f6ed35 bcyrill
		is_ipsec_cert($certref) ||
610
		is_captiveportal_cert($certref));
611 dab2e769 jim-p
}
612
613 c5f010aa jim-p
function crl_create(& $crl, $caref, $name, $serial=0, $lifetime=9999) {
614
	global $config;
615
	$ca =& lookup_ca($caref);
616
	if (!$ca)
617
		return false;
618 f2a86ca9 jim-p
	$crl['descr'] = $name;
619 c5f010aa jim-p
	$crl['caref'] = $caref;
620
	$crl['serial'] = $serial;
621
	$crl['lifetime'] = $lifetime;
622
	$crl['cert'] = array();
623
	$crl_res = crl_update($crl);
624
	$config['crl'][] = $crl;
625
	return $crl_res;
626
}
627
628
function crl_update(& $crl) {
629
	global $config;
630
	$ca =& lookup_ca($crl['caref']);
631
	if (!$ca)
632
		return false;
633 7b757d1b jim-p
	// If we have text but no certs, it was imported and cannot be updated.
634 728003c8 jim-p
	if (($crl["method"] != "internal") && (!empty($crl['text']) && empty($crl['cert'])))
635 7b757d1b jim-p
		return false;
636 c5f010aa jim-p
	$crl['serial']++;
637
	$ca_str_crt = base64_decode($ca['crt']);
638
	$ca_str_key = base64_decode($ca['prv']);
639
	$crl_res = openssl_crl_new($ca_str_crt, $crl['serial'], $crl['lifetime']);
640 4bc2c676 jim-p
	if (is_array($crl['cert']) && (count($crl['cert']) > 0)) {
641
		foreach ($crl['cert'] as $cert) {
642
			openssl_crl_revoke_cert($crl_res, base64_decode($cert["crt"]), $cert["revoke_time"], $cert["reason"]);
643
		}
644 c5f010aa jim-p
	}
645
	openssl_crl_export($crl_res, $crl_text, $ca_str_key);
646
	$crl['text'] = base64_encode($crl_text);
647
	return $crl_res;
648
}
649
650
function cert_revoke($cert, & $crl, $reason=OCSP_REVOKED_STATUS_UNSPECIFIED) {
651
	global $config;
652 fb3f1993 jim-p
	if (is_cert_revoked($cert, $crl['refid']))
653 c5f010aa jim-p
		return true;
654 7b757d1b jim-p
	// If we have text but no certs, it was imported and cannot be updated.
655 fb3f1993 jim-p
	if (!is_crl_internal($crl))
656 7b757d1b jim-p
		return false;
657 c5f010aa jim-p
	$cert["reason"] = $reason;
658
	$cert["revoke_time"] = time();
659
	$crl["cert"][] = $cert;
660
	crl_update($crl);
661 fb3f1993 jim-p
	return true;
662 c5f010aa jim-p
}
663
664
function cert_unrevoke($cert, & $crl) {
665
	global $config;
666 fb3f1993 jim-p
	if (!is_crl_internal($crl))
667 7b757d1b jim-p
		return false;
668 c5f010aa jim-p
	foreach ($crl['cert'] as $id => $rcert) {
669 f2a86ca9 jim-p
		if (($rcert['refid'] == $cert['refid']) || ($rcert['descr'] == $cert['descr'])) {
670 c5f010aa jim-p
			unset($crl['cert'][$id]);
671 728003c8 jim-p
			if (count($crl['cert']) == 0) {
672
				// Protect against accidentally switching the type to imported, for older CRLs
673
				if (!isset($crl['method']))
674
					$crl['method'] = "internal";
675
				crl_update($crl);
676
			} else
677 a59831e7 jim-p
				crl_update($crl);
678 c5f010aa jim-p
			return true;
679
		}
680
	}
681
	return false;
682
}
683
684 04761344 jim-p
/* Compare two certificates to see if they match. */
685
function cert_compare($cert1, $cert2) {
686
	/* Ensure two certs are identical by first checking that their issuers match, then
687
		subjects, then serial numbers, and finally the moduli. Anything less strict
688
		could accidentally count two similar, but different, certificates as
689
		being identical. */
690
	$c1 = base64_decode($cert1['crt']);
691
	$c2 = base64_decode($cert2['crt']);
692
	if ((cert_get_issuer($c1, false) == cert_get_issuer($c2, false))
693
		&& (cert_get_subject($c1, false) == cert_get_subject($c2, false))
694
		&& (cert_get_serial($c1, false) == cert_get_serial($c2, false))
695
		&& (cert_get_modulus($c1, false) == cert_get_modulus($c2, false)))
696
		return true;
697
	return false;
698
}
699
700 fb3f1993 jim-p
function is_cert_revoked($cert, $crlref = "") {
701 c5f010aa jim-p
	global $config;
702 088ce869 jim-p
	if (!is_array($config['crl']))
703 c5f010aa jim-p
		return false;
704
705 fb3f1993 jim-p
	if (!empty($crlref)) {
706 28ff7ace jim-p
		$crl = lookup_crl($crlref);
707 088ce869 jim-p
		if (!is_array($crl['cert']))
708 fb3f1993 jim-p
			return false;
709 088ce869 jim-p
		foreach ($crl['cert'] as $rcert) {
710 04761344 jim-p
			if (cert_compare($rcert, $cert))
711 c5f010aa jim-p
				return true;
712
		}
713 fb3f1993 jim-p
	} else {
714
		foreach ($config['crl'] as $crl) {
715
			if (!is_array($crl['cert']))
716
				continue;
717
			foreach ($crl['cert'] as $rcert) {
718 04761344 jim-p
				if (cert_compare($rcert, $cert))
719 fb3f1993 jim-p
					return true;
720
			}
721
		}
722
	}
723
	return false;
724
}
725
726
function is_openvpn_server_crl($crlref) {
727
	global $config;
728
	if (!is_array($config['openvpn']['openvpn-server']))
729
		return;
730
	foreach ($config['openvpn']['openvpn-server'] as $ovpns) {
731 cd9f13e0 jim-p
		if (!empty($ovpns['crlref']) && ($ovpns['crlref'] == $crlref))
732 fb3f1993 jim-p
			return true;
733 c5f010aa jim-p
	}
734
	return false;
735
}
736
737 fb3f1993 jim-p
// Keep this general to allow for future expansion. See cert_in_use() above.
738
function crl_in_use($crlref) {
739
	return (is_openvpn_server_crl($crlref));
740
}
741
742
function is_crl_internal($crl) {
743 728003c8 jim-p
	return (!(!empty($crl['text']) && empty($crl['cert'])) || ($crl["method"] == "internal"));
744 fb3f1993 jim-p
}
745
746 b34b2b7d jim-p
function cert_get_cn($crt, $isref = false) {
747
	/* If this is a certref, not an actual cert, look up the cert first */
748
	if ($isref) {
749
		$cert = lookup_cert($crt);
750
		/* If it's not a valid cert, bail. */
751
		if (!(is_array($cert) && !empty($cert['crt'])))
752
			return "";
753
		$cert = $cert['crt'];
754
	} else {
755
		$cert = $crt;
756
	}
757
	$sub = cert_get_subject_array($cert);
758
	if (is_array($sub)) {
759
		foreach ($sub as $s) {
760
			if (strtoupper($s['a']) == "CN")
761
				return $s['v'];
762
		}
763
	}
764
	return "";
765
}
766
767 b89c34aa Ermal
?>