Add RFC 3779 support.
[openssl.git] / crypto / x509v3 / v3_utl.c
index 2af05e555b7772188c451e87fca5612bf2a5c1a8..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;
@@ -745,7 +801,7 @@ int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
                                                unsigned long chtype)
        {
        CONF_VALUE *v;
-       int i;
+       int i, mval;
        char *p, *type;
        if (!nm)
                return 0;
@@ -768,8 +824,19 @@ int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
                                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,0))
+                               (unsigned char *) v->value,-1,-1,mval))
                                        return 0;
 
                }