summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/x509v3/v3_utl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/x509v3/v3_utl.c')
-rw-r--r--src/lib/libcrypto/x509v3/v3_utl.c343
1 files changed, 338 insertions, 5 deletions
diff --git a/src/lib/libcrypto/x509v3/v3_utl.c b/src/lib/libcrypto/x509v3/v3_utl.c
index f23a8d29a0..57be441399 100644
--- a/src/lib/libcrypto/x509v3/v3_utl.c
+++ b/src/lib/libcrypto/x509v3/v3_utl.c
@@ -1,9 +1,9 @@
1/* v3_utl.c */ 1/* v3_utl.c */
2/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL 2/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3 * project 1999. 3 * project.
4 */ 4 */
5/* ==================================================================== 5/* ====================================================================
6 * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 6 * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
@@ -63,6 +63,7 @@
63#include "cryptlib.h" 63#include "cryptlib.h"
64#include <openssl/conf.h> 64#include <openssl/conf.h>
65#include <openssl/x509v3.h> 65#include <openssl/x509v3.h>
66#include <openssl/bn.h>
66 67
67static char *strip_spaces(char *name); 68static char *strip_spaces(char *name);
68static int sk_strcmp(const char * const *a, const char * const *b); 69static int sk_strcmp(const char * const *a, const char * const *b);
@@ -70,6 +71,11 @@ static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens);
70static void str_free(void *str); 71static void str_free(void *str);
71static int append_ia5(STACK **sk, ASN1_IA5STRING *email); 72static int append_ia5(STACK **sk, ASN1_IA5STRING *email);
72 73
74static int ipv4_from_asc(unsigned char *v4, const char *in);
75static int ipv6_from_asc(unsigned char *v6, const char *in);
76static int ipv6_cb(const char *elem, int len, void *usr);
77static int ipv6_hex(unsigned char *out, const char *in, int inlen);
78
73/* Add a CONF_VALUE name value pair to stack */ 79/* Add a CONF_VALUE name value pair to stack */
74 80
75int X509V3_add_value(const char *name, const char *value, 81int X509V3_add_value(const char *name, const char *value,
@@ -156,11 +162,11 @@ ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value)
156 ASN1_INTEGER *aint; 162 ASN1_INTEGER *aint;
157 int isneg, ishex; 163 int isneg, ishex;
158 int ret; 164 int ret;
159 bn = BN_new();
160 if (!value) { 165 if (!value) {
161 X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_INVALID_NULL_VALUE); 166 X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_INVALID_NULL_VALUE);
162 return 0; 167 return 0;
163 } 168 }
169 bn = BN_new();
164 if (value[0] == '-') { 170 if (value[0] == '-') {
165 value++; 171 value++;
166 isneg = 1; 172 isneg = 1;
@@ -174,7 +180,8 @@ ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value)
174 if (ishex) ret = BN_hex2bn(&bn, value); 180 if (ishex) ret = BN_hex2bn(&bn, value);
175 else ret = BN_dec2bn(&bn, value); 181 else ret = BN_dec2bn(&bn, value);
176 182
177 if (!ret) { 183 if (!ret || value[ret]) {
184 BN_free(bn);
178 X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_DEC2BN_ERROR); 185 X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_DEC2BN_ERROR);
179 return 0; 186 return 0;
180 } 187 }
@@ -358,7 +365,7 @@ char *hex_to_string(unsigned char *buffer, long len)
358 char *tmp, *q; 365 char *tmp, *q;
359 unsigned char *p; 366 unsigned char *p;
360 int i; 367 int i;
361 static char hexdig[] = "0123456789ABCDEF"; 368 const static char hexdig[] = "0123456789ABCDEF";
362 if(!buffer || !len) return NULL; 369 if(!buffer || !len) return NULL;
363 if(!(tmp = OPENSSL_malloc(len * 3 + 1))) { 370 if(!(tmp = OPENSSL_malloc(len * 3 + 1))) {
364 X509V3err(X509V3_F_HEX_TO_STRING,ERR_R_MALLOC_FAILURE); 371 X509V3err(X509V3_F_HEX_TO_STRING,ERR_R_MALLOC_FAILURE);
@@ -466,6 +473,30 @@ STACK *X509_get1_email(X509 *x)
466 return ret; 473 return ret;
467} 474}
468 475
476STACK *X509_get1_ocsp(X509 *x)
477{
478 AUTHORITY_INFO_ACCESS *info;
479 STACK *ret = NULL;
480 int i;
481 info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
482 if (!info)
483 return NULL;
484 for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++)
485 {
486 ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
487 if (OBJ_obj2nid(ad->method) == NID_ad_OCSP)
488 {
489 if (ad->location->type == GEN_URI)
490 {
491 if (!append_ia5(&ret, ad->location->d.uniformResourceIdentifier))
492 break;
493 }
494 }
495 }
496 AUTHORITY_INFO_ACCESS_free(info);
497 return ret;
498}
499
469STACK *X509_REQ_get1_email(X509_REQ *x) 500STACK *X509_REQ_get1_email(X509_REQ *x)
470{ 501{
471 GENERAL_NAMES *gens; 502 GENERAL_NAMES *gens;
@@ -533,3 +564,305 @@ void X509_email_free(STACK *sk)
533{ 564{
534 sk_pop_free(sk, str_free); 565 sk_pop_free(sk, str_free);
535} 566}
567
568/* Convert IP addresses both IPv4 and IPv6 into an
569 * OCTET STRING compatible with RFC3280.
570 */
571
572ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
573 {
574 unsigned char ipout[16];
575 ASN1_OCTET_STRING *ret;
576 int iplen;
577
578 /* If string contains a ':' assume IPv6 */
579
580 iplen = a2i_ipadd(ipout, ipasc);
581
582 if (!iplen)
583 return NULL;
584
585 ret = ASN1_OCTET_STRING_new();
586 if (!ret)
587 return NULL;
588 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen))
589 {
590 ASN1_OCTET_STRING_free(ret);
591 return NULL;
592 }
593 return ret;
594 }
595
596ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
597 {
598 ASN1_OCTET_STRING *ret = NULL;
599 unsigned char ipout[32];
600 char *iptmp = NULL, *p;
601 int iplen1, iplen2;
602 p = strchr(ipasc,'/');
603 if (!p)
604 return NULL;
605 iptmp = BUF_strdup(ipasc);
606 if (!iptmp)
607 return NULL;
608 p = iptmp + (p - ipasc);
609 *p++ = 0;
610
611 iplen1 = a2i_ipadd(ipout, iptmp);
612
613 if (!iplen1)
614 goto err;
615
616 iplen2 = a2i_ipadd(ipout + iplen1, p);
617
618 OPENSSL_free(iptmp);
619 iptmp = NULL;
620
621 if (!iplen2 || (iplen1 != iplen2))
622 goto err;
623
624 ret = ASN1_OCTET_STRING_new();
625 if (!ret)
626 goto err;
627 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
628 goto err;
629
630 return ret;
631
632 err:
633 if (iptmp)
634 OPENSSL_free(iptmp);
635 if (ret)
636 ASN1_OCTET_STRING_free(ret);
637 return NULL;
638 }
639
640
641int a2i_ipadd(unsigned char *ipout, const char *ipasc)
642 {
643 /* If string contains a ':' assume IPv6 */
644
645 if (strchr(ipasc, ':'))
646 {
647 if (!ipv6_from_asc(ipout, ipasc))
648 return 0;
649 return 16;
650 }
651 else
652 {
653 if (!ipv4_from_asc(ipout, ipasc))
654 return 0;
655 return 4;
656 }
657 }
658
659static int ipv4_from_asc(unsigned char *v4, const char *in)
660 {
661 int a0, a1, a2, a3;
662 if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
663 return 0;
664 if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
665 || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
666 return 0;
667 v4[0] = a0;
668 v4[1] = a1;
669 v4[2] = a2;
670 v4[3] = a3;
671 return 1;
672 }
673
674typedef struct {
675 /* Temporary store for IPV6 output */
676 unsigned char tmp[16];
677 /* Total number of bytes in tmp */
678 int total;
679 /* The position of a zero (corresponding to '::') */
680 int zero_pos;
681 /* Number of zeroes */
682 int zero_cnt;
683 } IPV6_STAT;
684
685
686static int ipv6_from_asc(unsigned char *v6, const char *in)
687 {
688 IPV6_STAT v6stat;
689 v6stat.total = 0;
690 v6stat.zero_pos = -1;
691 v6stat.zero_cnt = 0;
692 /* Treat the IPv6 representation as a list of values
693 * separated by ':'. The presence of a '::' will parse
694 * as one, two or three zero length elements.
695 */
696 if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
697 return 0;
698
699 /* Now for some sanity checks */
700
701 if (v6stat.zero_pos == -1)
702 {
703 /* If no '::' must have exactly 16 bytes */
704 if (v6stat.total != 16)
705 return 0;
706 }
707 else
708 {
709 /* If '::' must have less than 16 bytes */
710 if (v6stat.total == 16)
711 return 0;
712 /* More than three zeroes is an error */
713 if (v6stat.zero_cnt > 3)
714 return 0;
715 /* Can only have three zeroes if nothing else present */
716 else if (v6stat.zero_cnt == 3)
717 {
718 if (v6stat.total > 0)
719 return 0;
720 }
721 /* Can only have two zeroes if at start or end */
722 else if (v6stat.zero_cnt == 2)
723 {
724 if ((v6stat.zero_pos != 0)
725 && (v6stat.zero_pos != v6stat.total))
726 return 0;
727 }
728 else
729 /* Can only have one zero if *not* start or end */
730 {
731 if ((v6stat.zero_pos == 0)
732 || (v6stat.zero_pos == v6stat.total))
733 return 0;
734 }
735 }
736
737 /* Format result */
738
739 /* Copy initial part */
740 if (v6stat.zero_pos > 0)
741 memcpy(v6, v6stat.tmp, v6stat.zero_pos);
742 /* Zero middle */
743 if (v6stat.total != 16)
744 memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
745 /* Copy final part */
746 if (v6stat.total != v6stat.zero_pos)
747 memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
748 v6stat.tmp + v6stat.zero_pos,
749 v6stat.total - v6stat.zero_pos);
750
751 return 1;
752 }
753
754static int ipv6_cb(const char *elem, int len, void *usr)
755 {
756 IPV6_STAT *s = usr;
757 /* Error if 16 bytes written */
758 if (s->total == 16)
759 return 0;
760 if (len == 0)
761 {
762 /* Zero length element, corresponds to '::' */
763 if (s->zero_pos == -1)
764 s->zero_pos = s->total;
765 /* If we've already got a :: its an error */
766 else if (s->zero_pos != s->total)
767 return 0;
768 s->zero_cnt++;
769 }
770 else
771 {
772 /* If more than 4 characters could be final a.b.c.d form */
773 if (len > 4)
774 {
775 /* Need at least 4 bytes left */
776 if (s->total > 12)
777 return 0;
778 /* Must be end of string */
779 if (elem[len])
780 return 0;
781 if (!ipv4_from_asc(s->tmp + s->total, elem))
782 return 0;
783 s->total += 4;
784 }
785 else
786 {
787 if (!ipv6_hex(s->tmp + s->total, elem, len))
788 return 0;
789 s->total += 2;
790 }
791 }
792 return 1;
793 }
794
795/* Convert a string of up to 4 hex digits into the corresponding
796 * IPv6 form.
797 */
798
799static int ipv6_hex(unsigned char *out, const char *in, int inlen)
800 {
801 unsigned char c;
802 unsigned int num = 0;
803 if (inlen > 4)
804 return 0;
805 while(inlen--)
806 {
807 c = *in++;
808 num <<= 4;
809 if ((c >= '0') && (c <= '9'))
810 num |= c - '0';
811 else if ((c >= 'A') && (c <= 'F'))
812 num |= c - 'A' + 10;
813 else if ((c >= 'a') && (c <= 'f'))
814 num |= c - 'a' + 10;
815 else
816 return 0;
817 }
818 out[0] = num >> 8;
819 out[1] = num & 0xff;
820 return 1;
821 }
822
823
824int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
825 unsigned long chtype)
826 {
827 CONF_VALUE *v;
828 int i, mval;
829 char *p, *type;
830 if (!nm)
831 return 0;
832
833 for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++)
834 {
835 v=sk_CONF_VALUE_value(dn_sk,i);
836 type=v->name;
837 /* Skip past any leading X. X: X, etc to allow for
838 * multiple instances
839 */
840 for(p = type; *p ; p++)
841#ifndef CHARSET_EBCDIC
842 if ((*p == ':') || (*p == ',') || (*p == '.'))
843#else
844 if ((*p == os_toascii[':']) || (*p == os_toascii[',']) || (*p == os_toascii['.']))
845#endif
846 {
847 p++;
848 if(*p) type = p;
849 break;
850 }
851#ifndef CHARSET_EBCDIC
852 if (*type == '+')
853#else
854 if (*type == os_toascii['+'])
855#endif
856 {
857 mval = -1;
858 type++;
859 }
860 else
861 mval = 0;
862 if (!X509_NAME_add_entry_by_txt(nm,type, chtype,
863 (unsigned char *) v->value,-1,-1,mval))
864 return 0;
865
866 }
867 return 1;
868 }