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
const T * get(size_t count)
Reads exactly the specified number of elements and returns a pointer to a storage location owned by t...
Definition: wvbufbase.h:114
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...
Definition: wvbufbase.h:225
size_t used() const
Returns the number of elements in the buffer currently available for reading.
Definition: wvbufbase.h:92
Specialization of WvBufBase for unsigned char type buffers intended for use with raw memory buffers.
Definition: wvbuf.h:24
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.
Definition: wvbuf.h:76
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
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.
Definition: wvstringlist.h:28
WvString join(const char *joinchars=" ") const
concatenates all elements of the list seperating on joinchars
Definition: wvstringlist.cc:14
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.
Definition: wvstringlist.cc:19
WvString popstr()
get the first string in the list, or an empty string if the list is empty.
Definition: wvstringlist.cc:55
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 deletev
Remplacement for delete[].
Definition: delete.h:129
#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