Projet

Général

Profil

Télécharger (20,1 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / certs.inc @ 7c4c77ee

1
<?php
2
/* $Id$ */
3
/*
4
	Copyright (C) 2008 Shrew Soft Inc
5
	Copyright (C) 2010 Jim Pingle <jimp@pfsense.org>
6
	All rights reserved.
7

    
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
		DISABLE_PHP_LINT_CHECKING
30
		pfSense_MODULE:	certificate_managaer
31
*/
32

    
33
define("OPEN_SSL_CONF_PATH", "/etc/ssl/openssl.cnf");
34

    
35
require_once("functions.inc");
36

    
37
global $openssl_digest_algs;
38
$openssl_digest_algs = array("sha1", "sha224", "sha256", "sha384", "sha512");
39

    
40
global $openssl_crl_status;
41
$openssl_crl_status = array(
42
	OCSP_REVOKED_STATUS_NOSTATUS              => "No Status (default)",
43
	OCSP_REVOKED_STATUS_UNSPECIFIED           => "Unspecified",
44
	OCSP_REVOKED_STATUS_KEYCOMPROMISE         => "Key Compromise",
45
	OCSP_REVOKED_STATUS_CACOMPROMISE          => "CA Compromise",
46
	OCSP_REVOKED_STATUS_AFFILIATIONCHANGED    => "Affiliation Changed",
47
	OCSP_REVOKED_STATUS_SUPERSEDED            => "Superseded",
48
	OCSP_REVOKED_STATUS_CESSATIONOFOPERATION  => "Cessation of Operation",
49
	OCSP_REVOKED_STATUS_CERTIFICATEHOLD       => "Certificate Hold"
50
);
51

    
52
function & lookup_ca($refid) {
53
	global $config;
54

    
55
	if (is_array($config['ca']))
56
		foreach ($config['ca'] as & $ca)
57
			if ($ca['refid'] == $refid)
58
				return $ca;
59

    
60
	return false;
61
}
62

    
63
function & lookup_ca_by_subject($subject) {
64
	global $config;
65

    
66
	if (is_array($config['ca']))
67
		foreach ($config['ca'] as & $ca)
68
		{
69
			$ca_subject = cert_get_subject($ca['crt']);
70
			if ($ca_subject == $subject)
71
				return $ca;
72
		}
73

    
74
	return false;
75
}
76

    
77
function & lookup_cert($refid) {
78
	global $config;
79

    
80
	if (is_array($config['cert']))
81
		foreach ($config['cert'] as & $cert)
82
			if ($cert['refid'] == $refid)
83
				return $cert;
84

    
85
	return false;
86
}
87

    
88
function & lookup_cert_by_name($name) {
89
	global $config;
90
	if (is_array($config['cert']))
91
		foreach ($config['cert'] as & $cert)
92
			if ($cert['descr'] == $name)
93
				return $cert;
94
}
95

    
96
function & lookup_crl($refid) {
97
	global $config;
98

    
99
	if (is_array($config['crl']))
100
		foreach ($config['crl'] as & $crl)
101
			if ($crl['refid'] == $refid)
102
				return $crl;
103

    
104
	return false;
105
}
106

    
107
function ca_chain_array(& $cert) {
108
	if($cert['caref']) {
109
		$chain = array();
110
		$crt = lookup_ca($cert['caref']);
111
		$chain[] = $crt;
112
		while ($crt) {
113
			$caref = $crt['caref'];
114
			if($caref)
115
				$crt = lookup_ca($caref);
116
			else
117
				$crt = false;
118
			if($crt)
119
				$chain[] = $crt;
120
		}
121
		return $chain;
122
	}
123
	return false;
124
}
125

    
126
function ca_chain(& $cert) {
127
	if($cert['caref']) {
128
		$ca = "";
129
		$cas = ca_chain_array($cert);
130
		if (is_array($cas))
131
			foreach ($cas as & $ca_cert)
132
			{
133
				$ca .= base64_decode($ca_cert['crt']);
134
				$ca .= "\n";
135
			}
136
		return $ca;
137
	}
138
	return "";
139
}
140

    
141
function ca_import(& $ca, $str, $key="", $serial=0) {
142
	global $config;
143

    
144
	$ca['crt'] = base64_encode($str);
145
	if (!empty($key))
146
		$ca['prv'] = base64_encode($key);
147
	if (!empty($serial))
148
		$ca['serial'] = $serial;
149
	$subject = cert_get_subject($str, false);
150
	$issuer = cert_get_issuer($str, false);
151
	
152
	// Find my issuer unless self-signed
153
	if($issuer <> $subject) {
154
		$issuer_crt =& lookup_ca_by_subject($issuer);
155
		if($issuer_crt)
156
			$ca['caref'] = $issuer_crt['refid'];
157
	}
158

    
159
	/* Correct if child certificate was loaded first */
160
	if (is_array($config['ca']))
161
		foreach ($config['ca'] as & $oca)
162
		{
163
			$issuer = cert_get_issuer($oca['crt']);
164
			if($ca['refid']<>$oca['refid'] && $issuer==$subject)
165
				$oca['caref'] = $ca['refid'];
166
		}
167
	if (is_array($config['cert']))
168
		foreach ($config['cert'] as & $cert)
169
		{
170
			$issuer = cert_get_issuer($cert['crt']);
171
			if($issuer==$subject)
172
				$cert['caref'] = $ca['refid'];
173
		}
174
	return true;
175
}
176

    
177
function ca_create(& $ca, $keylen, $lifetime, $dn, $digest_alg = "sha256") {
178

    
179
	$args = array(
180
		"x509_extensions" => "v3_ca",
181
		"digest_alg" => $digest_alg,
182
		"private_key_bits" => (int)$keylen,
183
		"private_key_type" => OPENSSL_KEYTYPE_RSA,
184
		"encrypt_key" => false);
185

    
186
	// generate a new key pair
187
	$res_key = openssl_pkey_new($args);
188
	if (!$res_key) return false;
189

    
190
	// generate a certificate signing request
191
	$res_csr = openssl_csr_new($dn, $res_key, $args);
192
	if (!$res_csr) return false;
193

    
194
	// self sign the certificate
195
	$res_crt = openssl_csr_sign($res_csr, null, $res_key, $lifetime, $args);
196
	if (!$res_crt) return false;
197

    
198
	// export our certificate data
199
	if (!openssl_pkey_export($res_key, $str_key) ||
200
	    !openssl_x509_export($res_crt, $str_crt))
201
		return false;
202

    
203
	// return our ca information
204
	$ca['crt'] = base64_encode($str_crt);
205
	$ca['prv'] = base64_encode($str_key);
206
	$ca['serial'] = 0;
207

    
208
	return true;
209
}
210

    
211
function ca_inter_create(& $ca, $keylen, $lifetime, $dn, $caref, $digest_alg = "sha256") {
212
	// Create Intermediate Certificate Authority
213
	$signing_ca =& lookup_ca($caref);
214
	if (!$signing_ca)
215
		return false;
216

    
217
	$signing_ca_res_crt = openssl_x509_read(base64_decode($signing_ca['crt']));
218
	$signing_ca_res_key = openssl_pkey_get_private(array(0 => base64_decode($signing_ca['prv']) , 1 => ""));
219
	if (!$signing_ca_res_crt || !$signing_ca_res_key) return false;
220
	$signing_ca_serial = ++$signing_ca['serial'];
221

    
222
	$args = array(
223
		"x509_extensions" => "v3_ca",
224
		"digest_alg" => $digest_alg,
225
		"private_key_bits" => (int)$keylen,
226
		"private_key_type" => OPENSSL_KEYTYPE_RSA,
227
		"encrypt_key" => false);
228

    
229
	// generate a new key pair
230
	$res_key = openssl_pkey_new($args);
231
	if (!$res_key) return false;
232

    
233
	// generate a certificate signing request
234
	$res_csr = openssl_csr_new($dn, $res_key, $args);
235
	if (!$res_csr) return false;
236

    
237
	// Sign the certificate
238
	$res_crt = openssl_csr_sign($res_csr, $signing_ca_res_crt, $signing_ca_res_key, $lifetime, $args, $signing_ca_serial);
239
	if (!$res_crt) return false;
240

    
241
	// export our certificate data
242
	if (!openssl_pkey_export($res_key, $str_key) ||
243
	    !openssl_x509_export($res_crt, $str_crt))
244
		return false;
245

    
246
	// return our ca information
247
	$ca['crt'] = base64_encode($str_crt);
248
	$ca['prv'] = base64_encode($str_key);
249
	$ca['serial'] = 0;
250

    
251
	return true;
252
}
253

    
254
function cert_import(& $cert, $crt_str, $key_str) {
255

    
256
	$cert['crt'] = base64_encode($crt_str);
257
	$cert['prv'] = base64_encode($key_str);
258

    
259
	$subject = cert_get_subject($crt_str, false);
260
	$issuer = cert_get_issuer($crt_str, false);
261
	
262
	// Find my issuer unless self-signed
263
	if($issuer <> $subject) {
264
		$issuer_crt =& lookup_ca_by_subject($issuer);
265
		if($issuer_crt)
266
			$cert['caref'] = $issuer_crt['refid'];
267
	}
268
	return true;
269
}
270

    
271
function cert_create(& $cert, $caref, $keylen, $lifetime, $dn, $type="user", $digest_alg = "sha256") {
272

    
273
	$cert['type'] = $type;
274

    
275
	if ($type != "self-signed") {
276
		$cert['caref'] = $caref;
277
		$ca =& lookup_ca($caref);
278
		if (!$ca)
279
			return false;
280

    
281
		$ca_str_crt = base64_decode($ca['crt']);
282
		$ca_str_key = base64_decode($ca['prv']);
283
		$ca_res_crt = openssl_x509_read($ca_str_crt);
284
		$ca_res_key = openssl_pkey_get_private(array(0 => $ca_str_key, 1 => ""));
285
		if(!$ca_res_key) return false;
286
		$ca_serial = ++$ca['serial'];
287
	}
288

    
289
	switch ($type) {
290
		case "ca":
291
			$cert_type = "v3_ca";
292
			break;
293
		case "server":
294
		case "self-signed":
295
			$cert_type = "server";
296
			break;
297
		default:
298
			$cert_type = "usr_cert";
299
			break;
300
	}
301

    
302
	// in case of using Subject Alternative Names use other sections (with postfix '_san')
303
	// pass subjectAltName over environment variable 'SAN'
304
	if ($dn['subjectAltName']) {
305
		putenv("SAN={$dn['subjectAltName']}"); // subjectAltName can be set _only_ via configuration file
306
		$cert_type .= '_san';
307
		unset($dn['subjectAltName']);
308
	}
309

    
310
	$args = array(
311
		"x509_extensions" => $cert_type,
312
		"digest_alg" => $digest_alg,
313
		"private_key_bits" => (int)$keylen,
314
		"private_key_type" => OPENSSL_KEYTYPE_RSA,
315
		"encrypt_key" => false);
316

    
317
	// generate a new key pair
318
	$res_key = openssl_pkey_new($args);
319
	if(!$res_key) return false;
320

    
321
	// If this is a self-signed cert, blank out the CA and sign with the cert's key
322
	if ($type == "self-signed") {
323
		$ca           = null;
324
		$ca_res_crt   = null;
325
		$ca_res_key   = $res_key;
326
		$ca_serial    = 0;
327
		$cert['type'] = "server";
328
	}
329

    
330
	// generate a certificate signing request
331
	$res_csr = openssl_csr_new($dn, $res_key, $args);
332
	if(!$res_csr) return false;
333

    
334
	// sign the certificate using an internal CA
335
	$res_crt = openssl_csr_sign($res_csr, $ca_res_crt, $ca_res_key, $lifetime,
336
				 $args, $ca_serial);
337
	if(!$res_crt) return false;
338

    
339
	// export our certificate data
340
	if (!openssl_pkey_export($res_key, $str_key) ||
341
	    !openssl_x509_export($res_crt, $str_crt))
342
		return false;
343

    
344
	// return our certificate information
345
	$cert['crt'] = base64_encode($str_crt);
346
	$cert['prv'] = base64_encode($str_key);
347

    
348
	return true;
349
}
350

    
351
function csr_generate(& $cert, $keylen, $dn, $digest_alg = "sha256") {
352

    
353
	$args = array(
354
		"x509_extensions" => "v3_req",
355
		"digest_alg" => $digest_alg,
356
		"private_key_bits" => (int)$keylen,
357
		"private_key_type" => OPENSSL_KEYTYPE_RSA,
358
		"encrypt_key" => false);
359

    
360
	// generate a new key pair
361
	$res_key = openssl_pkey_new($args);
362
	if(!$res_key) return false;
363

    
364
	// generate a certificate signing request
365
	$res_csr = openssl_csr_new($dn, $res_key, $args);
366
	if(!$res_csr) return false;
367

    
368
	// export our request data
369
	if (!openssl_pkey_export($res_key, $str_key) ||
370
	    !openssl_csr_export($res_csr, $str_csr))
371
		return false;
372

    
373
	// return our request information
374
	$cert['csr'] = base64_encode($str_csr);
375
	$cert['prv'] = base64_encode($str_key);
376

    
377
	return true;
378
}
379

    
380
function csr_complete(& $cert, $str_crt) {
381

    
382
	// return our request information
383
	$cert['crt'] = base64_encode($str_crt);
384
	unset($cert['csr']);
385

    
386
	return true;
387
}
388

    
389
function csr_get_subject($str_crt, $decode = true) {
390

    
391
	if ($decode)
392
		$str_crt = base64_decode($str_crt);
393

    
394
	$components = openssl_csr_get_subject($str_crt);
395

    
396
	if (empty($components) || !is_array($components))
397
		return "unknown";
398

    
399
	ksort($components);
400
	foreach ($components as $a => $v) {
401
		if (!strlen($subject))
402
			$subject = "{$a}={$v}";
403
		else
404
			$subject = "{$a}={$v}, {$subject}";
405
	}
406

    
407
	return $subject;
408
}
409

    
410
function cert_get_subject($str_crt, $decode = true) {
411

    
412
	if ($decode)
413
		$str_crt = base64_decode($str_crt);
414

    
415
	$inf_crt = openssl_x509_parse($str_crt);
416
	$components = $inf_crt['subject'];
417

    
418
	if (empty($components) || !is_array($components))
419
		return "unknown";
420

    
421
	ksort($components);
422
	foreach ($components as $a => $v) {
423
		if (is_array($v)) {
424
			ksort($v);
425
			foreach ($v as $w) {
426
				$asubject = "{$a}={$w}";
427
				$subject = (strlen($subject)) ? "{$asubject}, {$subject}" : $asubject;
428
			}
429
		} else {
430
			$asubject = "{$a}={$v}";
431
			$subject = (strlen($subject)) ? "{$asubject}, {$subject}" : $asubject;
432
		}
433
	}
434

    
435
	return $subject;
436
}
437

    
438
function cert_get_subject_array($crt) {
439
	$str_crt = base64_decode($crt);
440
	$inf_crt = openssl_x509_parse($str_crt);
441
	$components = $inf_crt['subject'];
442

    
443
	if (!is_array($components))
444
		return;
445

    
446
	$subject_array = array();
447

    
448
	foreach($components as $a => $v)
449
		$subject_array[] = array('a' => $a, 'v' => $v);
450

    
451
	return $subject_array;
452
}
453

    
454
function cert_get_subject_hash($crt) {
455
	$str_crt = base64_decode($crt);
456
	$inf_crt = openssl_x509_parse($str_crt);
457
	return $inf_crt['subject'];
458
}
459

    
460
function cert_get_issuer($str_crt, $decode = true) {
461

    
462
	if ($decode)
463
		$str_crt = base64_decode($str_crt);
464

    
465
	$inf_crt = openssl_x509_parse($str_crt);
466
	$components = $inf_crt['issuer'];
467
	
468
	if (empty($components) || !is_array($components))
469
		return "unknown";
470

    
471
	ksort($components);
472
	foreach ($components as $a => $v) {
473
		if (is_array($v)) {
474
			ksort($v);
475
			foreach ($v as $w) {
476
				$aissuer = "{$a}={$w}";
477
				$issuer = (strlen($issuer)) ? "{$aissuer}, {$issuer}" : $aissuer;
478
			}
479
		} else {
480
			$aissuer = "{$a}={$v}";
481
			$issuer = (strlen($issuer)) ? "{$aissuer}, {$issuer}" : $aissuer;
482
		}
483
	}
484

    
485
	return $issuer;
486
}
487

    
488
/* this function works on x509 (crt), rsa key (prv), and req(csr) */
489
function cert_get_modulus($str_crt, $decode = true, $type = "crt"){
490
	if ($decode)
491
		$str_crt = base64_decode($str_crt);
492

    
493
	$modulus = "";
494
	if ( in_array($type, array("crt", "prv", "csr")) ) {
495
			$type = str_replace( array("crt","prv","csr"), array("x509","rsa","req"), $type);
496
			$modulus = exec("echo \"{$str_crt}\" | openssl {$type} -noout -modulus");
497
	}
498
	return $modulus;
499
}
500
function csr_get_modulus($str_crt, $decode = true){
501
	return cert_get_modulus($str_crt, $decode, "csr");
502
}
503

    
504
function cert_get_purpose($str_crt, $decode = true) {
505
	if ($decode)
506
		$str_crt = base64_decode($str_crt);
507
	$crt_details = openssl_x509_parse($str_crt);
508
	$purpose = array();
509
	$purpose['ca'] = (stristr($crt_details['extensions']['basicConstraints'], 'CA:TRUE') === false) ? 'No': 'Yes';
510
	$purpose['server'] = ($crt_details['extensions']['nsCertType'] == "SSL Server") ? 'Yes': 'No';
511
	return $purpose;
512
}
513

    
514
function cert_get_dates($str_crt, $decode = true) {
515
	if ($decode)
516
		$str_crt = base64_decode($str_crt);
517
	$crt_details = openssl_x509_parse($str_crt);
518
	if ($crt_details['validFrom_time_t'] > 0)
519
		$start = date('r', $crt_details['validFrom_time_t']);
520
	if ($crt_details['validTo_time_t'] > 0)
521
		$end = date('r', $crt_details['validTo_time_t']);
522
	return array($start, $end);
523
}
524

    
525
function cert_get_serial($str_crt, $decode = true) {
526
	if ($decode)
527
		$str_crt = base64_decode($str_crt);
528
	$crt_details = openssl_x509_parse($str_crt);
529
	if (isset($crt_details['serialNumber']) && !empty($crt_details['serialNumber']))
530
		return $crt_details['serialNumber'];
531
	else
532
		return NULL;
533
}
534

    
535
function prv_get_modulus($str_crt, $decode = true){
536
	return cert_get_modulus($str_crt, $decode, "prv");
537
}
538

    
539
function is_user_cert($certref) {
540
	global $config;
541
	if (!is_array($config['system']['user']))
542
		return;
543
	foreach ($config['system']['user'] as $user) {
544
		if (!is_array($user['cert']))
545
			continue;
546
		foreach ($user['cert'] as $cert) {
547
			if ($certref == $cert)
548
				return true;
549
		}
550
	}
551
	return false;
552
}
553

    
554
function is_openvpn_server_cert($certref) {
555
	global $config;
556
	if (!is_array($config['openvpn']['openvpn-server']))
557
		return;
558
	foreach ($config['openvpn']['openvpn-server'] as $ovpns) {
559
		if ($ovpns['certref'] == $certref)
560
			return true;
561
	}
562
	return false;
563
}
564

    
565
function is_openvpn_client_cert($certref) {
566
	global $config;
567
	if (!is_array($config['openvpn']['openvpn-client']))
568
		return;
569
	foreach ($config['openvpn']['openvpn-client'] as $ovpnc) {
570
		if ($ovpnc['certref'] == $certref)
571
			return true;
572
	}
573
	return false;
574
}
575

    
576
function is_ipsec_cert($certref) {
577
	global $config;
578
	if (!is_array($config['ipsec']['phase1']))
579
		return;
580
	foreach ($config['ipsec']['phase1'] as $ipsec) {
581
		if ($ipsec['certref'] == $certref)
582
			return true;
583
	}
584
	return false;
585
}
586

    
587
function is_webgui_cert($certref) {
588
	global $config;
589
	if (($config['system']['webgui']['ssl-certref'] == $certref)
590
		&& ($config['system']['webgui']['protocol'] != "http"))
591
		return true;
592
}
593

    
594
function is_captiveportal_cert($certref) {
595
	global $config;
596
	if (!is_array($config['captiveportal']))
597
		return;
598
	foreach ($config['captiveportal'] as $portal) {
599
		if (isset($portal['enable']) && isset($portal['httpslogin']) && ($portal['certref'] == $certref))
600
			return true;
601
	}
602
	return false;
603
}
604

    
605
function cert_in_use($certref) {
606
	return (is_webgui_cert($certref) ||
607
		is_user_cert($certref) ||
608
		is_openvpn_server_cert($certref) ||
609
		is_openvpn_client_cert($certref) ||
610
		is_ipsec_cert($certref) ||
611
		is_captiveportal_cert($certref));
612
}
613

    
614
function crl_create(& $crl, $caref, $name, $serial=0, $lifetime=9999) {
615
	global $config;
616
	$ca =& lookup_ca($caref);
617
	if (!$ca)
618
		return false;
619
	$crl['descr'] = $name;
620
	$crl['caref'] = $caref;
621
	$crl['serial'] = $serial;
622
	$crl['lifetime'] = $lifetime;
623
	$crl['cert'] = array();
624
	$crl_res = crl_update($crl);
625
	$config['crl'][] = $crl;
626
	return $crl_res;
627
}
628

    
629
function crl_update(& $crl) {
630
	global $config;
631
	$ca =& lookup_ca($crl['caref']);
632
	if (!$ca)
633
		return false;
634
	// If we have text but no certs, it was imported and cannot be updated.
635
	if (($crl["method"] != "internal") && (!empty($crl['text']) && empty($crl['cert'])))
636
		return false;
637
	$crl['serial']++;
638
	$ca_str_crt = base64_decode($ca['crt']);
639
	$ca_str_key = base64_decode($ca['prv']);
640
	$crl_res = openssl_crl_new($ca_str_crt, $crl['serial'], $crl['lifetime']);
641
	if (is_array($crl['cert']) && (count($crl['cert']) > 0)) {
642
		foreach ($crl['cert'] as $cert) {
643
			openssl_crl_revoke_cert($crl_res, base64_decode($cert["crt"]), $cert["revoke_time"], $cert["reason"]);
644
		}
645
	}
646
	openssl_crl_export($crl_res, $crl_text, $ca_str_key);
647
	$crl['text'] = base64_encode($crl_text);
648
	return $crl_res;
649
}
650

    
651
function cert_revoke($cert, & $crl, $reason=OCSP_REVOKED_STATUS_UNSPECIFIED) {
652
	global $config;
653
	if (is_cert_revoked($cert, $crl['refid']))
654
		return true;
655
	// If we have text but no certs, it was imported and cannot be updated.
656
	if (!is_crl_internal($crl))
657
		return false;
658
	$cert["reason"] = $reason;
659
	$cert["revoke_time"] = time();
660
	$crl["cert"][] = $cert;
661
	crl_update($crl);
662
	return true;
663
}
664

    
665
function cert_unrevoke($cert, & $crl) {
666
	global $config;
667
	if (!is_crl_internal($crl))
668
		return false;
669
	foreach ($crl['cert'] as $id => $rcert) {
670
		if (($rcert['refid'] == $cert['refid']) || ($rcert['descr'] == $cert['descr'])) {
671
			unset($crl['cert'][$id]);
672
			if (count($crl['cert']) == 0) {
673
				// Protect against accidentally switching the type to imported, for older CRLs
674
				if (!isset($crl['method']))
675
					$crl['method'] = "internal";
676
				crl_update($crl);
677
			} else
678
				crl_update($crl);
679
			return true;
680
		}
681
	}
682
	return false;
683
}
684

    
685
/* Compare two certificates to see if they match. */
686
function cert_compare($cert1, $cert2) {
687
	/* Ensure two certs are identical by first checking that their issuers match, then
688
		subjects, then serial numbers, and finally the moduli. Anything less strict
689
		could accidentally count two similar, but different, certificates as
690
		being identical. */
691
	$c1 = base64_decode($cert1['crt']);
692
	$c2 = base64_decode($cert2['crt']);
693
	if ((cert_get_issuer($c1, false) == cert_get_issuer($c2, false))
694
		&& (cert_get_subject($c1, false) == cert_get_subject($c2, false))
695
		&& (cert_get_serial($c1, false) == cert_get_serial($c2, false))
696
		&& (cert_get_modulus($c1, false) == cert_get_modulus($c2, false)))
697
		return true;
698
	return false;
699
}
700

    
701
function is_cert_revoked($cert, $crlref = "") {
702
	global $config;
703
	if (!is_array($config['crl']))
704
		return false;
705

    
706
	if (!empty($crlref)) {
707
		$crl = lookup_crl($crlref);
708
		if (!is_array($crl['cert']))
709
			return false;
710
		foreach ($crl['cert'] as $rcert) {
711
			if (cert_compare($rcert, $cert))
712
				return true;
713
		}
714
	} else {
715
		foreach ($config['crl'] as $crl) {
716
			if (!is_array($crl['cert']))
717
				continue;
718
			foreach ($crl['cert'] as $rcert) {
719
				if (cert_compare($rcert, $cert))
720
					return true;
721
			}
722
		}
723
	}
724
	return false;
725
}
726

    
727
function is_openvpn_server_crl($crlref) {
728
	global $config;
729
	if (!is_array($config['openvpn']['openvpn-server']))
730
		return;
731
	foreach ($config['openvpn']['openvpn-server'] as $ovpns) {
732
		if (!empty($ovpns['crlref']) && ($ovpns['crlref'] == $crlref))
733
			return true;
734
	}
735
	return false;
736
}
737

    
738
// Keep this general to allow for future expansion. See cert_in_use() above.
739
function crl_in_use($crlref) {
740
	return (is_openvpn_server_crl($crlref));
741
}
742

    
743
function is_crl_internal($crl) {
744
	return (!(!empty($crl['text']) && empty($crl['cert'])) || ($crl["method"] == "internal"));
745
}
746

    
747
function cert_get_cn($crt, $isref = false) {
748
	/* If this is a certref, not an actual cert, look up the cert first */
749
	if ($isref) {
750
		$cert = lookup_cert($crt);
751
		/* If it's not a valid cert, bail. */
752
		if (!(is_array($cert) && !empty($cert['crt'])))
753
			return "";
754
		$cert = $cert['crt'];
755
	} else {
756
		$cert = $crt;
757
	}
758
	$sub = cert_get_subject_array($cert);
759
	if (is_array($sub)) {
760
		foreach ($sub as $s) {
761
			if (strtoupper($s['a']) == "CN")
762
				return $s['v'];
763
		}
764
	}
765
	return "";
766
}
767

    
768
?>
(9-9/68)