Handle special cases correctly in exponentation functions.
[openssl.git] / crypto / x509v3 / v3_utl.c
index 3f567180c597e2ca1f072267c309e773492f8ed1..619f161b588220873bcecdd02981b189ecdad2ca 100644 (file)
 #include <openssl/x509v3.h>
 
 static char *strip_spaces(char *name);
+static int sk_strcmp(const char * const *a, const char * const *b);
+static STACK *get_email(X509_NAME *name, STACK_OF(GENERAL_NAME) *gens);
+static void str_free(void *str);
+static int append_ia5(STACK **sk, ASN1_IA5STRING *email);
 
 /* Add a CONF_VALUE name value pair to stack */
 
@@ -76,7 +80,7 @@ int X509V3_add_value(const char *name, const char *value,
        if(name && !(tname = BUF_strdup(name))) goto err;
        if(value && !(tvalue = BUF_strdup(value))) goto err;;
        if(!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) goto err;
-       if(!*extlist && !(*extlist = sk_CONF_VALUE_new(NULL))) goto err;
+       if(!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) goto err;
        vtmp->section = NULL;
        vtmp->name = tname;
        vtmp->value = tvalue;
@@ -327,6 +331,7 @@ static char *strip_spaces(char *name)
 
 /* Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
  * hex representation
+ * @@@ (Contents of buffer are always kept in ASCII, also on EBCDIC machines)
  */
 
 char *hex_to_string(unsigned char *buffer, long len)
@@ -347,6 +352,10 @@ char *hex_to_string(unsigned char *buffer, long len)
                *q++ = ':';
        }
        q[-1] = 0;
+#ifdef CHARSET_EBCDIC
+       ebcdic2ascii(tmp, tmp, q - tmp - 1);
+#endif
+
        return tmp;
 }
 
@@ -365,8 +374,14 @@ unsigned char *string_to_hex(char *str, long *len)
        if(!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) goto err;
        for(p = (unsigned char *)str, q = hexbuf; *p;) {
                ch = *p++;
+#ifdef CHARSET_EBCDIC
+               ch = os_toebcdic[ch];
+#endif
                if(ch == ':') continue;
                cl = *p++;
+#ifdef CHARSET_EBCDIC
+               cl = os_toebcdic[cl];
+#endif
                if(!cl) {
                        X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ODD_NUMBER_OF_DIGITS);
                        OPENSSL_free(hexbuf);
@@ -416,3 +431,86 @@ int name_cmp(const char *name, const char *cmp)
        if(!c || (c=='.')) return 0;
        return 1;
 }
+
+static int sk_strcmp(const char * const *a, const char * const *b)
+{
+       return strcmp(*a, *b);
+}
+
+STACK *X509_get1_email(X509 *x)
+{
+       STACK_OF(GENERAL_NAME) *gens;
+       STACK *ret;
+       gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
+       ret = get_email(X509_get_subject_name(x), gens);
+       sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+       return ret;
+}
+
+STACK *X509_REQ_get1_email(X509_REQ *x)
+{
+       STACK_OF(GENERAL_NAME) *gens;
+       STACK_OF(X509_EXTENSION) *exts;
+       STACK *ret;
+       exts = X509_REQ_get_extensions(x);
+       gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
+       ret = get_email(X509_REQ_get_subject_name(x), gens);
+       sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+       sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+       return ret;
+}
+
+
+static STACK *get_email(X509_NAME *name, STACK_OF(GENERAL_NAME) *gens)
+{
+       STACK *ret = NULL;
+       X509_NAME_ENTRY *ne;
+       ASN1_IA5STRING *email;
+       GENERAL_NAME *gen;
+       int i;
+       /* Now add any email address(es) to STACK */
+       i = -1;
+       /* First supplied X509_NAME */
+       while((i = X509_NAME_get_index_by_NID(name,
+                                        NID_pkcs9_emailAddress, i)) > 0) {
+               ne = X509_NAME_get_entry(name, i);
+               email = X509_NAME_ENTRY_get_data(ne);
+               if(!append_ia5(&ret, email)) return NULL;
+       }
+       for(i = 0; i < sk_GENERAL_NAME_num(gens); i++)
+       {
+               gen = sk_GENERAL_NAME_value(gens, i);
+               if(gen->type != GEN_EMAIL) continue;
+               if(!append_ia5(&ret, gen->d.ia5)) return NULL;
+       }
+       return ret;
+}
+
+static void str_free(void *str)
+{
+       OPENSSL_free(str);
+}
+
+static int append_ia5(STACK **sk, ASN1_IA5STRING *email)
+{
+       char *emtmp;
+       /* First some sanity checks */
+       if(email->type != V_ASN1_IA5STRING) return 1;
+       if(!email->data || !email->length) return 1;
+       if(!*sk) *sk = sk_new(sk_strcmp);
+       if(!*sk) return 0;
+       /* Don't add duplicates */
+       if(sk_find(*sk, (char *)email->data) != -1) return 1;
+       emtmp = BUF_strdup((char *)email->data);
+       if(!emtmp || !sk_push(*sk, emtmp)) {
+               X509_email_free(*sk);
+               *sk = NULL;
+               return 0;
+       }
+       return 1;
+}
+
+void X509_email_free(STACK *sk)
+{
+       sk_pop_free(sk, str_free);
+}