WvStreams
wvx509.cc
1/*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2005 Net Integration Technologies, Inc.
4 *
5 * X.509 certificate management classes.
6 */
7#include "wvx509.h"
8#include "wvcrl.h"
9#include "wvsslhacks.h"
10#include "wvcrypto.h"
11#include "wvstringlist.h"
12#include "wvbase64.h"
13#include "wvstrutils.h"
14#include "wvautoconf.h"
15
16#include <openssl/pem.h>
17#include <openssl/x509v3.h>
18#include <openssl/err.h>
19#include <openssl/sha.h>
20#include <openssl/ssl.h>
21
22// enable this to add some extra debugging trace messages (this can be VERY
23// verbose)
24#if 0
25# define TRACE(x, y...) debug(x, ## y);
26#else
27#ifndef _MSC_VER
28# define TRACE(x, y...)
29#else
30# define TRACE
31#endif
32#endif
33
34// helper method to let us return and warn gracefully when getting/setting an
35// element in a null certificate
36static const char * warning_str_set
37 = "Tried to set %s, but certificate not ok.\n";
38static const char * warning_str_get
39 = "Tried to get %s, but certificate not ok.\n";
40#define CHECK_CERT_EXISTS_SET(x) \
41 if (!cert) { \
42 debug(WvLog::Warning, warning_str_set, x); \
43 return; \
44 }
45#define CHECK_CERT_EXISTS_GET(x, y) \
46 if (!cert) { \
47 debug(WvLog::Warning, warning_str_get, x); \
48 return y; \
49 }
50
51
55
56static int ssl_init_count = 0;
57
58#if !HAVE_OPENSSL_POLICY_MAPPING
59
60// HACK: old versions of OpenSSL can't handle ERR_free_strings() being called
61// more than once in the same process; the next wvssl_init won't work. So
62// let's make sure to make a global variable that holds the refcount at 1
63// even when all the objects go away, then clean it up at exit.
64class WvSSL_Stupid_Refcount
65{
66public:
67 WvSSL_Stupid_Refcount()
68 {
69 wvssl_init();
70 }
71
72 ~WvSSL_Stupid_Refcount()
73 {
74 wvssl_free();
75 }
76};
77
78WvSSL_Stupid_Refcount wvssl_stupid_refcount;
79
80#endif // !HAVE_OPENSSL_POLICY_MAPPING
81
82
83void wvssl_init()
84{
85 if (!ssl_init_count)
86 {
87 SSL_library_init();
88 SSL_load_error_strings();
89 ERR_load_BIO_strings();
90 ERR_load_crypto_strings();
91 OpenSSL_add_all_algorithms();
92 OpenSSL_add_all_ciphers();
93 OpenSSL_add_all_digests();
94 }
95
96 ssl_init_count++;
97}
98
99
100void wvssl_free()
101{
102 assert(ssl_init_count >= 1);
103 if (ssl_init_count >= 1)
104 ssl_init_count--;
105
106 if (!ssl_init_count)
107 {
108 ERR_free_strings();
109 EVP_cleanup();
110 }
111}
112
113
114WvString wvssl_errstr()
115{
116 char buf[256];
117 ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
118 buf[sizeof(buf)-1] = 0;
119 return buf;
120}
121
122
123WvX509::WvX509(X509 *_cert)
124 : debug("X509", WvLog::Debug5)
125{
126 wvssl_init();
127 cert = _cert;
128}
129
130
132 : debug("X509", WvLog::Debug5)
133{
134 wvssl_init();
135 cert = NULL;
136}
137
138
140 : debug("X509", WvLog::Debug5)
141{
142 wvssl_init();
143 if (x509.cert)
144 cert = X509_dup(x509.cert);
145 else
146 cert = NULL;
147}
148
149
151{
152 TRACE("Deleting.\n");
153
154 if (cert)
155 X509_free(cert);
156
157 wvssl_free();
158}
159
160
161
162// The people who designed this garbage should be shot!
163// Support old versions of openssl...
164#ifndef NID_domainComponent
165#define NID_domainComponent 391
166#endif
167
168#ifndef NID_Domain
169#define NID_Domain 392
170#endif
171
172
173// returns some approximation of the server's fqdn, or an empty string.
174static WvString set_name_entry(X509_NAME *name, WvStringParm dn)
175{
176 WvString fqdn(""), force_fqdn("");
177 X509_NAME_ENTRY *ne = NULL;
178 int count = 0, nid;
179
180 WvStringList l;
181 l.split(dn, ",");
182
183 // dn is of the form: c=ca,o=foo organization,dc=foo,dc=com
184 // (ie. name=value pairs separated by commas)
185 WvStringList::Iter i(l);
186 for (i.rewind(); i.next(); )
187 {
188 WvString s(*i), sid;
189 char *cptr, *value;
190
191 cptr = s.edit();
192 value = strchr(cptr, '=');
193 if (value)
194 *value++ = 0;
195 else
196 value = (char*)"NULL";
197
198 sid = strlwr(trim_string(cptr));
199
200 if (sid == "c")
201 nid = NID_countryName;
202 else if (sid == "st")
203 nid = NID_stateOrProvinceName;
204 else if (sid == "l")
205 nid = NID_localityName;
206 else if (sid == "o")
207 nid = NID_organizationName;
208 else if (sid == "ou")
209 nid = NID_organizationalUnitName;
210 else if (sid == "cn")
211 {
212 nid = NID_commonName;
213 force_fqdn = value;
214 }
215 else if (sid == "dc")
216 {
217 nid = NID_domainComponent;
218 if (!!fqdn)
219 fqdn.append(".");
220 fqdn.append(value);
221 }
222 else if (sid == "domain")
223 {
224 nid = NID_Domain;
225 force_fqdn = value;
226 }
227 else if (sid == "email")
228 nid = NID_pkcs9_emailAddress;
229 else
230 nid = NID_domainComponent;
231
232 // Sometimes we just want to parse dn into fqdn.
233 if (name == NULL)
234 continue;
235
236 if (!ne)
237 ne = X509_NAME_ENTRY_create_by_NID(NULL, nid,
238 V_ASN1_APP_CHOOSE, (unsigned char *)value, -1);
239 else
240 X509_NAME_ENTRY_create_by_NID(&ne, nid,
241 V_ASN1_APP_CHOOSE, (unsigned char *)value, -1);
242 if (!ne)
243 continue;
244
245 X509_NAME_add_entry(name, ne, count++, 0);
246 }
247
248 X509_NAME_ENTRY_free(ne);
249
250 if (!!force_fqdn)
251 return force_fqdn;
252
253 return fqdn;
254}
255
256
257WvRSAKey *WvX509::get_rsa_pub() const
258{
259 EVP_PKEY *pkcert = X509_get_pubkey(cert);
260 RSA *certrsa = EVP_PKEY_get1_RSA(pkcert);
261 EVP_PKEY_free(pkcert);
262 return new WvRSAKey(certrsa, false);
263}
264
265
266WvString WvX509::certreq(WvStringParm subject, const WvRSAKey &rsa)
267{
268 WvLog debug("X509::certreq", WvLog::Debug5);
269
270 EVP_PKEY *pk = NULL;
271 X509_NAME *name = NULL;
272 X509_REQ *certreq = NULL;
273
274 // double check RSA key
275 if (rsa.isok())
276 debug("RSA Key is fine.\n");
277 else
278 {
279 debug(WvLog::Warning, "RSA Key is bad");
280 return WvString::null;
281 }
282
283 if ((pk=EVP_PKEY_new()) == NULL)
284 {
285 debug(WvLog::Warning,
286 "Error creating key handler for new certificate");
287 return WvString::null;
288 }
289
290 if ((certreq=X509_REQ_new()) == NULL)
291 {
292 debug(WvLog::Warning, "Error creating new PKCS#10 object");
293 EVP_PKEY_free(pk);
294 return WvString::null;
295 }
296
297 if (!EVP_PKEY_set1_RSA(pk, rsa.rsa))
298 {
299 debug(WvLog::Warning, "Error adding RSA keys to certificate");
300 X509_REQ_free(certreq);
301 EVP_PKEY_free(pk);
302 return WvString::null;
303 }
304
305 X509_REQ_set_version(certreq, 0); /* version 1 */
306
307 X509_REQ_set_pubkey(certreq, pk);
308
309 debug("Creating Certificate request for %s\n", subject);
310 if ((name = X509_NAME_new()) == NULL)
311 {
312 debug(WvLog::Warning, "Error creating X509_NAME");
313 X509_REQ_free(certreq);
314 EVP_PKEY_free(pk);
315 return WvString::null;
316 }
317 set_name_entry(name, subject);
318 X509_REQ_set_subject_name(certreq, name);
319 X509_NAME_free(name);
320 char *sub_name = X509_NAME_oneline(X509_REQ_get_subject_name(certreq),
321 0, 0);
322 debug("SubjectDN: %s\n", sub_name);
323 OPENSSL_free(sub_name);
324
325 if (!X509_REQ_sign(certreq, pk, EVP_sha1()))
326 {
327 debug(WvLog::Warning, "Could not self sign the request");
328 X509_REQ_free(certreq);
329 EVP_PKEY_free(pk);
330 return WvString::null;
331 }
332
333 int verify_result = X509_REQ_verify(certreq, pk);
334 if (verify_result == 0 || verify_result == -1)
335 {
336 debug(WvLog::Warning, "Self signed request failed");
337 X509_REQ_free(certreq);
338 EVP_PKEY_free(pk);
339 return WvString::null;
340 }
341 else
342 {
343 debug("Self Signed Certificate Request verifies OK!\n");
344 }
345
346 // Horribly involuted hack to get around the fact that the
347 // OpenSSL people are too braindead to have a PEM_write function
348 // that returns a char *
349 WvDynBuf retval;
350 BIO *bufbio = BIO_new(BIO_s_mem());
351 BUF_MEM *bm;
352
353 PEM_write_bio_X509_REQ(bufbio, certreq);
354 BIO_get_mem_ptr(bufbio, &bm);
355 retval.put(bm->data, bm->length);
356
357 X509_REQ_free(certreq);
358 EVP_PKEY_free(pk);
359 BIO_free(bufbio);
360
361 return retval.getstr();
362}
363
364
365bool WvX509::validate(WvX509 *cacert) const
366{
367 if (cert == NULL)
368 {
369 debug(WvLog::Warning, "Tried to validate certificate against CA, but "
370 "certificate is blank!\n");
371 return false;
372 }
373
374 bool retval = true;
375
376 // Check and make sure that the certificate is still valid
377 if (X509_cmp_current_time(X509_get_notAfter(cert)) < 0)
378 {
379 debug("Certificate has expired.\n");
380 retval = false;
381 }
382
383 if (X509_cmp_current_time(X509_get_notBefore(cert)) > 0)
384 {
385 debug("Certificate is not yet valid.\n");
386 retval = false;
387 }
388
389 if (cacert)
390 {
391 retval &= signedbyca(*cacert);
392 retval &= issuedbyca(*cacert);
393 }
394
395 return retval;
396}
397
398
399bool WvX509::signedbyca(WvX509 &cacert) const
400{
401 if (!cert || !cacert.cert)
402 {
403 debug(WvLog::Warning, "Tried to determine if certificate was signed "
404 "by CA, but either client or CA certificate (or both) are "
405 "blank.\n");
406 return false;
407 }
408
409 EVP_PKEY *pkey = X509_get_pubkey(cacert.cert);
410 int result = X509_verify(cert, pkey);
411 EVP_PKEY_free(pkey);
412
413 if (result < 0)
414 {
415 debug("Can't determine if we were signed by CA %s: %s\n",
416 cacert.get_subject(), wvssl_errstr());
417 return false;
418 }
419 bool issigned = (result > 0);
420
421 debug("Certificate was%s signed by CA %s.\n", issigned ? "" : " NOT",
422 cacert.get_subject());
423
424 return issigned;
425}
426
427
428bool WvX509::issuedbyca(WvX509 &cacert) const
429{
430 if (!cert || !cacert.cert)
431 {
432 debug(WvLog::Warning, "Tried to determine if certificate was issued "
433 "by CA, but either client or CA certificate (or both) are "
434 "blank.\n");
435 return false;
436 }
437
438 int ret = X509_check_issued(cacert.cert, cert);
439 debug("issuedbyca: %s==X509_V_OK(%s)\n", ret, X509_V_OK);
440 if (ret != X509_V_OK)
441 return false;
442
443 return true;
444}
445
446
448{
449 WvDynBuf retval;
450 encode(mode, retval);
451 return retval.getstr();
452}
453
454
455void WvX509::encode(const DumpMode mode, WvBuf &buf) const
456{
457 if (mode == CertFileDER || mode == CertFilePEM)
458 return; // file modes are no ops with encode
459
460 if (!cert)
461 {
462 debug(WvLog::Warning, "Tried to encode certificate, but certificate "
463 "is blank!\n");
464 return;
465 }
466
467 debug("Encoding X509 certificate.\n");
468
469 if (mode == CertHex)
470 {
471 size_t size;
472 unsigned char *keybuf, *iend;
473 WvString enccert;
474
475 size = i2d_X509(cert, NULL);
476 iend = keybuf = new unsigned char[size];
477 i2d_X509(cert, &iend);
478
479 enccert.setsize(size * 2 +1);
480 ::hexify(enccert.edit(), keybuf, size);
481
482 deletev keybuf;
483 buf.putstr(enccert);
484 }
485 else
486 {
487 BIO *bufbio = BIO_new(BIO_s_mem());
488 BUF_MEM *bm;
489
490 if (mode == CertPEM)
491 PEM_write_bio_X509(bufbio, cert);
492 else if (mode == CertDER)
493 i2d_X509_bio(bufbio, cert);
494 else
495 debug(WvLog::Warning, "Tried to encode certificate with unknown "
496 "mode!\n");
497
498 BIO_get_mem_ptr(bufbio, &bm);
499 buf.put(bm->data, bm->length);
500 BIO_free(bufbio);
501 }
502}
503
504
505void WvX509::decode(const DumpMode mode, WvStringParm str)
506{
507 if (cert)
508 {
509 debug("Replacing an already existant X509 certificate.\n");
510 X509_free(cert);
511 cert = NULL;
512 }
513
514 if (mode == CertFileDER)
515 {
516 BIO *bio = BIO_new(BIO_s_file());
517
518 if (BIO_read_filename(bio, str.cstr()) <= 0)
519 {
520 debug(WvLog::Warning, "Open '%s': %s\n", str, wvssl_errstr());
521 BIO_free(bio);
522 return;
523 }
524
525 if (!(cert = d2i_X509_bio(bio, NULL)))
526 debug(WvLog::Warning, "Import DER from '%s': %s\n",
527 str, wvssl_errstr());
528
529 BIO_free(bio);
530 return;
531 }
532 else if (mode == CertFilePEM)
533 {
534 FILE *fp = fopen(str, "rb");
535 if (!fp)
536 {
537 int errnum = errno;
538 debug("Open '%s': %s\n", str, strerror(errnum));
539 return;
540 }
541
542 if (!(cert = PEM_read_X509(fp, NULL, NULL, NULL)))
543 debug(WvLog::Warning, "Import PEM from '%s': %s\n",
544 str, wvssl_errstr());
545
546 fclose(fp);
547 return;
548 }
549 else if (mode == CertHex)
550 {
551 int hexbytes = str.len();
552 int bufsize = hexbytes/2;
553 unsigned char *certbuf = new unsigned char[bufsize];
554 unsigned char *cp = certbuf;
555 X509 *tmpcert;
556
557 ::unhexify(certbuf, str);
558 tmpcert = cert = X509_new();
559 cert = wv_d2i_X509(&tmpcert, &cp, bufsize);
560 delete[] certbuf;
561 return;
562 }
563
564 // we use the buffer decode functions for everything else
565 WvDynBuf buf;
566 buf.putstr(str);
567 decode(mode, buf);
568}
569
570
571void WvX509::decode(const DumpMode mode, WvBuf &encoded)
572{
573 if (cert)
574 {
575 debug("Replacing an already existant X509 certificate.\n");
576 X509_free(cert);
577 cert = NULL;
578 }
579
580 if (mode == CertHex || mode == CertFileDER || mode == CertFilePEM)
581 decode(mode, encoded.getstr());
582 else
583 {
584 BIO *membuf = BIO_new(BIO_s_mem());
585 BIO_write(membuf, encoded.get(encoded.used()), encoded.used());
586
587 if (mode == CertPEM)
588 cert = PEM_read_bio_X509(membuf, NULL, NULL, NULL);
589 else if (mode == CertDER)
590 cert = d2i_X509_bio(membuf, NULL);
591 else
592 debug(WvLog::Warning, "Tried to decode certificate with unknown "
593 "mode!\n");
594
595 BIO_free_all(membuf);
596 }
597}
598
599
601{
602 CHECK_CERT_EXISTS_GET("issuer", WvString::null);
603
604 char *name = X509_NAME_oneline(X509_get_issuer_name(cert),0,0);
605 WvString retval(name);
606 OPENSSL_free(name);
607 return retval;
608}
609
610
611void WvX509::set_issuer(WvStringParm issuer)
612{
613 CHECK_CERT_EXISTS_SET("issuer");
614
615 X509_NAME *name;
616 if ((name = X509_NAME_new()) == NULL)
617 return;
618 set_name_entry(name, issuer);
619 X509_set_issuer_name(cert, name);
620 X509_NAME_free(name);
621}
622
623
624void WvX509::set_issuer(const WvX509 &cacert)
625{
626 CHECK_CERT_EXISTS_SET("issuer");
627
628 const X509_NAME *casubj = X509_get_subject_name(cacert.cert);
629 X509_set_issuer_name(cert, casubj);
630}
631
632
634{
635 CHECK_CERT_EXISTS_GET("subject", WvString::null);
636
637 char *name = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
638 WvString retval(name);
639 OPENSSL_free(name);
640 return retval;
641}
642
643
644void WvX509::set_subject(WvStringParm subject)
645{
646 CHECK_CERT_EXISTS_SET("subject");
647
648 X509_NAME *name;
649 if ((name = X509_NAME_new()) == NULL)
650 return;
651 set_name_entry(name, subject);
652 X509_set_subject_name(cert, name);
653 X509_NAME_free(name);
654}
655
656
657void WvX509::set_subject(const X509_NAME *name)
658{
659 CHECK_CERT_EXISTS_SET("subject");
660
661 X509_set_subject_name(cert, name);
662}
663
664
666{
667 CHECK_CERT_EXISTS_SET("pubkey");
668
669 EVP_PKEY *pk = EVP_PKEY_new();
670 assert(pk);
671
672 // Assign RSA Key from WvRSAKey into stupid package that OpenSSL needs
673 if (!EVP_PKEY_set1_RSA(pk, _rsa.rsa))
674 {
675 debug("Error adding RSA keys to certificate.\n");
676 return;
677 }
678
679 X509_set_pubkey(cert, pk);
680
681 EVP_PKEY_free(pk);
682}
683
684
685
686void WvX509::set_nsserver(WvStringParm servername)
687{
688 CHECK_CERT_EXISTS_SET("nsserver");
689
690 WvString fqdn;
691
692 // FQDN cannot have a = in it, therefore it
693 // must be a distinguished name :)
694 if (strchr(servername, '='))
695 fqdn = set_name_entry(NULL, servername);
696 else
697 fqdn = servername;
698
699 if (!fqdn)
700 fqdn = "null.noname.null";
701
702 debug("Setting Netscape SSL server name extension to '%s'.\n", fqdn);
703
704 // Add in the netscape-specific server extension
705 set_extension(NID_netscape_cert_type, "server");
706 set_extension(NID_netscape_ssl_server_name, fqdn);
707}
708
709
711{
712 return get_extension(NID_netscape_ssl_server_name);
713}
714
715
717{
718 CHECK_CERT_EXISTS_GET("serial", WvString::null);
719
720 BIGNUM *bn = BN_new();
721 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), bn);
722 char * c;
723 if (hex)
724 c = BN_bn2hex(bn);
725 else
726 c = BN_bn2dec(bn);
727 WvString ret("%s", c);
728 OPENSSL_free(c);
729 BN_free(bn);
730 return ret;
731}
732
733
735{
736 CHECK_CERT_EXISTS_SET("version");
737
738 X509_set_version(cert, 0x2);
739}
740
741
742void WvX509::set_serial(long serial)
743{
744 CHECK_CERT_EXISTS_SET("serial");
745
746 ASN1_INTEGER_set(X509_get_serialNumber(cert), serial);
747}
748
749
751{
752 return get_extension(NID_crl_distribution_points);
753}
754
755
756void WvX509::set_lifetime(long seconds)
757{
758 CHECK_CERT_EXISTS_SET("lifetime");
759
760 // Set the NotBefore time to now.
761 X509_gmtime_adj(X509_get_notBefore(cert), 0);
762
763 // Now + 10 years... should be shorter, but since we don't currently
764 // have a set of routines to refresh the certificates, make it
765 // REALLY long.
766 X509_gmtime_adj(X509_get_notAfter(cert), seconds);
767}
768
769
770void WvX509::set_key_usage(WvStringParm values)
771{
772 set_extension(NID_key_usage, values);
773}
774
775
777{
778 return get_extension(NID_key_usage);
779}
780
781
782void WvX509::set_ext_key_usage(WvStringParm values)
783{
784 set_extension(NID_ext_key_usage, values);
785}
786
787
789{
790 return get_extension(NID_ext_key_usage);
791}
792
793
795{
796 return get_extension(NID_subject_alt_name);
797}
798
799
800bool WvX509::get_basic_constraints(bool &ca, int &pathlen) const
801{
802 CHECK_CERT_EXISTS_GET("basic constraints", false);
803
804 BASIC_CONSTRAINTS *constraints = NULL;
805 int i;
806
807 constraints = static_cast<BASIC_CONSTRAINTS *>
808 (X509_get_ext_d2i(cert, NID_basic_constraints, &i, NULL));
809 if (constraints)
810 {
811 ca = constraints->ca;
812 if (constraints->pathlen)
813 {
814 if ((ASN1_STRING_type(constraints->pathlen) == V_ASN1_NEG_INTEGER) || !ca)
815 {
816 debug("Path length type not valid when getting basic "
817 "constraints.\n");
818 BASIC_CONSTRAINTS_free(constraints);
819 pathlen = 0;
820 return false;
821 }
822
823 pathlen = ASN1_INTEGER_get(constraints->pathlen);
824 }
825 else
826 pathlen = (-1);
827
828 BASIC_CONSTRAINTS_free(constraints);
829 return true;
830 }
831
832 debug("Basic constraints extension not present.\n");
833 return false;
834}
835
836
837void WvX509::set_basic_constraints(bool ca, int pathlen)
838{
839 CHECK_CERT_EXISTS_SET("basic constraints");
840
841 BASIC_CONSTRAINTS *constraints = BASIC_CONSTRAINTS_new();
842
843 constraints->ca = static_cast<int>(ca);
844 if (pathlen != (-1))
845 {
846 ASN1_INTEGER *i = ASN1_INTEGER_new();
847 ASN1_INTEGER_set(i, pathlen);
848 constraints->pathlen = i;
849 }
850
851 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_basic_constraints, 0,
852 constraints);
853 while (int idx = X509_get_ext_by_NID(cert, NID_basic_constraints, 0) >= 0)
854 {
855 debug("Found extension at idx %s\n", idx);
856 X509_EXTENSION *tmpex = X509_delete_ext(cert, idx);
857 X509_EXTENSION_free(tmpex);
858 }
859
860 X509_add_ext(cert, ex, NID_basic_constraints);
861 X509_EXTENSION_free(ex);
862 BASIC_CONSTRAINTS_free(constraints);
863}
864
865
866/*
867 * These functions are optional to the API. If OpenSSL doesn't support them,
868 * we simply won't include them here, and apps that need them won't compile.
869 */
870#ifdef HAVE_OPENSSL_POLICY_MAPPING
871
872bool WvX509::get_policy_constraints(int &require_explicit_policy,
873 int &inhibit_policy_mapping) const
874{
875 CHECK_CERT_EXISTS_GET("policy constraints", false);
876
877 POLICY_CONSTRAINTS *constraints = NULL;
878 int i;
879
880 constraints = static_cast<POLICY_CONSTRAINTS *>(X509_get_ext_d2i(
881 cert, NID_policy_constraints,
882 &i, NULL));
883 if (constraints)
884 {
885 if (constraints->requireExplicitPolicy)
886 require_explicit_policy = ASN1_INTEGER_get(
887 constraints->requireExplicitPolicy);
888 else
889 require_explicit_policy = (-1);
890
891 if (constraints->inhibitPolicyMapping)
892 inhibit_policy_mapping = ASN1_INTEGER_get(
893 constraints->inhibitPolicyMapping);
894 else
895 inhibit_policy_mapping = (-1);
896 POLICY_CONSTRAINTS_free(constraints);
897 return true;
898 }
899
900 return false;
901}
902
903
904void WvX509::set_policy_constraints(int require_explicit_policy,
905 int inhibit_policy_mapping)
906{
907 CHECK_CERT_EXISTS_SET("policy constraints");
908
909 POLICY_CONSTRAINTS *constraints = POLICY_CONSTRAINTS_new();
910
911 ASN1_INTEGER *i = ASN1_INTEGER_new();
912 ASN1_INTEGER_set(i, require_explicit_policy);
913 constraints->requireExplicitPolicy = i;
914 i = ASN1_INTEGER_new();
915 ASN1_INTEGER_set(i, inhibit_policy_mapping);
916 constraints->inhibitPolicyMapping = i;
917
918 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_policy_constraints, 0,
919 constraints);
920 X509_add_ext(cert, ex, -1);
921 X509_EXTENSION_free(ex);
922 POLICY_CONSTRAINTS_free(constraints);
923}
924
925
926bool WvX509::get_policy_mapping(PolicyMapList &list) const
927{
928 CHECK_CERT_EXISTS_GET("policy mapping", false);
929
930 POLICY_MAPPINGS *mappings = NULL;
931 POLICY_MAPPING *map = NULL;
932 int i;
933
934 mappings = static_cast<POLICY_MAPPINGS *>(X509_get_ext_d2i(
935 cert, NID_policy_mappings,
936 &i, NULL));
937 if (!mappings)
938 return false;
939
940 const int POLICYID_MAXLEN = 80;
941 char tmp1[80];
942 char tmp2[80];
943 for(int j = 0; j < sk_POLICY_MAPPING_num(mappings); j++)
944 {
945 map = sk_POLICY_MAPPING_value(mappings, j);
946 OBJ_obj2txt(tmp1, POLICYID_MAXLEN, map->issuerDomainPolicy, true);
947 OBJ_obj2txt(tmp2, POLICYID_MAXLEN, map->subjectDomainPolicy, true);
948 list.append(new PolicyMap(tmp1, tmp2), true);
949 }
950
951 sk_POLICY_MAPPING_pop_free(mappings, POLICY_MAPPING_free);
952
953 return true;
954}
955
956
957void WvX509::set_policy_mapping(PolicyMapList &list)
958{
959 CHECK_CERT_EXISTS_SET("policy mapping");
960
961 POLICY_MAPPINGS *maps = sk_POLICY_MAPPING_new_null();
962
963 PolicyMapList::Iter i(list);
964 for (i.rewind(); i.next();)
965 {
966 POLICY_MAPPING *map = POLICY_MAPPING_new();
967 map->issuerDomainPolicy = OBJ_txt2obj(i().issuer_domain.cstr(), 0);
968 map->subjectDomainPolicy = OBJ_txt2obj(i().subject_domain.cstr(), 0);
969 sk_POLICY_MAPPING_push(maps, map);
970 printf("Push!\n");
971 }
972
973 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_policy_mappings, 0, maps);
974 X509_add_ext(cert, ex, -1);
975 X509_EXTENSION_free(ex);
976 sk_POLICY_MAPPING_pop_free(maps, POLICY_MAPPING_free);
977}
978
979#endif // HAVE_OPENSSL_POLICY_MAPPING
980
981
982static void add_aia(WvStringParm type, WvString identifier,
983 AUTHORITY_INFO_ACCESS *ainfo)
984{
985 ACCESS_DESCRIPTION *acc = ACCESS_DESCRIPTION_new();
986 sk_ACCESS_DESCRIPTION_push(ainfo, acc);
987 acc->method = OBJ_txt2obj(type.cstr(), 0);
988 acc->location->type = GEN_URI;
989 acc->location->d.ia5 = ASN1_IA5STRING_new();
990 unsigned char *cident
991 = reinterpret_cast<unsigned char *>(identifier.edit());
992 ASN1_STRING_set(acc->location->d.ia5, cident, identifier.len());
993}
994
995
997 WvStringList &responders)
998{
999 CHECK_CERT_EXISTS_SET("aia");
1000
1001 AUTHORITY_INFO_ACCESS *ainfo = sk_ACCESS_DESCRIPTION_new_null();
1002
1003 WvStringList::Iter i(ca_urls);
1004 for (i.rewind(); i.next();)
1005 add_aia("caIssuers", i(), ainfo);
1006
1007 WvStringList::Iter j(responders);
1008 for (j.rewind(); j.next();)
1009 add_aia("OCSP", j(), ainfo);
1010
1011 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_info_access, 0, ainfo);
1012 X509_add_ext(cert, ex, -1);
1013 X509_EXTENSION_free(ex);
1014 sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free);
1015}
1016
1017
1019{
1020 return get_extension(NID_info_access);
1021}
1022
1023
1024static void parse_stack(WvStringParm ext, WvStringList &list,
1025 WvStringParm prefix)
1026{
1027 WvStringList stack;
1028 stack.split(ext, ";\n");
1029 WvStringList::Iter i(stack);
1030 for (i.rewind();i.next();)
1031 {
1032 WvString stack_entry(*i);
1033 if (strstr(stack_entry, prefix))
1034 {
1035 WvString uri(trim_string(stack_entry.edit()) + prefix.len());
1036 list.append(uri);
1037 }
1038 }
1039}
1040
1041
1042void WvX509::get_ocsp(WvStringList &responders) const
1043{
1044 parse_stack(get_aia(), responders, "OCSP - URI:");
1045}
1046
1047
1049{
1050 parse_stack(get_aia(), urls, "CA Issuers - URI:");
1051}
1052
1053
1055{
1056 parse_stack(get_crl_dp(), urls, "URI:");
1057}
1058
1059
1061{
1062 CHECK_CERT_EXISTS_SET("CRL urls");
1063
1064 STACK_OF(DIST_POINT) *crldp = sk_DIST_POINT_new_null();
1065 WvStringList::Iter i(urls);
1066 for (i.rewind(); i.next();)
1067 {
1068 DIST_POINT *point = DIST_POINT_new();
1069 sk_DIST_POINT_push(crldp, point);
1070
1071 GENERAL_NAMES *uris = GENERAL_NAMES_new();
1072 GENERAL_NAME *uri = GENERAL_NAME_new();
1073 uri->type = GEN_URI;
1074 uri->d.ia5 = ASN1_IA5STRING_new();
1075 unsigned char *cident
1076 = reinterpret_cast<unsigned char *>(i().edit());
1077 ASN1_STRING_set(uri->d.ia5, cident, i().len());
1078 sk_GENERAL_NAME_push(uris, uri);
1079
1080 point->distpoint = DIST_POINT_NAME_new();
1081 point->distpoint->name.fullname = uris;
1082 point->distpoint->type = 0;
1083 }
1084
1085 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_crl_distribution_points, 0, crldp);
1086 X509_add_ext(cert, ex, -1);
1087 X509_EXTENSION_free(ex);
1088 sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
1089}
1090
1091
1092bool WvX509::get_policies(WvStringList &policy_oids) const
1093{
1094 CHECK_CERT_EXISTS_GET("policies", false);
1095
1096 int critical;
1097 CERTIFICATEPOLICIES * policies = static_cast<CERTIFICATEPOLICIES *>(
1098 X509_get_ext_d2i(cert, NID_certificate_policies, &critical, NULL));
1099 if (policies)
1100 {
1101 for (int i = 0; i < sk_POLICYINFO_num(policies); i++)
1102 {
1103 POLICYINFO * policy = sk_POLICYINFO_value(policies, i);
1104 const int POLICYID_MAXLEN = 80;
1105
1106 char policyid[POLICYID_MAXLEN];
1107 OBJ_obj2txt(policyid, POLICYID_MAXLEN, policy->policyid,
1108 true); // don't substitute human-readable names
1109 policy_oids.append(policyid);
1110 }
1111
1112 sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
1113 return true;
1114 }
1115
1116 return false;
1117}
1118
1119
1121{
1122 CHECK_CERT_EXISTS_SET("policies");
1123
1124 STACK_OF(POLICYINFO) *sk_pinfo = sk_POLICYINFO_new_null();
1125
1126 WvStringList::Iter i(policy_oids);
1127 for (i.rewind(); i.next();)
1128 {
1129 ASN1_OBJECT *pobj = OBJ_txt2obj(i(), 0);
1130 POLICYINFO *pol = POLICYINFO_new();
1131 pol->policyid = pobj;
1132 sk_POLICYINFO_push(sk_pinfo, pol);
1133 }
1134
1135#if 0
1136 // this code would let you set URL information to a policy
1137 // qualifier
1138 POLICYQUALINFO *qual = NULL;
1139 WvString url(_url);
1140 if (!!url)
1141 {
1142 pol->qualifiers = sk_POLICYQUALINFO_new_null();
1143 qual = POLICYQUALINFO_new();
1144 qual->pqualid = OBJ_nid2obj(NID_id_qt_cps);
1145 qual->d.cpsouri = M_ASN1_IA5STRING_new();
1146 ASN1_STRING_set(qual->d.cpsuri, url.edit(), url.len());
1147 sk_POLICYQUALINFO_push(pol->qualifiers, qual);
1148 }
1149#endif
1150
1151 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_certificate_policies, 0,
1152 sk_pinfo);
1153 X509_add_ext(cert, ex, -1);
1154 X509_EXTENSION_free(ex);
1155 sk_POLICYINFO_pop_free(sk_pinfo, POLICYINFO_free);
1156}
1157
1158
1159WvString WvX509::get_extension(int nid) const
1160{
1161 CHECK_CERT_EXISTS_GET("extension", WvString::null);
1162
1163 WvString retval = WvString::null;
1164
1165 int index = X509_get_ext_by_NID(cert, nid, -1);
1166 if (index >= 0)
1167 {
1168 const X509_EXTENSION *ext = X509_get_ext(cert, index);
1169
1170 if (ext)
1171 {
1172 X509V3_EXT_METHOD *method = (X509V3_EXT_METHOD *)X509V3_EXT_get(const_cast<X509_EXTENSION *>(ext));
1173 const ASN1_OCTET_STRING *ext_data_str = X509_EXTENSION_get_data(const_cast<X509_EXTENSION *>(ext));
1174 if (!method)
1175 {
1176 WvDynBuf buf;
1177 buf.put(ASN1_STRING_get0_data(ext_data_str), ASN1_STRING_length(ext_data_str));
1178 retval = buf.getstr();
1179 }
1180 else
1181 {
1182 void *ext_data = NULL;
1183 // we NEED to use a temporary pointer for ext_value_data,
1184 // as openssl's ASN1_item_d2i will muck around with it,
1185 // even though it's const (at least as of version 0.9.8e).
1186 // gah.
1187#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
1188 const unsigned char * ext_value_data = ASN1_STRING_get0_data(ext_data_str);
1189#else
1190 unsigned char *ext_value_data = ASN1_STRING_get0_data(ext_data_str);
1191#endif
1192 if (method->it)
1193 {
1194 ext_data = ASN1_item_d2i(NULL, &ext_value_data,
1195 ASN1_STRING_length(ext_data_str),
1196 ASN1_ITEM_ptr(method->it));
1197 TRACE("Applied generic conversion!\n");
1198 }
1199 else
1200 {
1201 ext_data = method->d2i(NULL, &ext_value_data,
1202 ASN1_STRING_length(ext_data_str));
1203 TRACE("Applied method specific conversion!\n");
1204 }
1205
1206 if (method->i2s)
1207 {
1208 TRACE("String Extension!\n");
1209 char *s = method->i2s(method, ext_data);
1210 retval = s;
1211 OPENSSL_free(s);
1212 }
1213 else if (method->i2v)
1214 {
1215 TRACE("Stack Extension!\n");
1216 CONF_VALUE *val = NULL;
1217 STACK_OF(CONF_VALUE) *svals = NULL;
1218 svals = method->i2v(method, ext_data, NULL);
1219 if (!sk_CONF_VALUE_num(svals))
1220 retval = "EMPTY";
1221 else
1222 {
1223 WvStringList list;
1224 for(int i = 0; i < sk_CONF_VALUE_num(svals); i++)
1225 {
1226 val = sk_CONF_VALUE_value(svals, i);
1227 if (!val->name)
1228 list.append(WvString(val->value));
1229 else if (!val->value)
1230 list.append(WvString(val->name));
1231 else
1232 {
1233 WvString pair("%s:%s", val->name, val->value);
1234 list.append(pair);
1235 }
1236 }
1237 retval = list.join(";\n");
1238 }
1239 sk_CONF_VALUE_pop_free(svals, X509V3_conf_free);
1240 }
1241 else if (method->i2r)
1242 {
1243 TRACE("Raw Extension!\n");
1244 WvDynBuf retvalbuf;
1245 BIO *bufbio = BIO_new(BIO_s_mem());
1246 BUF_MEM *bm;
1247 method->i2r(method, ext_data, bufbio, 0);
1248 BIO_get_mem_ptr(bufbio, &bm);
1249 retvalbuf.put(bm->data, bm->length);
1250 BIO_free(bufbio);
1251 retval = retvalbuf.getstr();
1252 }
1253
1254 if (method->it)
1255 ASN1_item_free((ASN1_VALUE *)ext_data,
1256 ASN1_ITEM_ptr(method->it));
1257 else
1258 method->ext_free(ext_data);
1259
1260 }
1261 }
1262 }
1263 else
1264 {
1265 TRACE("Extension not present!\n");
1266 }
1267
1268 if (!!retval)
1269 TRACE("Returning: %s\n", retval);
1270
1271 return retval;
1272}
1273
1274
1275void WvX509::set_extension(int nid, WvStringParm _values)
1276{
1277 CHECK_CERT_EXISTS_SET("extension");
1278
1279 // first we check to see if the extension already exists, if so we need to
1280 // kill it
1281 int index = X509_get_ext_by_NID(cert, nid, -1);
1282 if (index >= 0)
1283 {
1284 X509_EXTENSION *ex = X509_delete_ext(cert, index);
1285 X509_EXTENSION_free(ex);
1286 }
1287
1288 // now set the extension
1289 WvString values(_values);
1290 X509_EXTENSION *ex = NULL;
1291 ex = X509V3_EXT_conf_nid(NULL, NULL, nid, values.edit());
1292 X509_add_ext(cert, ex, -1);
1293 X509_EXTENSION_free(ex);
1294}
1295
1296
1297bool WvX509::isok() const
1298{
1299 return cert;
1300}
1301
1302
1304{
1305 return !isok();
1306}
1307
1308
1310{
1311 if (!cert)
1312 return "No certificate.";
1313
1314 return WvString::empty;
1315}
1316
1317
1318bool WvX509::verify(WvStringParm original, WvStringParm signature) const
1319{
1320 WvDynBuf buf;
1321 buf.putstr(original);
1322 return verify(buf, signature);
1323}
1324
1325
1326bool WvX509::verify(WvBuf &original, WvStringParm signature) const
1327{
1328 unsigned char sig_buf[4096];
1329 size_t sig_size = sizeof(sig_buf);
1330 WvBase64Decoder().flushstrmem(signature, sig_buf, &sig_size, true);
1331
1332 EVP_PKEY *pk = X509_get_pubkey(cert);
1333 if (!pk)
1334 return false;
1335
1336 /* Verify the signature */
1337 EVP_MD_CTX *sig_ctx = EVP_MD_CTX_new();
1338 EVP_VerifyInit(sig_ctx, EVP_sha1());
1339 EVP_VerifyUpdate(sig_ctx, original.peek(0, original.used()),
1340 original.used());
1341 int sig_err = EVP_VerifyFinal(sig_ctx, sig_buf, sig_size, pk);
1342 EVP_PKEY_free(pk);
1343 EVP_MD_CTX_free(sig_ctx); // Again, not my fault...
1344 if (sig_err != 1)
1345 {
1346 debug("Verify failed!\n");
1347 return false;
1348 }
1349 else
1350 return true;
1351}
1352
1353
1354static time_t ASN1_TIME_to_time_t(const ASN1_TIME *t)
1355{
1356 struct tm newtime;
1357 char *p = NULL;
1358 char d[18];
1359 memset(&d,'\0',sizeof(d));
1360 memset(&newtime,'\0',sizeof newtime);
1361
1362 if (ASN1_STRING_type(t) == V_ASN1_GENERALIZEDTIME)
1363 {
1364 // For time values >= 2050, OpenSSL uses
1365 // ASN1_GENERALIZEDTIME - which we'll worry about
1366 // later.
1367 return 0;
1368 }
1369
1370 p = (char *)ASN1_STRING_get0_data(t);
1371 sscanf(p,"%2s%2s%2s%2s%2s%2sZ", d, &d[3], &d[6], &d[9], &d[12], &d[15]);
1372
1373 int year = strtol(d, (char **)NULL, 10);
1374 if (year < 49)
1375 year += 100;
1376 else
1377 year += 50;
1378
1379 newtime.tm_year = year;
1380 newtime.tm_mon = strtol(&d[3], (char **)NULL, 10) - 1;
1381 newtime.tm_mday = strtol(&d[6], (char **)NULL, 10);
1382 newtime.tm_hour = strtol(&d[9], (char **)NULL, 10);
1383 newtime.tm_min = strtol(&d[12], (char **)NULL, 10);
1384 newtime.tm_sec = strtol(&d[15], (char **)NULL, 10);
1385
1386 return mktime(&newtime);
1387}
1388
1389
1391{
1392 CHECK_CERT_EXISTS_GET("not valid before", 0);
1393
1394 return ASN1_TIME_to_time_t(X509_get_notBefore(cert));
1395}
1396
1397
1398time_t WvX509::get_notvalid_after() const
1399{
1400 CHECK_CERT_EXISTS_GET("not valid after", 0);
1401
1402 return ASN1_TIME_to_time_t(X509_get_notAfter(cert));
1403}
1404
1405
1407{
1408 CHECK_CERT_EXISTS_GET("ski", WvString::null);
1409
1410 return get_extension(NID_subject_key_identifier);
1411}
1412
1413
1415{
1416 CHECK_CERT_EXISTS_GET("aki", WvString::null);
1417
1418 WvStringList aki_list;
1419 parse_stack(get_extension(NID_authority_key_identifier), aki_list,
1420 "keyid:");
1421 if (aki_list.count())
1422 return aki_list.popstr();
1423
1424 return WvString::null;
1425}
1426
1427
1428WvString WvX509::get_fingerprint(const FprintMode mode) const
1429{
1430 CHECK_CERT_EXISTS_GET("fingerprint", WvString::null);
1431
1432 /* Default to SHA-1 because OpenSSL does too */
1433 const EVP_MD *digest = EVP_sha1();
1434 if (mode == FingerMD5)
1435 digest = EVP_md5();
1436
1437 unsigned char md[EVP_MAX_MD_SIZE];
1438 unsigned int n;
1439 if (!X509_digest(cert, digest, md, &n))
1440 {
1441 errno = -ENOMEM;
1442 debug("get_fingerprint: Out of memory\n");
1443 return WvString::null;
1444 }
1445
1446 WvDynBuf store;
1447 char buf[3];
1448 unsigned int i = 0;
1449 do {
1450 sprintf(buf, "%02X", md[i]);
1451 store.putstr(buf);
1452 } while (++i < n && (store.putch(':'), 1));
1453
1454 return store.getstr();
1455}
1456
1457
1458void WvX509::set_ski()
1459{
1460 CHECK_CERT_EXISTS_SET("ski");
1461
1462 ASN1_OCTET_STRING *oct = ASN1_OCTET_STRING_new();
1463 const ASN1_BIT_STRING *pk = X509_get0_pubkey_bitstr(cert);
1464 unsigned char pkey_dig[EVP_MAX_MD_SIZE];
1465 unsigned int diglen;
1466
1467 EVP_Digest(ASN1_STRING_get0_data(pk), ASN1_STRING_length(pk), pkey_dig, &diglen, EVP_sha1(), NULL);
1468
1469 ASN1_OCTET_STRING_set(oct, pkey_dig, diglen);
1470 X509_EXTENSION *ext = X509V3_EXT_i2d(NID_subject_key_identifier, 0,
1471 oct);
1472 X509_add_ext(cert, ext, -1);
1473 X509_EXTENSION_free(ext);
1474 ASN1_OCTET_STRING_free(oct);
1475}
1476
1477
1478void WvX509::set_aki(const WvX509 &cacert)
1479{
1480 CHECK_CERT_EXISTS_SET("aki");
1481
1482 // can't set a meaningful AKI for subordinate certification without the
1483 // parent having an SKI
1484 ASN1_OCTET_STRING *ikeyid = NULL;
1485 const X509_EXTENSION *src_ext;
1486 X509_EXTENSION *ext;
1487 int i = X509_get_ext_by_NID(cacert.cert, NID_subject_key_identifier, -1);
1488 if ((i >= 0) && (src_ext = X509_get_ext(cacert.cert, i)))
1489 ikeyid = static_cast<ASN1_OCTET_STRING *>(X509V3_EXT_d2i(const_cast<X509_EXTENSION *>(src_ext)));
1490
1491 if (!ikeyid)
1492 return;
1493
1494 AUTHORITY_KEYID *akeyid = AUTHORITY_KEYID_new();
1495 akeyid->issuer = NULL;
1496 akeyid->serial = NULL;
1497 akeyid->keyid = ikeyid;
1498 ext = X509V3_EXT_i2d(NID_authority_key_identifier, 0, akeyid);
1499 X509_add_ext(cert, ext, -1);
1500 X509_EXTENSION_free(ext);
1501 AUTHORITY_KEYID_free(akeyid);
1502}
1503
The basic interface which is included by all other XPLC interfaces and objects.
const T * get(size_t count)
Reads exactly the specified number of elements and returns a pointer to a storage location owned by t...
void put(const T *data, size_t count)
Writes the specified number of elements from the specified storage location into the buffer at its ta...
const T * peek(int offset, size_t count)
Returns a const pointer into the buffer at the specified offset to the specified number of elements w...
size_t used() const
Returns the number of elements in the buffer currently available for reading.
WvString getstr()
Returns the entire buffer as a null-terminated WvString.
void putch(int ch)
Puts a single character into the buffer as an int.
void putstr(WvStringParm str)
Copies a WvString into the buffer, excluding the null-terminator.
bool flushstrmem(WvStringParm instr, void *outmem, size_t *outlen, bool finish=false)
Flushes data through the encoder from a string to memory.
Definition wvencoder.cc:150
const char * cstr() const
return a (const char *) for this string.
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
An RSA public key or public/private key pair that can be used for encryption.
This is a WvList of WvStrings, and is a really handy way to parse strings.
WvString join(const char *joinchars=" ") const
concatenates all elements of the list seperating on joinchars
void split(WvStringParm s, const char *splitchars=" \t\r\n", int limit=0)
split s and form a list ignoring splitchars (except at beginning and end) ie.
WvString popstr()
get the first string in the list, or an empty string if the list is empty.
WvString is an implementation of a simple and efficient printable-string class.
char * edit()
make the string editable, and return a non-const (char*)
X509 Class to handle certificates and their related functions.
virtual WvString errstr() const
Returns an error string if isok() is not true.
Definition wvx509.cc:1309
WvString get_ski() const
Get the Subject Key Info.
Definition wvx509.cc:1406
void set_policy_mapping(PolicyMapList &list)
Set the policy mappings for this certificate.
void set_policies(WvStringList &policy_oids)
Set the Certificate Policy OIDs in the certificate to that of the input array.
Definition wvx509.cc:1120
time_t get_notvalid_before() const
Return the not before and not after in a format we're more able to easily use.
Definition wvx509.cc:1390
bool signedbyca(WvX509 &cacert) const
Check the certificate in cert against the CA certificate in cacert.
Definition wvx509.cc:399
void set_basic_constraints(bool ca, int pathlen)
Set the values in the basic constraints extension.
Definition wvx509.cc:837
WvString get_serial(bool hex=false) const
get and set the serialNumber field of the certificate
Definition wvx509.cc:716
WvString get_aki() const
Get the Authority key Info.
Definition wvx509.cc:1414
void get_ocsp(WvStringList &responders) const
Get a list of OCSP Responders for this certificate.
Definition wvx509.cc:1042
void get_ca_urls(WvStringList &urls) const
Get a list of urls that have the Certificate of the CA that issued this certificate.
Definition wvx509.cc:1048
WvX509()
Initialize a completely empty X509 Object with an X509 certificate that doesn't have anything it it....
Definition wvx509.cc:131
virtual ~WvX509()
Destructor.
Definition wvx509.cc:150
bool get_policy_mapping(PolicyMapList &list) const
Get the policy mappings for this certificate.
void set_crl_urls(WvStringList &urls)
Set the list of URLs that are valid CRL distribution points for this certificate.
Definition wvx509.cc:1060
void set_version()
Set the Certificate to use X509v3, since that's all modern PKI uses anyways :).
Definition wvx509.cc:734
WvString get_ext_key_usage() const
Get and set the extendedKeyUsage field.
Definition wvx509.cc:788
bool get_policies(WvStringList &policy_oids) const
Get any certificate Policy OIDs.
Definition wvx509.cc:1092
WvString get_subject() const
get and set the Subject field of the certificate
Definition wvx509.cc:633
bool validate(WvX509 *cacert=NULL) const
Function to verify the validity of a certificate that has been placed in cert.
Definition wvx509.cc:365
bool get_policy_constraints(int &require_explicit_policy, int &inhibit_policy_mapping) const
Get the values in the policy constraints extension.
bool get_basic_constraints(bool &ca, int &pathlen) const
Get the values in the basic constraints extension.
Definition wvx509.cc:800
WvString get_fingerprint(const FprintMode mode=FingerSHA1) const
Get the certHash (fingerprint) of the certificate.
Definition wvx509.cc:1428
DumpMode
Type for the encode() and decode() methods.
bool issuedbyca(WvX509 &cacert) const
Check to see if the certificate in cert was issued by the CA certificate in cacert.
Definition wvx509.cc:428
WvString get_crl_dp() const
get the CRL Distribution points if they exist, WvString::null if they don't.
Definition wvx509.cc:750
void set_lifetime(long seconds)
Set the lifetime to be used for this certificate... the lifetime starts from the minute that the cert...
Definition wvx509.cc:756
void set_pubkey(WvRSAKey &rsa_pubkey)
Set the public key of the certificate to the public key rsa_pubkey.
Definition wvx509.cc:665
virtual void decode(const DumpMode mode, WvStringParm str)
Load the information from the format requested by mode into the class - this overwrites the certifica...
Definition wvx509.cc:505
static WvString certreq(WvStringParm subject, const WvRSAKey &rsa)
Create a certificate request (PKCS#10) using this function.
Definition wvx509.cc:266
bool operator!() const
The not operator returns true if !isok().
Definition wvx509.cc:1303
void set_policy_constraints(int require_explicit_policy, int inhibit_policy_mapping)
Set the values in the policy constraints extension.
WvString get_issuer() const
Get and set the Certificate Issuer (usually the CA who signed the certificate).
Definition wvx509.cc:600
WvString get_aia() const
Get the authority info access information.
Definition wvx509.cc:1018
WvString get_altsubject() const
Return the Subject alt name if it exists, and WvString::null if it doesn't.
Definition wvx509.cc:794
bool verify(WvBuf &original, WvStringParm signature) const
Verify that the contents of data were signed by the certificate currently in cert.
Definition wvx509.cc:1326
WvString get_key_usage() const
Get and set the keyUsage field.
Definition wvx509.cc:776
WvString encode(const DumpMode mode) const
Return the information requested by mode.
Definition wvx509.cc:447
void get_crl_urls(WvStringList &urls) const
Get a list of URLs that are valid CRL distribution points for this certificate.
Definition wvx509.cc:1054
void set_aia(WvStringList &ca_urls, WvStringList &responders)
Set a list of urls that have the Certificate of the CA that issued this certificate,...
Definition wvx509.cc:996
WvString get_nsserver() const
get and set the Netscape SSL Server extension
Definition wvx509.cc:710
virtual bool isok() const
Is the certificate object valid?
Definition wvx509.cc:1297
void hexify(char *obuf, const void *ibuf, size_t len)
Write the contents of the binary string of length 'len' pointed to by 'ibuf' into the output buffer '...
Definition wvhex.cc:95
void unhexify(void *obuf, const char *ibuf)
Reverse the operation performed by hexify().
Definition wvhex.cc:104
char * trim_string(char *string)
Trims whitespace from the beginning and end of the character string, including carriage return / line...
Definition strutils.cc:59
char * strlwr(char *string)
In-place modify a character string so that all contained letters are in lower case.
Definition strutils.cc:201
#define deletev
Remplacement for delete[].
#define UUID_MAP_END
Marks the end of an interface map.
#define UUID_MAP_BEGIN(component)
Start the interface map for "component".
#define UUID_MAP_ENTRY(iface)
Add an entry to an interface map.