Project

General

Profile

Download (17.5 KB) Statistics
| Branch: | Tag: | Revision:
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
function & lookup_ca($refid) {
38
	global $config;
39

    
40
	if (is_array($config['ca']))
41
		foreach ($config['ca'] as & $ca)
42
			if ($ca['refid'] == $refid)
43
				return $ca;
44

    
45
	return false;
46
}
47

    
48
function & lookup_ca_by_subject($subject) {
49
	global $config;
50

    
51
	if (is_array($config['ca']))
52
		foreach ($config['ca'] as & $ca)
53
		{
54
			$ca_subject = cert_get_subject($ca['crt']);
55
			if ($ca_subject == $subject)
56
				return $ca;
57
		}
58

    
59
	return false;
60
}
61

    
62
function & lookup_cert($refid) {
63
	global $config;
64

    
65
	if (is_array($config['cert']))
66
		foreach ($config['cert'] as & $cert)
67
			if ($cert['refid'] == $refid)
68
				return $cert;
69

    
70
	return false;
71
}
72

    
73
function & lookup_cert_by_name($name) {
74
	global $config;
75
	if (is_array($config['cert']))
76
		foreach ($config['cert'] as & $cert)
77
			if ($cert['descr'] == $name)
78
				return $cert;
79
}
80

    
81
function & lookup_crl($refid) {
82
	global $config;
83

    
84
	if (is_array($config['crl']))
85
		foreach ($config['crl'] as & $crl)
86
			if ($crl['refid'] == $refid)
87
				return $crl;
88

    
89
	return false;
90
}
91

    
92
function ca_chain_array(& $cert) {
93
	if($cert['caref']) {
94
		$chain = array();
95
		$crt = lookup_ca($cert['caref']);
96
		$chain[] = $crt;
97
		while ($crt) {
98
			$caref = $crt['caref'];
99
			if($caref)
100
				$crt = lookup_ca($caref);
101
			else
102
				$crt = false;
103
			if($crt)
104
				$chain[] = $crt;
105
		}
106
		return $chain;
107
	}
108
	return false;
109
}
110

    
111
function ca_chain(& $cert) {
112
	if($cert['caref']) {
113
		$ca = "";
114
		$cas = ca_chain_array($cert);
115
		if (is_array($cas))
116
			foreach ($cas as & $ca_cert)
117
			{
118
				$ca .= base64_decode($ca_cert['crt']);
119
				$ca .= "\n";
120
			}
121
		return $ca;
122
	}
123
	return "";
124
}
125

    
126
function ca_import(& $ca, $str, $key="", $serial=0) {
127
	global $config;
128

    
129
	$ca['crt'] = base64_encode($str);
130
	if (!empty($key))
131
		$ca['prv'] = base64_encode($key);
132
	if (!empty($serial))
133
		$ca['serial'] = $serial;
134
	$subject = cert_get_subject($str, false);
135
	$issuer = cert_get_issuer($str, false);
136
	
137
	// Find my issuer unless self-signed
138
	if($issuer <> $subject) {
139
		$issuer_crt =& lookup_ca_by_subject($issuer);
140
		if($issuer_crt)
141
			$ca['caref'] = $issuer_crt['refid'];
142
	}
143

    
144
	/* Correct if child certificate was loaded first */
145
	if (is_array($config['ca']))
146
		foreach ($config['ca'] as & $oca)
147
		{
148
			$issuer = cert_get_issuer($oca['crt']);
149
			if($ca['refid']<>$oca['refid'] && $issuer==$subject)
150
				$oca['caref'] = $ca['refid'];
151
		}
152
	if (is_array($config['cert']))
153
		foreach ($config['cert'] as & $cert)
154
		{
155
			$issuer = cert_get_issuer($cert['crt']);
156
			if($issuer==$subject)
157
				$cert['caref'] = $ca['refid'];
158
		}
159
	return true;
160
}
161

    
162
function ca_create(& $ca, $keylen, $lifetime, $dn) {
163

    
164
	$args = array(
165
		"x509_extensions" => "v3_ca",
166
		"digest_alg" => "sha1",
167
		"private_key_bits" => (int)$keylen,
168
		"private_key_type" => OPENSSL_KEYTYPE_RSA,
169
		"encrypt_key" => false);
170

    
171
	// generate a new key pair
172
	$res_key = openssl_pkey_new($args);
173
	if (!$res_key) return false;
174

    
175
	// generate a certificate signing request
176
	$res_csr = openssl_csr_new($dn, $res_key, $args);
177
	if (!$res_csr) return false;
178

    
179
	// self sign the certificate
180
	$res_crt = openssl_csr_sign($res_csr, null, $res_key, $lifetime, $args);
181
	if (!$res_crt) return false;
182

    
183
	// export our certificate data
184
	if (!openssl_pkey_export($res_key, $str_key) ||
185
	    !openssl_x509_export($res_crt, $str_crt))
186
		return false;
187

    
188
	// return our ca information
189
	$ca['crt'] = base64_encode($str_crt);
190
	$ca['prv'] = base64_encode($str_key);
191
	$ca['serial'] = 0;
192

    
193
	return true;
194
}
195

    
196
function ca_inter_create(& $ca, $keylen, $lifetime, $dn, $caref) {
197
	// Create Intermediate Certificate Authority
198
	$signing_ca =& lookup_ca($caref);
199
	if (!$signing_ca)
200
		return false;
201

    
202
	$signing_ca_res_crt = openssl_x509_read(base64_decode($signing_ca['crt']));
203
	$signing_ca_res_key = openssl_pkey_get_private(array(0 => base64_decode($signing_ca['prv']) , 1 => ""));
204
	if (!$signing_ca_res_crt || !$signing_ca_res_key) return false;
205
	$signing_ca_serial = ++$signing_ca['serial'];
206

    
207
	$args = array(
208
		"x509_extensions" => "v3_ca",
209
		"digest_alg" => "sha1",
210
		"private_key_bits" => (int)$keylen,
211
		"private_key_type" => OPENSSL_KEYTYPE_RSA,
212
		"encrypt_key" => false);
213

    
214
	// generate a new key pair
215
	$res_key = openssl_pkey_new($args);
216
	if (!$res_key) return false;
217

    
218
	// generate a certificate signing request
219
	$res_csr = openssl_csr_new($dn, $res_key, $args);
220
	if (!$res_csr) return false;
221

    
222
	// Sign the certificate
223
	$res_crt = openssl_csr_sign($res_csr, $signing_ca_res_crt, $signing_ca_res_key, $lifetime, $args, $signing_ca_serial);
224
	if (!$res_crt) return false;
225

    
226
	// export our certificate data
227
	if (!openssl_pkey_export($res_key, $str_key) ||
228
	    !openssl_x509_export($res_crt, $str_crt))
229
		return false;
230

    
231
	// return our ca information
232
	$ca['crt'] = base64_encode($str_crt);
233
	$ca['prv'] = base64_encode($str_key);
234
	$ca['serial'] = 0;
235

    
236
	return true;
237
}
238

    
239
function cert_import(& $cert, $crt_str, $key_str) {
240

    
241
	$cert['crt'] = base64_encode($crt_str);
242
	$cert['prv'] = base64_encode($key_str);
243

    
244
	$subject = cert_get_subject($crt_str, false);
245
	$issuer = cert_get_issuer($crt_str, false);
246
	
247
	// Find my issuer unless self-signed
248
	if($issuer <> $subject) {
249
		$issuer_crt =& lookup_ca_by_subject($issuer);
250
		if($issuer_crt)
251
			$cert['caref'] = $issuer_crt['refid'];
252
	}
253
	return true;
254
}
255

    
256
function cert_create(& $cert, $caref, $keylen, $lifetime, $dn, $type="user") {
257

    
258
	$ca =& lookup_ca($caref);
259
	if (!$ca)
260
		return false;
261

    
262
	$ca_str_crt = base64_decode($ca['crt']);
263
	$ca_str_key = base64_decode($ca['prv']);
264
	$ca_res_crt = openssl_x509_read($ca_str_crt);
265
	$ca_res_key = openssl_pkey_get_private(array(0 => $ca_str_key, 1 => ""));
266
	if(!$ca_res_key) return false;
267
	$ca_serial = ++$ca['serial'];
268

    
269
	switch ($type) {
270
		case "ca":
271
			$cert_type = "v3_ca";
272
			break;
273
		case "server":
274
			$cert_type = "server";
275
			break;
276
		default:
277
			$cert_type = "usr_cert";
278
			break;
279
	}
280

    
281
	$args = array(
282
		"x509_extensions" => $cert_type,
283
		"digest_alg" => "sha1",
284
		"private_key_bits" => (int)$keylen,
285
		"private_key_type" => OPENSSL_KEYTYPE_RSA,
286
		"encrypt_key" => false);
287

    
288
	// generate a new key pair
289
	$res_key = openssl_pkey_new($args);
290
	if(!$res_key) return false;
291

    
292
	// generate a certificate signing request
293
	$res_csr = openssl_csr_new($dn, $res_key, $args);
294
	if(!$res_csr) return false;
295

    
296
	// self sign the certificate
297
	$res_crt = openssl_csr_sign($res_csr, $ca_res_crt, $ca_res_key, $lifetime,
298
				 $args, $ca_serial);
299
	if(!$res_crt) return false;
300

    
301
	// export our certificate data
302
	if (!openssl_pkey_export($res_key, $str_key) ||
303
	    !openssl_x509_export($res_crt, $str_crt))
304
		return false;
305

    
306
	// return our certificate information
307
	$cert['caref'] = $caref;
308
	$cert['crt'] = base64_encode($str_crt);
309
	$cert['prv'] = base64_encode($str_key);
310
	$cert['type'] = $type;
311

    
312
	return true;
313
}
314

    
315
function csr_generate(& $cert, $keylen, $dn) {
316

    
317
	$args = array(
318
		"x509_extensions" => "v3_req",
319
		"digest_alg" => "sha1",
320
		"private_key_bits" => (int)$keylen,
321
		"private_key_type" => OPENSSL_KEYTYPE_RSA,
322
		"encrypt_key" => false);
323

    
324
	// generate a new key pair
325
	$res_key = openssl_pkey_new($args);
326
	if(!$res_key) return false;
327

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

    
332
	// export our request data
333
	if (!openssl_pkey_export($res_key, $str_key) ||
334
	    !openssl_csr_export($res_csr, $str_csr))
335
		return false;
336

    
337
	// return our request information
338
	$cert['csr'] = base64_encode($str_csr);
339
	$cert['prv'] = base64_encode($str_key);
340

    
341
	return true;
342
}
343

    
344
function csr_complete(& $cert, $str_crt) {
345

    
346
	// return our request information
347
	$cert['crt'] = base64_encode($str_crt);
348
	unset($cert['csr']);
349

    
350
	return true;
351
}
352

    
353
function csr_get_subject($str_crt, $decode = true) {
354

    
355
	if ($decode)
356
		$str_crt = base64_decode($str_crt);
357

    
358
	$components = openssl_csr_get_subject($str_crt);
359

    
360
	if (empty($components) || !is_array($components))
361
		return "unknown";
362

    
363
	ksort($components);
364
	foreach ($components as $a => $v) {
365
		if (!strlen($subject))
366
			$subject = "{$a}={$v}";
367
		else
368
			$subject = "{$a}={$v}, {$subject}";
369
	}
370

    
371
	return $subject;
372
}
373

    
374
function cert_get_subject($str_crt, $decode = true) {
375

    
376
	if ($decode)
377
		$str_crt = base64_decode($str_crt);
378

    
379
	$inf_crt = openssl_x509_parse($str_crt);
380
	$components = $inf_crt['subject'];
381

    
382
	if (empty($components) || !is_array($components))
383
		return "unknown";
384

    
385
	ksort($components);
386
	foreach ($components as $a => $v) {
387
		if (is_array($v)) {
388
			ksort($v);
389
			foreach ($v as $w) {
390
				$asubject = "{$a}={$w}";
391
				$subject = (strlen($subject)) ? "{$asubject}, {$subject}" : $asubject;
392
			}
393
		} else {
394
			$asubject = "{$a}={$v}";
395
			$subject = (strlen($subject)) ? "{$asubject}, {$subject}" : $asubject;
396
		}
397
	}
398

    
399
	return $subject;
400
}
401

    
402
function cert_get_subject_array($crt) {
403
	$str_crt = base64_decode($crt);
404
	$inf_crt = openssl_x509_parse($str_crt);
405
	$components = $inf_crt['subject'];
406

    
407
	if (!is_array($components))
408
		return;
409

    
410
	$subject_array = array();
411

    
412
	foreach($components as $a => $v)
413
		$subject_array[] = array('a' => $a, 'v' => $v);
414

    
415
	return $subject_array;
416
}
417

    
418
function cert_get_subject_hash($crt) {
419
	$str_crt = base64_decode($crt);
420
	$inf_crt = openssl_x509_parse($str_crt);
421
	return $inf_crt['subject'];
422
}
423

    
424
function cert_get_issuer($str_crt, $decode = true) {
425

    
426
	if ($decode)
427
		$str_crt = base64_decode($str_crt);
428

    
429
	$inf_crt = openssl_x509_parse($str_crt);
430
	$components = $inf_crt['issuer'];
431
	
432
	if (empty($components) || !is_array($components))
433
		return "unknown";
434

    
435
	ksort($components);
436
	foreach ($components as $a => $v) {
437
		if (!strlen($issuer))
438
			$issuer = "{$a}={$v}";
439
		else
440
			$issuer = "{$a}={$v}, {$issuer}";
441
	}
442

    
443
	return $issuer;
444
}
445

    
446
/* this function works on x509 (crt), rsa key (prv), and req(csr) */
447
function cert_get_modulus($str_crt, $decode = true, $type = "crt"){
448
	if ($decode)
449
		$str_crt = base64_decode($str_crt);
450

    
451
	$modulus = "";
452
	if ( in_array($type, array("crt", "prv", "csr")) ) {
453
			$type = str_replace( array("crt","prv","csr"), array("x509","rsa","req"), $type);
454
			$modulus = exec("echo \"{$str_crt}\" | openssl {$type} -noout -modulus");
455
	}
456
	return $modulus;
457
}
458
function csr_get_modulus($str_crt, $decode = true){
459
	return cert_get_modulus($str_crt, $decode, "csr");
460
}
461
function prv_get_modulus($str_crt, $decode = true){
462
	return cert_get_modulus($str_crt, $decode, "prv");
463
}
464

    
465
function is_user_cert($certref) {
466
	global $config;
467
	if (!is_array($config['system']['user']))
468
		return;
469
	foreach ($config['system']['user'] as $user) {
470
		if (!is_array($user['cert']))
471
			continue;
472
		foreach ($user['cert'] as $cert) {
473
			if ($certref == $cert)
474
				return true;
475
		}
476
	}
477
	return false;
478
}
479

    
480
function is_openvpn_server_cert($certref) {
481
	global $config;
482
	if (!is_array($config['openvpn']['openvpn-server']))
483
		return;
484
	foreach ($config['openvpn']['openvpn-server'] as $ovpns) {
485
		if ($ovpns['certref'] == $certref)
486
			return true;
487
	}
488
	return false;
489
}
490

    
491
function is_openvpn_client_cert($certref) {
492
	global $config;
493
	if (!is_array($config['openvpn']['openvpn-client']))
494
		return;
495
	foreach ($config['openvpn']['openvpn-client'] as $ovpnc) {
496
		if ($ovpnc['certref'] == $certref)
497
			return true;
498
	}
499
	return false;
500
}
501

    
502
function is_ipsec_cert($certref) {
503
	global $config;
504
	if (!is_array($config['ipsec']['phase1']))
505
		return;
506
	foreach ($config['ipsec']['phase1'] as $ipsec) {
507
		if ($ipsec['certref'] == $certref)
508
			return true;
509
	}
510
	return false;
511
}
512

    
513
function is_webgui_cert($certref) {
514
	global $config;
515
	if (($config['system']['webgui']['ssl-certref'] == $certref)
516
		&& ($config['system']['webgui']['protocol'] != "http"))
517
		return true;
518
}
519

    
520
function cert_in_use($certref) {
521
	return (is_webgui_cert($certref) ||
522
		is_user_cert($certref) ||
523
		is_openvpn_server_cert($certref) ||
524
		is_openvpn_client_cert($certref) ||
525
		is_ipsec_cert($certref));
526
}
527

    
528
/*
529
CRL code is a *WORK IN PROGRESS* do not try to use these functions yet.
530

    
531
OpenSSL CRL status code constants.
532
OCSP_REVOKED_STATUS_NOSTATUS
533
OCSP_REVOKED_STATUS_UNSPECIFIED
534
OCSP_REVOKED_STATUS_KEYCOMPROMISE
535
OCSP_REVOKED_STATUS_CACOMPROMISE
536
OCSP_REVOKED_STATUS_AFFILIATIONCHANGED
537
OCSP_REVOKED_STATUS_SUPERSEDED
538
OCSP_REVOKED_STATUS_CESSATIONOFOPERATION
539
OCSP_REVOKED_STATUS_CERTIFICATEHOLD
540
OCSP_REVOKED_STATUS_REMOVEFROMCRL
541
*/
542

    
543
$openssl_crl_status = array(
544
	OCSP_REVOKED_STATUS_NOSTATUS              => "No Status (default)",
545
	OCSP_REVOKED_STATUS_UNSPECIFIED           => "Unspecified",
546
	OCSP_REVOKED_STATUS_KEYCOMPROMISE         => "Key Compromise",
547
	OCSP_REVOKED_STATUS_CACOMPROMISE          => "CA Compromise",
548
	OCSP_REVOKED_STATUS_AFFILIATIONCHANGED    => "Affiliation Changed",
549
	OCSP_REVOKED_STATUS_SUPERSEDED            => "Superseded",
550
	OCSP_REVOKED_STATUS_CESSATIONOFOPERATION  => "Cessation of Operation",
551
	OCSP_REVOKED_STATUS_CERTIFICATEHOLD       => "Certificate Hold"
552
);
553

    
554
function crl_create(& $crl, $caref, $name, $serial=0, $lifetime=9999) {
555
	global $config;
556
	$ca =& lookup_ca($caref);
557
	if (!$ca)
558
		return false;
559
	$crl['descr'] = $name;
560
	$crl['caref'] = $caref;
561
	$crl['serial'] = $serial;
562
	$crl['lifetime'] = $lifetime;
563
	$crl['cert'] = array();
564
	$crl_res = crl_update($crl);
565
	$config['crl'][] = $crl;
566
	return $crl_res;
567
}
568

    
569
function crl_update(& $crl) {
570
	global $config;
571
	$ca =& lookup_ca($crl['caref']);
572
	if (!$ca)
573
		return false;
574
	// If we have text but no certs, it was imported and cannot be updated.
575
	if (($crl["method"] != "internal") && (!empty($crl['text']) && empty($crl['cert'])))
576
		return false;
577
	$crl['serial']++;
578
	$ca_str_crt = base64_decode($ca['crt']);
579
	$ca_str_key = base64_decode($ca['prv']);
580
	$crl_res = openssl_crl_new($ca_str_crt, $crl['serial'], $crl['lifetime']);
581
	if (is_array($crl['cert']) && (count($crl['cert']) > 0)) {
582
		foreach ($crl['cert'] as $cert) {
583
			openssl_crl_revoke_cert($crl_res, base64_decode($cert["crt"]), $cert["revoke_time"], $cert["reason"]);
584
		}
585
	}
586
	openssl_crl_export($crl_res, $crl_text, $ca_str_key);
587
	$crl['text'] = base64_encode($crl_text);
588
	return $crl_res;
589
}
590

    
591
function cert_revoke($cert, & $crl, $reason=OCSP_REVOKED_STATUS_UNSPECIFIED) {
592
	global $config;
593
	if (is_cert_revoked($cert, $crl['refid']))
594
		return true;
595
	// If we have text but no certs, it was imported and cannot be updated.
596
	if (!is_crl_internal($crl))
597
		return false;
598
	$cert["reason"] = $reason;
599
	$cert["revoke_time"] = time();
600
	$crl["cert"][] = $cert;
601
	crl_update($crl);
602
	return true;
603
}
604

    
605
function cert_unrevoke($cert, & $crl) {
606
	global $config;
607
	if (!is_crl_internal($crl))
608
		return false;
609
	foreach ($crl['cert'] as $id => $rcert) {
610
		if (($rcert['refid'] == $cert['refid']) || ($rcert['descr'] == $cert['descr'])) {
611
			unset($crl['cert'][$id]);
612
			if (count($crl['cert']) == 0) {
613
				// Protect against accidentally switching the type to imported, for older CRLs
614
				if (!isset($crl['method']))
615
					$crl['method'] = "internal";
616
				crl_update($crl);
617
			} else
618
				crl_update($crl);
619
			return true;
620
		}
621
	}
622
	return false;
623
}
624

    
625
function is_cert_revoked($cert, $crlref = "") {
626
	global $config;
627
	if (!is_array($config['crl']))
628
		return false;
629

    
630
	if (!empty($crlref)) {
631
		$crl = lookup_crl($crlref);
632
		if (!is_array($crl['cert']))
633
			return false;
634
		foreach ($crl['cert'] as $rcert) {
635
			if (($rcert['refid'] == $cert['refid']) || ($rcert['descr'] == $cert['descr']))
636
				return true;
637
		}
638
	} else {
639
		foreach ($config['crl'] as $crl) {
640
			if (!is_array($crl['cert']))
641
				continue;
642
			foreach ($crl['cert'] as $rcert) {
643
				if (($rcert['refid'] == $cert['refid']) || ($rcert['descr'] == $cert['descr']))
644
					return true;
645
			}
646
		}
647
	}
648
	return false;
649
}
650

    
651
function is_openvpn_server_crl($crlref) {
652
	global $config;
653
	if (!is_array($config['openvpn']['openvpn-server']))
654
		return;
655
	foreach ($config['openvpn']['openvpn-server'] as $ovpns) {
656
		if (!empty($ovpns['crlref']) && ($ovpns['crlref'] == $crlref))
657
			return true;
658
	}
659
	return false;
660
}
661

    
662
// Keep this general to allow for future expansion. See cert_in_use() above.
663
function crl_in_use($crlref) {
664
	return (is_openvpn_server_crl($crlref));
665
}
666

    
667
function is_crl_internal($crl) {
668
	return (!(!empty($crl['text']) && empty($crl['cert'])) || ($crl["method"] == "internal"));
669
}
670

    
671
function cert_get_cn($crt, $isref = false) {
672
	/* If this is a certref, not an actual cert, look up the cert first */
673
	if ($isref) {
674
		$cert = lookup_cert($crt);
675
		/* If it's not a valid cert, bail. */
676
		if (!(is_array($cert) && !empty($cert['crt'])))
677
			return "";
678
		$cert = $cert['crt'];
679
	} else {
680
		$cert = $crt;
681
	}
682
	$sub = cert_get_subject_array($cert);
683
	if (is_array($sub)) {
684
		foreach ($sub as $s) {
685
			if (strtoupper($s['a']) == "CN")
686
				return $s['v'];
687
		}
688
	}
689
	return "";
690
}
691

    
692
?>
(8-8/62)