Some more prototype fixes.
[openssl.git] / crypto / asn1 / a_mbstr.c
index ce413ec3de79e1d96c2de29ef1eca0d314b42e0d..5d981c655387c385fcaeb7b44eb75a3a72aabf4b 100644 (file)
@@ -57,6 +57,7 @@
  */
 
 #include <stdio.h>
  */
 
 #include <stdio.h>
+#include <ctype.h>
 #include "cryptlib.h"
 #include <openssl/asn1.h>
 
 #include "cryptlib.h"
 #include <openssl/asn1.h>
 
@@ -71,24 +72,35 @@ static int cpy_univ(unsigned long value, void *arg);
 static int cpy_utf8(unsigned long value, void *arg);
 static int is_printable(unsigned long value);
 
 static int cpy_utf8(unsigned long value, void *arg);
 static int is_printable(unsigned long value);
 
-/* This function takes a string in UTF8, ASCII or multibyte form and
+/* These functions take a string in UTF8, ASCII or multibyte form and
  * a mask of permissible ASN1 string types. It then works out the minimal
  * type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
  * and creates a string of the correct type with the supplied data.
  * Yes this is horrible: it has to be :-(
  * a mask of permissible ASN1 string types. It then works out the minimal
  * type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
  * and creates a string of the correct type with the supplied data.
  * Yes this is horrible: it has to be :-(
+ * The 'ncopy' form checks minimum and maximum size limits too.
  */
 
 int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
  */
 
 int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
