Add RFC 3779 support.
[openssl.git] / crypto / x509v3 / v3_utl.c
index 4b85378e945fdcc6e4adeb9fd07325736fb45e6d..7c1d26fc398bb57e15c66e17be5d77c8a48c92d2 100644 (file)
@@ -63,6 +63,7 @@
 #include "cryptlib.h"
 #include <openssl/conf.h>
 #include <openssl/x509v3.h>
+#include <openssl/bn.h>
 
 static char *strip_spaces(char *name);
 static int sk_strcmp(const char * const *a, const char * const *b);
@@ -552,18 +553,10 @@ ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
 
        /* If string contains a ':' assume IPv6 */
 
-       if (strchr(ipasc, ':'))
-               {
-               if (!ipv6_from_asc(ipout, ipasc))
-                       return NULL;
-               iplen = 16;
-               }
-       else
-               {
-               if (!ipv4_from_asc(ipout, ipasc))
-                       return NULL;
-               iplen = 4;
-               }
+       iplen = a2i_ipadd(ipout, ipasc);
+
+       if (!iplen)
+               return NULL;
 
        ret = ASN1_OCTET_STRING_new();
        if (!ret)
@@ -576,6 +569,69 @@ ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
        return ret;
        }
 
+ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
+       {
+       ASN1_OCTET_STRING *ret = NULL;
+       unsigned char ipout[32];
+       char *iptmp = NULL, *p;
+       int iplen1, iplen2;
+       p = strchr(ipasc,'/');
+       if (!p)
+               return NULL;
+       iptmp = BUF_strdup(ipasc);
+       if (!iptmp)
+               return NULL;
+       p = iptmp + (p - ipasc);
+       *p++ = 0;
+
+       iplen1 = a2i_ipadd(ipout, iptmp);
+
+       if (!iplen1)
+               goto err;
+
+       iplen2 = a2i_ipadd(ipout + iplen1, p);
+
+       OPENSSL_free(iptmp);
+       iptmp = NULL;
+
+       if (!iplen2 || (iplen1 != iplen2))
+               goto err;
+
+       ret = ASN1_OCTET_STRING_new();
+       if (!ret)
+               goto err;
+       if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
+               goto err;
+
+       return ret;
+
+       err:
+       if (iptmp)
+               OPENSSL_free(iptmp);
+       if (ret)
+               ASN1_OCTET_STRING_free(ret);
+       return NULL;
+       }
+       
+
+int a2i_ipadd(unsigned char *ipout, const char *ipasc)
+       {
+       /* If string contains a ':' assume IPv6 */
+
+       if (strchr(ipasc, ':'))
+               {
+               if (!ipv6_from_asc(ipout, ipasc))
+                       return 0;
+               return 16;
+               }
+       else
+               {
+               if (!ipv4_from_asc(ipout, ipasc))
+                       return 0;
+               return 4;
+               }
+       }
+
 static int ipv4_from_asc(unsigned char *v4, const char *in)
        {
        int a0, a1, a2, a3;
@@ -740,3 +796,49 @@ static int ipv6_hex(unsigned char *out, const char *in, int inlen)
        return 1;
        }
 
+
+int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
+                                               unsigned long chtype)
+       {
+       CONF_VALUE *v;
+       int i, mval;
+       char *p, *type;
+       if (!nm)
+               return 0;
+
+       for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++)
+               {
+               v=sk_CONF_VALUE_value(dn_sk,i);
+               type=v->name;
+               /* Skip past any leading X. X: X, etc to allow for
+                * multiple instances 
+                */
+               for(p = type; *p ; p++) 
+#ifndef CHARSET_EBCDIC
+                       if ((*p == ':') || (*p == ',') || (*p == '.'))
+#else
+                       if ((*p == os_toascii[':']) || (*p == os_toascii[',']) || (*p == os_toascii['.']))
+#endif
+                               {
+                               p++;
+                               if(*p) type = p;
+                               break;
+                               }
+#ifndef CHARSET_EBCDIC
+               if (*type == '+')
+#else
+               if (*type == os_toascii['+'])
+#endif
+                       {
+                       mval = -1;
+                       type++;
+                       }
+               else
+                       mval = 0;
+               if (!X509_NAME_add_entry_by_txt(nm,type, chtype,
+                               (unsigned char *) v->value,-1,-1,mval))
+                                       return 0;
+
+               }
+       return 1;
+       }