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.
65{
66public:
68 {
69 wvssl_init();
70 }
71
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
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 name = X509_REQ_get_subject_name(certreq);
310
311 debug("Creating Certificate request for %s\n", subject);
312 set_name_entry(name, subject);
313 X509_REQ_set_subject_name(certreq, name);
314 char *sub_name = X509_NAME_oneline(X509_REQ_get_subject_name(certreq),
315 0, 0);
316 debug("SubjectDN: %s\n", sub_name);
317 OPENSSL_free(sub_name);
318
319 if (!X509_REQ_sign(certreq, pk, EVP_sha1()))
320 {
321 debug(WvLog::Warning, "Could not self sign the request");
322 X509_REQ_free(certreq);
323 EVP_PKEY_free(pk);
324 return WvString::null;
325 }
326
327 int verify_result = X509_REQ_verify(certreq, pk);
328 if (verify_result == 0 || verify_result == -1)
329 {
330 debug(WvLog::Warning, "Self signed request failed");
331 X509_REQ_free(certreq);
332 EVP_PKEY_free(pk);
333 return WvString::null;
334 }
335 else
336 {
337 debug("Self Signed Certificate Request verifies OK!\n");
338 }
339
340 // Horribly involuted hack to get around the fact that the
341 // OpenSSL people are too braindead to have a PEM_write function
342 // that returns a char *
343 WvDynBuf retval;
344 BIO *bufbio = BIO_new(BIO_s_mem());
345 BUF_MEM *bm;
346
347 PEM_write_bio_X509_REQ(bufbio, certreq);
348 BIO_get_mem_ptr(bufbio, &bm);
349 retval.put(bm->data, bm->length);
350
351 X509_REQ_free(certreq);
352 EVP_PKEY_free(pk);
353 BIO_free(bufbio);
354
355 return retval.getstr();
356}
357
358
359bool WvX509::validate(WvX509 *cacert) const
360{
361 if (cert == NULL)
362 {
363 debug(WvLog::Warning, "Tried to validate certificate against CA, but "
364 "certificate is blank!\n");
365 return false;
366 }
367
368 bool retval = true;
369
370 // Check and make sure that the certificate is still valid
371 if (X509_cmp_current_time(X509_get_notAfter(cert)) < 0)
372 {
373 debug("Certificate has expired.\n");
374 retval = false;
375 }
376
377 if (X509_cmp_current_time(X509_get_notBefore(cert)) > 0)
378 {
379 debug("Certificate is not yet valid.\n");
380 retval = false;
381 }
382
383 if (cacert)
384 {
385 retval &= signedbyca(*cacert);
386 retval &= issuedbyca(*cacert);
387 }
388
389 return retval;
390}
391
392
393bool WvX509::signedbyca(WvX509 &cacert) const
394{
395 if (!cert || !cacert.cert)
396 {
397 debug(WvLog::Warning, "Tried to determine if certificate was signed "
398 "by CA, but either client or CA certificate (or both) are "
399 "blank.\n");
400 return false;
401 }
402
403 EVP_PKEY *pkey = X509_get_pubkey(cacert.cert);
404 int result = X509_verify(cert, pkey);
405 EVP_PKEY_free(pkey);
406
407 if (result < 0)
408 {
409 debug("Can't determine if we were signed by CA %s: %s\n",
410 cacert.get_subject(), wvssl_errstr());
411 return false;
412 }
413 bool issigned = (result > 0);
414
415 debug("Certificate was%s signed by CA %s.\n", issigned ? "" : " NOT",
416 cacert.get_subject());
417
418 return issigned;
419}
420
421
422bool WvX509::issuedbyca(WvX509 &cacert) const
423{
424 if (!cert || !cacert.cert)
425 {
426 debug(WvLog::Warning, "Tried to determine if certificate was issued "
427 "by CA, but either client or CA certificate (or both) are "
428 "blank.\n");
429 return false;
430 }
431
432 int ret = X509_check_issued(cacert.cert, cert);
433 debug("issuedbyca: %s==X509_V_OK(%s)\n", ret, X509_V_OK);
434 if (ret != X509_V_OK)
435 return false;
436
437 return true;
438}
439
440
442{
443 WvDynBuf retval;
444 encode(mode, retval);
445 return retval.getstr();
446}
447
448
449void WvX509::encode(const DumpMode mode, WvBuf &buf) const
450{
451 if (mode == CertFileDER || mode == CertFilePEM)
452 return; // file modes are no ops with encode
453
454 if (!cert)
455 {
456 debug(WvLog::Warning, "Tried to encode certificate, but certificate "
457 "is blank!\n");
458 return;
459 }
460
461 debug("Encoding X509 certificate.\n");
462
463 if (mode == CertHex)
464 {
465 size_t size;
466 unsigned char *keybuf, *iend;
467 WvString enccert;
468
469 size = i2d_X509(cert, NULL);
470 iend = keybuf = new unsigned char[size];
471 i2d_X509(cert, &iend);
472
473 enccert.setsize(size * 2 +1);
474 ::hexify(enccert.edit(), keybuf, size);
475
476 deletev keybuf;
477 buf.putstr(enccert);
478 }
479 else
480 {
481 BIO *bufbio = BIO_new(BIO_s_mem());
482 BUF_MEM *bm;
483
484 if (mode == CertPEM)
485 PEM_write_bio_X509(bufbio, cert);
486 else if (mode == CertDER)
487 i2d_X509_bio(bufbio, cert);
488 else
489 debug(WvLog::Warning, "Tried to encode certificate with unknown "
490 "mode!\n");
491
492 BIO_get_mem_ptr(bufbio, &bm);
493 buf.put(bm->data, bm->length);
494 BIO_free(bufbio);
495 }
496}
497
498
500{
501 if (cert)
502 {
503 debug("Replacing an already existant X509 certificate.\n");
504 X509_free(cert);
505 cert = NULL;
506 }
507
508 if (mode == CertFileDER)
509 {
510 BIO *bio = BIO_new(BIO_s_file());
511
512 if (BIO_read_filename(bio, str.cstr()) <= 0)
513 {
514 debug(WvLog::Warning, "Open '%s': %s\n", str, wvssl_errstr());
515 BIO_free(bio);
516 return;
517 }
518
519 if (!(cert = d2i_X509_bio(bio, NULL)))
520 debug(WvLog::Warning, "Import DER from '%s': %s\n",
521 str, wvssl_errstr());
522
523 BIO_free(bio);
524 return;
525 }
526 else if (mode == CertFilePEM)
527 {
528 FILE *fp = fopen(str, "rb");
529 if (!fp)
530 {
531 int errnum = errno;
532 debug("Open '%s': %s\n", str, strerror(errnum));
533 return;
534 }
535
536 if (!(cert = PEM_read_X509(fp, NULL, NULL, NULL)))
537 debug(WvLog::Warning, "Import PEM from '%s': %s\n",
538 str, wvssl_errstr());
539
540 fclose(fp);
541 return;
542 }
543 else if (mode == CertHex)
544 {
545 int hexbytes = str.len();
546 int bufsize = hexbytes/2;
547 unsigned char *certbuf = new unsigned char[bufsize];
548 unsigned char *cp = certbuf;
549 X509 *tmpcert;
550
551 ::unhexify(certbuf, str);
552 tmpcert = cert = X509_new();
553 cert = wv_d2i_X509(&tmpcert, &cp, bufsize);
554 delete[] certbuf;
555 return;
556 }
557
558 // we use the buffer decode functions for everything else
559 WvDynBuf buf;
560 buf.putstr(str);
561 decode(mode, buf);
562}
563
564
565void WvX509::decode(const DumpMode mode, WvBuf &encoded)
566{
567 if (cert)
568 {
569 debug("Replacing an already existant X509 certificate.\n");
570 X509_free(cert);
571 cert = NULL;
572 }
573
574 if (mode == CertHex || mode == CertFileDER || mode == CertFilePEM)
575 decode(mode, encoded.getstr());
576 else
577 {
578 BIO *membuf = BIO_new(BIO_s_mem());
579 BIO_write(membuf, encoded.get(encoded.used()), encoded.used());
580
581 if (mode == CertPEM)
582 cert = PEM_read_bio_X509(membuf, NULL, NULL, NULL);
583 else if (mode == CertDER)
584 cert = d2i_X509_bio(membuf, NULL);
585 else
586 debug(WvLog::Warning, "Tried to decode certificate with unknown "
587 "mode!\n");
588
589 BIO_free_all(membuf);
590 }
591}
592
593
595{
596 CHECK_CERT_EXISTS_GET("issuer", WvString::null);
597
598 char *name = X509_NAME_oneline(X509_get_issuer_name(cert),0,0);
599 WvString retval(name);
600 OPENSSL_free(name);
601 return retval;
602}
603
604
605void WvX509::set_issuer(WvStringParm issuer)
606{
607 CHECK_CERT_EXISTS_SET("issuer");
608
609 X509_NAME *name = X509_get_issuer_name(cert);
610 set_name_entry(name, issuer);
611 X509_set_issuer_name(cert, name);
612}
613
614
615void WvX509::set_issuer(const WvX509 &cacert)
616{
617 CHECK_CERT_EXISTS_SET("issuer");
618
619 X509_NAME *casubj = X509_get_subject_name(cacert.cert);
620 X509_set_issuer_name(cert, casubj);
621}
622
623
625{
626 CHECK_CERT_EXISTS_GET("subject", WvString::null);
627
628 char *name = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
629 WvString retval(name);
630 OPENSSL_free(name);
631 return retval;
632}
633
634
635void WvX509::set_subject(WvStringParm subject)
636{
637 CHECK_CERT_EXISTS_SET("subject");
638
639 X509_NAME *name = X509_get_subject_name(cert);
640 set_name_entry(name, subject);
641 X509_set_subject_name(cert, name);
642}
643
644
645void WvX509::set_subject(X509_NAME *name)
646{
647 CHECK_CERT_EXISTS_SET("subject");
648
649 X509_set_subject_name(cert, name);
650}
651
652
654{
655 CHECK_CERT_EXISTS_SET("pubkey");
656
657 EVP_PKEY *pk = EVP_PKEY_new();
658 assert(pk);
659
660 // Assign RSA Key from WvRSAKey into stupid package that OpenSSL needs
661 if (!EVP_PKEY_set1_RSA(pk, _rsa.rsa))
662 {
663 debug("Error adding RSA keys to certificate.\n");
664 return;
665 }
666
667 X509_set_pubkey(cert, pk);
668
669 EVP_PKEY_free(pk);
670}
671
672
673
674void WvX509::set_nsserver(WvStringParm servername)
675{
676 CHECK_CERT_EXISTS_SET("nsserver");
677
678 WvString fqdn;
679
680 // FQDN cannot have a = in it, therefore it
681 // must be a distinguished name :)
682 if (strchr(servername, '='))
683 fqdn = set_name_entry(NULL, servername);
684 else
685 fqdn = servername;
686
687 if (!fqdn)
688 fqdn = "null.noname.null";
689
690 debug("Setting Netscape SSL server name extension to '%s'.\n", fqdn);
691
692 // Add in the netscape-specific server extension
693 set_extension(NID_netscape_cert_type, "server");
694 set_extension(NID_netscape_ssl_server_name, fqdn);
695}
696
697
699{
700 return get_extension(NID_netscape_ssl_server_name);
701}
702
703
705{
706 CHECK_CERT_EXISTS_GET("serial", WvString::null);
707
708 BIGNUM *bn = BN_new();
709 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), bn);
710 char * c;
711 if (hex)
712 c = BN_bn2hex(bn);
713 else
714 c = BN_bn2dec(bn);
715 WvString ret("%s", c);
716 OPENSSL_free(c);
717 BN_free(bn);
718 return ret;
719}
720
721
723{
724 CHECK_CERT_EXISTS_SET("version");
725
726 X509_set_version(cert, 0x2);
727}
728
729
730void WvX509::set_serial(long serial)
731{
732 CHECK_CERT_EXISTS_SET("serial");
733
734 ASN1_INTEGER_set(X509_get_serialNumber(cert), serial);
735}
736
737
739{
740 return get_extension(NID_crl_distribution_points);
741}
742
743
744void WvX509::set_lifetime(long seconds)
745{
746 CHECK_CERT_EXISTS_SET("lifetime");
747
748 // Set the NotBefore time to now.
749 X509_gmtime_adj(X509_get_notBefore(cert), 0);
750
751 // Now + 10 years... should be shorter, but since we don't currently
752 // have a set of routines to refresh the certificates, make it
753 // REALLY long.
754 X509_gmtime_adj(X509_get_notAfter(cert), seconds);
755}
756
757
758void WvX509::set_key_usage(WvStringParm values)
759{
760 set_extension(NID_key_usage, values);
761}
762
763
765{
766 return get_extension(NID_key_usage);
767}
768
769
770void WvX509::set_ext_key_usage(WvStringParm values)
771{
772 set_extension(NID_ext_key_usage, values);
773}
774
775
777{
778 return get_extension(NID_ext_key_usage);
779}
780
781
783{
784 return get_extension(NID_subject_alt_name);
785}
786
787
788bool WvX509::get_basic_constraints(bool &ca, int &pathlen) const
789{
790 CHECK_CERT_EXISTS_GET("basic constraints", false);
791
792 BASIC_CONSTRAINTS *constraints = NULL;
793 int i;
794
795 constraints = static_cast<BASIC_CONSTRAINTS *>
796 (X509_get_ext_d2i(cert, NID_basic_constraints, &i, NULL));
797 if (constraints)
798 {
799 ca = constraints->ca;
800 if (constraints->pathlen)
801 {
802 if ((constraints->pathlen->type == V_ASN1_NEG_INTEGER) || !ca)
803 {
804 debug("Path length type not valid when getting basic "
805 "constraints.\n");
806 BASIC_CONSTRAINTS_free(constraints);
807 pathlen = 0;
808 return false;
809 }
810
811 pathlen = ASN1_INTEGER_get(constraints->pathlen);
812 }
813 else
814 pathlen = (-1);
815
816 BASIC_CONSTRAINTS_free(constraints);
817 return true;
818 }
819
820 debug("Basic constraints extension not present.\n");
821 return false;
822}
823
824
825void WvX509::set_basic_constraints(bool ca, int pathlen)
826{
827 CHECK_CERT_EXISTS_SET("basic constraints");
828
829 BASIC_CONSTRAINTS *constraints = BASIC_CONSTRAINTS_new();
830
831 constraints->ca = static_cast<int>(ca);
832 if (pathlen != (-1))
833 {
834 ASN1_INTEGER *i = ASN1_INTEGER_new();
835 ASN1_INTEGER_set(i, pathlen);
836 constraints->pathlen = i;
837 }
838
839 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_basic_constraints, 0,
840 constraints);
841 while (int idx = X509_get_ext_by_NID(cert, NID_basic_constraints, 0) >= 0)
842 {
843 debug("Found extension at idx %s\n", idx);
844 X509_EXTENSION *tmpex = X509_delete_ext(cert, idx);
845 X509_EXTENSION_free(tmpex);
846 }
847
848 X509_add_ext(cert, ex, NID_basic_constraints);
849 X509_EXTENSION_free(ex);
850 BASIC_CONSTRAINTS_free(constraints);
851}
852
853
854/*
855 * These functions are optional to the API. If OpenSSL doesn't support them,
856 * we simply won't include them here, and apps that need them won't compile.
857 */
858#ifdef HAVE_OPENSSL_POLICY_MAPPING
859
860bool WvX509::get_policy_constraints(int &require_explicit_policy,
861 int &inhibit_policy_mapping) const
862{
863 CHECK_CERT_EXISTS_GET("policy constraints", false);
864
865 POLICY_CONSTRAINTS *constraints = NULL;
866 int i;
867
868 constraints = static_cast<POLICY_CONSTRAINTS *>(X509_get_ext_d2i(
869 cert, NID_policy_constraints,
870 &i, NULL));
871 if (constraints)
872 {
873 if (constraints->requireExplicitPolicy)
874 require_explicit_policy = ASN1_INTEGER_get(
875 constraints->requireExplicitPolicy);
876 else
877 require_explicit_policy = (-1);
878
879 if (constraints->inhibitPolicyMapping)
880 inhibit_policy_mapping = ASN1_INTEGER_get(
881 constraints->inhibitPolicyMapping);
882 else
883 inhibit_policy_mapping = (-1);
884 POLICY_CONSTRAINTS_free(constraints);
885 return true;
886 }
887
888 return false;
889}
890
891
892void WvX509::set_policy_constraints(int require_explicit_policy,
893 int inhibit_policy_mapping)
894{
895 CHECK_CERT_EXISTS_SET("policy constraints");
896
897 POLICY_CONSTRAINTS *constraints = POLICY_CONSTRAINTS_new();
898
899 ASN1_INTEGER *i = ASN1_INTEGER_new();
900 ASN1_INTEGER_set(i, require_explicit_policy);
901 constraints->requireExplicitPolicy = i;
902 i = ASN1_INTEGER_new();
903 ASN1_INTEGER_set(i, inhibit_policy_mapping);
904 constraints->inhibitPolicyMapping = i;
905
906 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_policy_constraints, 0,
907 constraints);
908 X509_add_ext(cert, ex, -1);
909 X509_EXTENSION_free(ex);
910 POLICY_CONSTRAINTS_free(constraints);
911}
912
913
914bool WvX509::get_policy_mapping(PolicyMapList &list) const
915{
916 CHECK_CERT_EXISTS_GET("policy mapping", false);
917
918 POLICY_MAPPINGS *mappings = NULL;
919 POLICY_MAPPING *map = NULL;
920 int i;
921
922 mappings = static_cast<POLICY_MAPPINGS *>(X509_get_ext_d2i(
923 cert, NID_policy_mappings,
924 &i, NULL));
925 if (!mappings)
926 return false;
927
928 const int POLICYID_MAXLEN = 80;
929 char tmp1[80];
930 char tmp2[80];
931 for(int j = 0; j < sk_POLICY_MAPPING_num(mappings); j++)
932 {
933 map = sk_POLICY_MAPPING_value(mappings, j);
934 OBJ_obj2txt(tmp1, POLICYID_MAXLEN, map->issuerDomainPolicy, true);
935 OBJ_obj2txt(tmp2, POLICYID_MAXLEN, map->subjectDomainPolicy, true);
936 list.append(new PolicyMap(tmp1, tmp2), true);
937 }
938
939 sk_POLICY_MAPPING_pop_free(mappings, POLICY_MAPPING_free);
940
941 return true;
942}
943
944
945void WvX509::set_policy_mapping(PolicyMapList &list)
946{
947 CHECK_CERT_EXISTS_SET("policy mapping");
948
949 POLICY_MAPPINGS *maps = sk_POLICY_MAPPING_new_null();
950
951 PolicyMapList::Iter i(list);
952 for (i.rewind(); i.next();)
953 {
954 POLICY_MAPPING *map = POLICY_MAPPING_new();
955 map->issuerDomainPolicy = OBJ_txt2obj(i().issuer_domain.cstr(), 0);
956 map->subjectDomainPolicy = OBJ_txt2obj(i().subject_domain.cstr(), 0);
957 sk_POLICY_MAPPING_push(maps, map);
958 printf("Push!\n");
959 }
960
961 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_policy_mappings, 0, maps);
962 X509_add_ext(cert, ex, -1);
963 X509_EXTENSION_free(ex);
964 sk_POLICY_MAPPING_pop_free(maps, POLICY_MAPPING_free);
965}
966
967#endif // HAVE_OPENSSL_POLICY_MAPPING
968
969
970static void add_aia(WvStringParm type, WvString identifier,
971 AUTHORITY_INFO_ACCESS *ainfo)
972{
973 ACCESS_DESCRIPTION *acc = ACCESS_DESCRIPTION_new();
974 sk_ACCESS_DESCRIPTION_push(ainfo, acc);
975 acc->method = OBJ_txt2obj(type.cstr(), 0);
976 acc->location->type = GEN_URI;
977 acc->location->d.ia5 = ASN1_IA5STRING_new();
978 unsigned char *cident
979 = reinterpret_cast<unsigned char *>(identifier.edit());
980 ASN1_STRING_set(acc->location->d.ia5, cident, identifier.len());
981}
982
983
985 WvStringList &responders)
986{
987 CHECK_CERT_EXISTS_SET("aia");
988
989 AUTHORITY_INFO_ACCESS *ainfo = sk_ACCESS_DESCRIPTION_new_null();
990
991 WvStringList::Iter i(ca_urls);
992 for (i.rewind(); i.next();)
993 add_aia("caIssuers", i(), ainfo);
994
995 WvStringList::Iter j(responders);
996 for (j.rewind(); j.next();)
997 add_aia("OCSP", j(), ainfo);
998
999 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_info_access, 0, ainfo);
1000 X509_add_ext(cert, ex, -1);
1001 X509_EXTENSION_free(ex);
1002 sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free);
1003}
1004
1005
1007{
1008 return get_extension(NID_info_access);
1009}
1010
1011
1012static void parse_stack(WvStringParm ext, WvStringList &list,
1013 WvStringParm prefix)
1014{
1015 WvStringList stack;
1016 stack.split(ext, ";\n");
1017 WvStringList::Iter i(stack);
1018 for (i.rewind();i.next();)
1019 {
1020 WvString stack_entry(*i);
1021 if (strstr(stack_entry, prefix))
1022 {
1023 WvString uri(stack_entry.edit() + prefix.len());
1024 list.append(uri);
1025 }
1026 }
1027}
1028
1029
1030void WvX509::get_ocsp(WvStringList &responders) const
1031{
1032 parse_stack(get_aia(), responders, "OCSP - URI:");
1033}
1034
1035
1037{
1038 parse_stack(get_aia(), urls, "CA Issuers - URI:");
1039}
1040
1041
1043{
1044 parse_stack(get_crl_dp(), urls, "URI:");
1045}
1046
1047
1049{
1050 CHECK_CERT_EXISTS_SET("CRL urls");
1051
1052 STACK_OF(DIST_POINT) *crldp = sk_DIST_POINT_new_null();
1053 WvStringList::Iter i(urls);
1054 for (i.rewind(); i.next();)
1055 {
1056 DIST_POINT *point = DIST_POINT_new();
1057 sk_DIST_POINT_push(crldp, point);
1058
1059 GENERAL_NAMES *uris = GENERAL_NAMES_new();
1060 GENERAL_NAME *uri = GENERAL_NAME_new();
1061 uri->type = GEN_URI;
1062 uri->d.ia5 = ASN1_IA5STRING_new();
1063 unsigned char *cident
1064 = reinterpret_cast<unsigned char *>(i().edit());
1065 ASN1_STRING_set(uri->d.ia5, cident, i().len());
1066 sk_GENERAL_NAME_push(uris, uri);
1067
1068 point->distpoint = DIST_POINT_NAME_new();
1069 point->distpoint->name.fullname = uris;
1070 point->distpoint->type = 0;
1071 }
1072
1073 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_crl_distribution_points, 0, crldp);
1074 X509_add_ext(cert, ex, -1);
1075 X509_EXTENSION_free(ex);
1076 sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
1077}
1078
1079
1080bool WvX509::get_policies(WvStringList &policy_oids) const
1081{
1082 CHECK_CERT_EXISTS_GET("policies", false);
1083
1084 int critical;
1085 CERTIFICATEPOLICIES * policies = static_cast<CERTIFICATEPOLICIES *>(
1086 X509_get_ext_d2i(cert, NID_certificate_policies, &critical, NULL));
1087 if (policies)
1088 {
1089 for (int i = 0; i < sk_POLICYINFO_num(policies); i++)
1090 {
1091 POLICYINFO * policy = sk_POLICYINFO_value(policies, i);
1092 const int POLICYID_MAXLEN = 80;
1093
1094 char policyid[POLICYID_MAXLEN];
1095 OBJ_obj2txt(policyid, POLICYID_MAXLEN, policy->policyid,
1096 true); // don't substitute human-readable names
1097 policy_oids.append(policyid);
1098 }
1099
1100 sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
1101 return true;
1102 }
1103
1104 return false;
1105}
1106
1107
1109{
1110 CHECK_CERT_EXISTS_SET("policies");
1111
1112 STACK_OF(POLICYINFO) *sk_pinfo = sk_POLICYINFO_new_null();
1113
1114 WvStringList::Iter i(policy_oids);
1115 for (i.rewind(); i.next();)
1116 {
1117 ASN1_OBJECT *pobj = OBJ_txt2obj(i(), 0);
1118 POLICYINFO *pol = POLICYINFO_new();
1119 pol->policyid = pobj;
1120 sk_POLICYINFO_push(sk_pinfo, pol);
1121 }
1122
1123#if 0
1124 // this code would let you set URL information to a policy
1125 // qualifier
1126 POLICYQUALINFO *qual = NULL;
1127 WvString url(_url);
1128 if (!!url)
1129 {
1130 pol->qualifiers = sk_POLICYQUALINFO_new_null();
1131 qual = POLICYQUALINFO_new();
1132 qual->pqualid = OBJ_nid2obj(NID_id_qt_cps);
1133 qual->d.cpsouri = M_ASN1_IA5STRING_new();
1134 ASN1_STRING_set(qual->d.cpsuri, url.edit(), url.len());
1135 sk_POLICYQUALINFO_push(pol->qualifiers, qual);
1136 }
1137#endif
1138
1139 X509_EXTENSION *ex = X509V3_EXT_i2d(NID_certificate_policies, 0,
1140 sk_pinfo);
1141 X509_add_ext(cert, ex, -1);
1142 X509_EXTENSION_free(ex);
1143 sk_POLICYINFO_pop_free(sk_pinfo, POLICYINFO_free);
1144}
1145
1146
1147WvString WvX509::get_extension(int nid) const
1148{
1149 CHECK_CERT_EXISTS_GET("extension", WvString::null);
1150
1151 WvString retval = WvString::null;
1152
1153 int index = X509_get_ext_by_NID(cert, nid, -1);
1154 if (index >= 0)
1155 {
1156 X509_EXTENSION *ext = X509_get_ext(cert, index);
1157
1158 if (ext)
1159 {
1160 X509V3_EXT_METHOD *method = (X509V3_EXT_METHOD *)X509V3_EXT_get(ext);
1161 ASN1_OCTET_STRING *ext_data_str = X509_EXTENSION_get_data(ext);
1162 if (!method)
1163 {
1164 WvDynBuf buf;
1165 buf.put(ext_data_str->data, ext_data_str->length);
1166 retval = buf.getstr();
1167 }
1168 else
1169 {
1170 void *ext_data = NULL;
1171 // we NEED to use a temporary pointer for ext_value_data,
1172 // as openssl's ASN1_item_d2i will muck around with it,
1173 // even though it's const (at least as of version 0.9.8e).
1174 // gah.
1175#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
1176 const unsigned char * ext_value_data = ext_data_str->data;
1177#else
1178 unsigned char *ext_value_data = ext->value->data;
1179#endif
1180 if (method->it)
1181 {
1182 ext_data = ASN1_item_d2i(NULL, &ext_value_data,
1183 ext_data_str->length,
1184 ASN1_ITEM_ptr(method->it));
1185 TRACE("Applied generic conversion!\n");
1186 }
1187 else
1188 {
1189 ext_data = method->d2i(NULL, &ext_value_data,
1190 ext_data_str->length);
1191 TRACE("Applied method specific conversion!\n");
1192 }
1193
1194 if (method->i2s)
1195 {
1196 TRACE("String Extension!\n");
1197 char *s = method->i2s(method, ext_data);
1198 retval = s;
1199 OPENSSL_free(s);
1200 }
1201 else if (method->i2v)
1202 {
1203 TRACE("Stack Extension!\n");
1204 CONF_VALUE *val = NULL;
1205 STACK_OF(CONF_VALUE) *svals = NULL;
1206 svals = method->i2v(method, ext_data, NULL);
1207 if (!sk_CONF_VALUE_num(svals))
1208 retval = "EMPTY";
1209 else
1210 {
1211 WvStringList list;
1212 for(int i = 0; i < sk_CONF_VALUE_num(svals); i++)
1213 {
1214 val = sk_CONF_VALUE_value(svals, i);
1215 if (!val->name)
1216 list.append(WvString(val->value));
1217 else if (!val->value)
1218 list.append(WvString(val->name));
1219 else
1220 {
1221 WvString pair("%s:%s", val->name, val->value);
1222 list.append(pair);
1223 }
1224 }
1225 retval = list.join(";\n");
1226 }
1227 sk_CONF_VALUE_pop_free(svals, X509V3_conf_free);
1228 }
1229 else if (method->i2r)
1230 {
1231 TRACE("Raw Extension!\n");
1232 WvDynBuf retvalbuf;
1233 BIO *bufbio = BIO_new(BIO_s_mem());
1234 BUF_MEM *bm;
1235 method->i2r(method, ext_data, bufbio, 0);
1236 BIO_get_mem_ptr(bufbio, &bm);
1237 retvalbuf.put(bm->data, bm->length);
1238 BIO_free(bufbio);
1239 retval = retvalbuf.getstr();
1240 }
1241
1242 if (method->it)
1243 ASN1_item_free((ASN1_VALUE *)ext_data,
1244 ASN1_ITEM_ptr(method->it));
1245 else
1246 method->ext_free(ext_data);
1247
1248 }
1249 }
1250 }
1251 else
1252 {
1253 TRACE("Extension not present!\n");
1254 }
1255
1256 if (!!retval)
1257 TRACE("Returning: %s\n", retval);
1258
1259 return retval;
1260}
1261
1262
1263void WvX509::set_extension(int nid, WvStringParm _values)
1264{
1265 CHECK_CERT_EXISTS_SET("extension");
1266
1267 // first we check to see if the extension already exists, if so we need to
1268 // kill it
1269 int index = X509_get_ext_by_NID(cert, nid, -1);
1270 if (index >= 0)
1271 {
1272 X509_EXTENSION *ex = X509_delete_ext(cert, index);
1273 X509_EXTENSION_free(ex);
1274 }
1275
1276 // now set the extension
1277 WvString values(_values);
1278 X509_EXTENSION *ex = NULL;
1279 ex = X509V3_EXT_conf_nid(NULL, NULL, nid, values.edit());
1280 X509_add_ext(cert, ex, -1);
1281 X509_EXTENSION_free(ex);
1282}
1283
1284
1285bool WvX509::isok() const
1286{
1287 return cert;
1288}
1289
1290
1292{
1293 return !isok();
1294}
1295
1296
1298{
1299 if (!cert)
1300 return "No certificate.";
1301
1302 return WvString::empty;
1303}
1304
1305
1306bool WvX509::verify(WvStringParm original, WvStringParm signature) const
1307{
1308 WvDynBuf buf;
1309 buf.putstr(original);
1310 return verify(buf, signature);
1311}
1312
1313
1314bool WvX509::verify(WvBuf &original, WvStringParm signature) const
1315{
1316 unsigned char sig_buf[4096];
1317 size_t sig_size = sizeof(sig_buf);
1318 WvBase64Decoder().flushstrmem(signature, sig_buf, &sig_size, true);
1319
1320 EVP_PKEY *pk = X509_get_pubkey(cert);
1321 if (!pk)
1322 return false;
1323
1324 /* Verify the signature */
1325 EVP_MD_CTX *sig_ctx = EVP_MD_CTX_new();
1326 EVP_VerifyInit(sig_ctx, EVP_sha1());
1327 EVP_VerifyUpdate(sig_ctx, original.peek(0, original.used()),
1328 original.used());
1329 int sig_err = EVP_VerifyFinal(sig_ctx, sig_buf, sig_size, pk);
1330 EVP_PKEY_free(pk);
1331 EVP_MD_CTX_free(sig_ctx); // Again, not my fault...
1332 if (sig_err != 1)
1333 {
1334 debug("Verify failed!\n");
1335 return false;
1336 }
1337 else
1338 return true;
1339}
1340
1341
1342static time_t ASN1_TIME_to_time_t(ASN1_TIME *t)
1343{
1344 struct tm newtime;
1345 char *p = NULL;
1346 char d[18];
1347 memset(&d,'\0',sizeof(d));
1348 memset(&newtime,'\0',sizeof newtime);
1349
1350 if (t->type == V_ASN1_GENERALIZEDTIME)
1351 {
1352 // For time values >= 2050, OpenSSL uses
1353 // ASN1_GENERALIZEDTIME - which we'll worry about
1354 // later.
1355 return 0;
1356 }
1357
1358 p = (char *)t->data;
1359 sscanf(p,"%2s%2s%2s%2s%2s%2sZ", d, &d[3], &d[6], &d[9], &d[12], &d[15]);
1360
1361 int year = strtol(d, (char **)NULL, 10);
1362 if (year < 49)
1363 year += 100;
1364 else
1365 year += 50;
1366
1367 newtime.tm_year = year;
1368 newtime.tm_mon = strtol(&d[3], (char **)NULL, 10) - 1;
1369 newtime.tm_mday = strtol(&d[6], (char **)NULL, 10);
1370 newtime.tm_hour = strtol(&d[9], (char **)NULL, 10);
1371 newtime.tm_min = strtol(&d[12], (char **)NULL, 10);
1372 newtime.tm_sec = strtol(&d[15], (char **)NULL, 10);
1373
1374 return mktime(&newtime);
1375}
1376
1377
1379{
1380 CHECK_CERT_EXISTS_GET("not valid before", 0);
1381
1382 return ASN1_TIME_to_time_t(X509_get_notBefore(cert));
1383}
1384
1385
1386time_t WvX509::get_notvalid_after() const
1387{
1388 CHECK_CERT_EXISTS_GET("not valid after", 0);
1389
1390 return ASN1_TIME_to_time_t(X509_get_notAfter(cert));
1391}
1392
1393
1395{
1396 CHECK_CERT_EXISTS_GET("ski", WvString::null);
1397
1398 return get_extension(NID_subject_key_identifier);
1399}
1400
1401
1403{
1404 CHECK_CERT_EXISTS_GET("aki", WvString::null);
1405
1406 WvStringList aki_list;
1407 parse_stack(get_extension(NID_authority_key_identifier), aki_list,
1408 "keyid:");
1409 if (aki_list.count())
1410 return aki_list.popstr();
1411
1412 return WvString::null;
1413}
1414
1415
1416WvString WvX509::get_fingerprint(const FprintMode mode) const
1417{
1418 CHECK_CERT_EXISTS_GET("fingerprint", WvString::null);
1419
1420 /* Default to SHA-1 because OpenSSL does too */
1421 const EVP_MD *digest = EVP_sha1();
1422 if (mode == FingerMD5)
1423 digest = EVP_md5();
1424
1425 unsigned char md[EVP_MAX_MD_SIZE];
1426 unsigned int n;
1427 if (!X509_digest(cert, digest, md, &n))
1428 {
1429 errno = -ENOMEM;
1430 debug("get_fingerprint: Out of memory\n");
1431 return WvString::null;
1432 }
1433
1434 WvDynBuf store;
1435 char buf[3];
1436 unsigned int i = 0;
1437 do {
1438 sprintf(buf, "%02X", md[i]);
1439 store.putstr(buf);
1440 } while (++i < n && (store.putch(':'), 1));
1441
1442 return store.getstr();
1443}
1444
1445
1446void WvX509::set_ski()
1447{
1448 CHECK_CERT_EXISTS_SET("ski");
1449
1450 ASN1_OCTET_STRING *oct = ASN1_OCTET_STRING_new();
1451 ASN1_BIT_STRING *pk = X509_get0_pubkey_bitstr(cert);
1452 unsigned char pkey_dig[EVP_MAX_MD_SIZE];
1453 unsigned int diglen;
1454
1455 EVP_Digest(pk->data, pk->length, pkey_dig, &diglen, EVP_sha1(), NULL);
1456
1457 ASN1_OCTET_STRING_set(oct, pkey_dig, diglen);
1458 X509_EXTENSION *ext = X509V3_EXT_i2d(NID_subject_key_identifier, 0,
1459 oct);
1460 X509_add_ext(cert, ext, -1);
1461 X509_EXTENSION_free(ext);
1462 ASN1_OCTET_STRING_free(oct);
1463}
1464
1465
1466void WvX509::set_aki(const WvX509 &cacert)
1467{
1468 CHECK_CERT_EXISTS_SET("aki");
1469
1470 // can't set a meaningful AKI for subordinate certification without the
1471 // parent having an SKI
1472 ASN1_OCTET_STRING *ikeyid = NULL;
1473 X509_EXTENSION *ext;
1474 int i = X509_get_ext_by_NID(cacert.cert, NID_subject_key_identifier, -1);
1475 if ((i >= 0) && (ext = X509_get_ext(cacert.cert, i)))
1476 ikeyid = static_cast<ASN1_OCTET_STRING *>(X509V3_EXT_d2i(ext));
1477
1478 if (!ikeyid)
1479 return;
1480
1481 AUTHORITY_KEYID *akeyid = AUTHORITY_KEYID_new();
1482 akeyid->issuer = NULL;
1483 akeyid->serial = NULL;
1484 akeyid->keyid = ikeyid;
1485 ext = X509V3_EXT_i2d(NID_authority_key_identifier, 0, akeyid);
1486 X509_add_ext(cert, ext, -1);
1487 X509_EXTENSION_free(ext);
1488 AUTHORITY_KEYID_free(akeyid);
1489}
1490
The basic interface which is included by all other XPLC interfaces and objects.
Definition IObject.h:65
A base 64 decoder.
Definition wvbase64.h:50
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...
Definition wvbufbase.h:483
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
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
Definition wvstring.h:94
const char * cstr() const
return a (const char *) for this string.
Definition wvstring.h:267
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
Definition wvlog.h:57
An RSA public key or public/private key pair that can be used for encryption.
Definition wvrsa.h:27
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.
Definition wvstring.h:330
char * edit()
make the string editable, and return a non-const (char*)
Definition wvstring.h:397
X509 Class to handle certificates and their related functions.
Definition wvx509.h:42
virtual WvString errstr() const
Returns an error string if isok() is not true.
Definition wvx509.cc:1297
WvString get_ski() const
Get the Subject Key Info.
Definition wvx509.cc:1394
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:1108
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:1378
bool signedbyca(WvX509 &cacert) const
Check the certificate in cert against the CA certificate in cacert.
Definition wvx509.cc:393
void set_basic_constraints(bool ca, int pathlen)
Set the values in the basic constraints extension.
Definition wvx509.cc:825
WvString get_serial(bool hex=false) const
get and set the serialNumber field of the certificate
Definition wvx509.cc:704
WvString get_aki() const
Get the Authority key Info.
Definition wvx509.cc:1402
void get_ocsp(WvStringList &responders) const
Get a list of OCSP Responders for this certificate.
Definition wvx509.cc:1030
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:1036
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:1048
void set_version()
Set the Certificate to use X509v3, since that's all modern PKI uses anyways :)
Definition wvx509.cc:722
WvString get_ext_key_usage() const
Get and set the extendedKeyUsage field.
Definition wvx509.cc:776
bool get_policies(WvStringList &policy_oids) const
Get any certificate Policy OIDs.
Definition wvx509.cc:1080
WvString get_subject() const
get and set the Subject field of the certificate
Definition wvx509.cc:624
bool validate(WvX509 *cacert=NULL) const
Function to verify the validity of a certificate that has been placed in cert.
Definition wvx509.cc:359
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:788
WvString get_fingerprint(const FprintMode mode=FingerSHA1) const
Get the certHash (fingerprint) of the certificate.
Definition wvx509.cc:1416
DumpMode
Type for the encode() and decode() methods.
Definition wvx509.h:56
bool issuedbyca(WvX509 &cacert) const
Check to see if the certificate in cert was issued by the CA certificate in cacert.
Definition wvx509.cc:422
WvString get_crl_dp() const
get the CRL Distribution points if they exist, WvString::null if they don't.
Definition wvx509.cc:738
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:744
void set_pubkey(WvRSAKey &rsa_pubkey)
Set the public key of the certificate to the public key rsa_pubkey.
Definition wvx509.cc:653
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:499
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:1291
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:594
WvString get_aia() const
Get the authority info access information.
Definition wvx509.cc:1006
WvString get_altsubject() const
Return the Subject alt name if it exists, and WvString::null if it doesn't.
Definition wvx509.cc:782
bool verify(WvBuf &original, WvStringParm signature) const
Verify that the contents of data were signed by the certificate currently in cert.
Definition wvx509.cc:1314
WvString get_key_usage() const
Get and set the keyUsage field.
Definition wvx509.cc:764
WvString encode(const DumpMode mode) const
Return the information requested by mode.
Definition wvx509.cc:441
void get_crl_urls(WvStringList &urls) const
Get a list of URLs that are valid CRL distribution points for this certificate.
Definition wvx509.cc:1042
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:984
WvString get_nsserver() const
get and set the Netscape SSL Server extension
Definition wvx509.cc:698
virtual bool isok() const
Is the certificate object valid?
Definition wvx509.cc:1285
#define UUID_MAP_END
Marks the end of an interface map.
Definition utils.h:80
#define UUID_MAP_BEGIN(component)
Start the interface map for "component".
Definition utils.h:63
#define UUID_MAP_ENTRY(iface)
Add an entry to an interface map.
Definition utils.h:68
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
Various little string functions.
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