-                      int inform, unsigned long mask)
+                                       int inform, unsigned long mask)
+{
+       return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
+}
+
+int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
+                                       int inform, unsigned long mask, 
+                                       long minsize, long maxsize)
 {
        int str_type;
        int ret;
 {
        int str_type;
        int ret;
+       char free_out;
        int outform, outlen;
        ASN1_STRING *dest;
        unsigned char *p;
        int nchar;
        int outform, outlen;
        ASN1_STRING *dest;
        unsigned char *p;
        int nchar;
-       int (*cpyfunc)(unsigned long value, void *in_) = NULL;
+       char strbuf[32];
+       int (*cpyfunc)(unsigned long,void *) = NULL;
        if(len == -1) len = strlen((const char *)in);
        if(len == -1) len = strlen((const char *)in);
+       if(!mask) mask = DIRSTRING_TYPE;
 
        /* First do a string check and work out the number of characters */
        switch(inform) {
 
        /* First do a string check and work out the number of characters */
        switch(inform) {
@@ -113,6 +125,7 @@ int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
 
                case MBSTRING_UTF8:
                nchar = 0;
 
                case MBSTRING_UTF8:
                nchar = 0;
+               /* This counts the characters and does utf8 syntax checking */
                ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
                if(ret < 0) {
                        ASN1err(ASN1_F_ASN1_MBSTRING_COPY,
                ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
                if(ret < 0) {
                        ASN1err(ASN1_F_ASN1_MBSTRING_COPY,
@@ -130,12 +143,27 @@ int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
                return -1;
        }
 
                return -1;
        }
 
+       if((minsize > 0) && (nchar < minsize)) {
+               ASN1err(ASN1_F_ASN1_MBSTRING_COPY, ASN1_R_STRING_TOO_SHORT);
+               sprintf(strbuf, "%ld", minsize);
+               ERR_add_error_data(2, "minsize=", strbuf);
+               return -1;
+       }
+
+       if((maxsize > 0) && (nchar > maxsize)) {
+               ASN1err(ASN1_F_ASN1_MBSTRING_COPY, ASN1_R_STRING_TOO_LONG);
+               sprintf(strbuf, "%ld", maxsize);
+               ERR_add_error_data(2, "maxsize=", strbuf);
+               return -1;
+       }
+
        /* Now work out minimal type (if any) */
        if(traverse_string(in, len, inform, type_str, &mask) < 0) {
                ASN1err(ASN1_F_ASN1_MBSTRING_COPY, ASN1_R_ILLEGAL_CHARACTERS);
                return -1;
        }
 
        /* Now work out minimal type (if any) */
        if(traverse_string(in, len, inform, type_str, &mask) < 0) {
                ASN1err(ASN1_F_ASN1_MBSTRING_COPY, ASN1_R_ILLEGAL_CHARACTERS);
                return -1;
        }
 
+
        /* Now work out output format and string type */
        outform = MBSTRING_ASC;
        if(mask & B_ASN1_PRINTABLESTRING) str_type = V_ASN1_PRINTABLESTRING;
        /* Now work out output format and string type */
        outform = MBSTRING_ASC;
        if(mask & B_ASN1_PRINTABLESTRING) str_type = V_ASN1_PRINTABLESTRING;
@@ -152,15 +180,28 @@ int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
                outform = MBSTRING_UTF8;
        }
        if(!out) return str_type;
                outform = MBSTRING_UTF8;
        }
        if(!out) return str_type;
-       if(!(dest = ASN1_STRING_type_new(str_type))) {
-               ASN1err(ASN1_F_ASN1_MBSTRING_COPY, ERR_R_MALLOC_FAILURE);
-               return -1;
+       if(*out) {
+               free_out = 0;
+               dest = *out;
+               if(dest->data) {
+                       dest->length = 0;
+                       OPENSSL_free(dest->data);
+                       dest->data = NULL;
+               }
+               dest->type = str_type;
+       } else {
+               free_out = 1;
+               dest = ASN1_STRING_type_new(str_type);
+               if(!dest) {
+                       ASN1err(ASN1_F_ASN1_MBSTRING_COPY,
+                                                       ERR_R_MALLOC_FAILURE);
+                       return -1;
+               }
+               *out = dest;
        }
        }
-       *out = dest;
        /* If both the same type just copy across */
        if(inform == outform) {
                if(!ASN1_STRING_set(dest, in, len)) {
        /* If both the same type just copy across */
        if(inform == outform) {
                if(!ASN1_STRING_set(dest, in, len)) {
-                       ASN1_STRING_free(dest);
                        ASN1err(ASN1_F_ASN1_MBSTRING_COPY,ERR_R_MALLOC_FAILURE);
                        return -1;
                }
                        ASN1err(ASN1_F_ASN1_MBSTRING_COPY,ERR_R_MALLOC_FAILURE);
                        return -1;
                }
@@ -190,8 +231,8 @@ int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
                cpyfunc = cpy_utf8;
                break;
        }
                cpyfunc = cpy_utf8;
                break;
        }
-       if(!(p = Malloc(outlen + 1))) {
-               ASN1_STRING_free(dest);
+       if(!(p = OPENSSL_malloc(outlen + 1))) {
+               if(free_out) ASN1_STRING_free(dest);
                ASN1err(ASN1_F_ASN1_MBSTRING_COPY,ERR_R_MALLOC_FAILURE);
                return -1;
        }
                ASN1err(ASN1_F_ASN1_MBSTRING_COPY,ERR_R_MALLOC_FAILURE);
                return -1;
        }
@@ -220,8 +261,8 @@ static int traverse_string(const unsigned char *p, int len, int inform,
                        value |= *p++;
                        len -= 2;
                } else if(inform == MBSTRING_UNIV) {
                        value |= *p++;
                        len -= 2;
                } else if(inform == MBSTRING_UNIV) {
-                       value = *p++ << 24;
-                       value |= *p++ << 16;
+                       value = ((unsigned long)*p++) << 24;
+                       value |= ((unsigned long)*p++) << 16;
                        value |= *p++ << 8;
                        value |= *p++;
                        len -= 4;
                        value |= *p++ << 8;
                        value |= *p++;
                        len -= 4;
@@ -344,9 +385,16 @@ static int is_printable(unsigned long value)
        /* Note: we can't use 'isalnum' because certain accented 
         * characters may count as alphanumeric in some environments.
         */
        /* Note: we can't use 'isalnum' because certain accented 
         * characters may count as alphanumeric in some environments.
         */
+#ifndef CHARSET_EBCDIC
        if((ch >= 'a') && (ch <= 'z')) return 1;
        if((ch >= 'A') && (ch <= 'Z')) return 1;
        if((ch >= '0') && (ch <= '9')) return 1;
        if ((ch == ' ') || strchr("'()+,-./:=?", ch)) return 1;
        if((ch >= 'a') && (ch <= 'z')) return 1;
        if((ch >= 'A') && (ch <= 'Z')) return 1;
        if((ch >= '0') && (ch <= '9')) return 1;
        if ((ch == ' ') || strchr("'()+,-./:=?", ch)) return 1;
+#else /*CHARSET_EBCDIC*/
+       if((ch >= os_toascii['a']) && (ch <= os_toascii['z'])) return 1;
+       if((ch >= os_toascii['A']) && (ch <= os_toascii['Z'])) return 1;
+       if((ch >= os_toascii['0']) && (ch <= os_toascii['9'])) return 1;
+       if ((ch == os_toascii[' ']) || strchr("'()+,-./:=?", os_toebcdic[ch])) return 1;
+#endif /*CHARSET_EBCDIC*/
        return 0;
 }
        return 0;
 }