xref: /openssl/crypto/x509/x509_obj.c (revision 7ed6de99)
1 /*
2  * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <stdio.h>
11 #include "internal/cryptlib.h"
12 #include <openssl/objects.h>
13 #include <openssl/x509.h>
14 #include <openssl/buffer.h>
15 #include "crypto/x509.h"
16 #include "crypto/ctype.h"
17 
18 /*
19  * Limit to ensure we don't overflow: much greater than
20  * anything encountered in practice.
21  */
22 
23 #define NAME_ONELINE_MAX    (1024 * 1024)
24 
X509_NAME_oneline(const X509_NAME * a,char * buf,int len)25 char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len)
26 {
27     const X509_NAME_ENTRY *ne;
28     int i;
29     int n, lold, l, l1, l2, num, j, type;
30     int prev_set = -1;
31     const char *s;
32     char *p;
33     unsigned char *q;
34     BUF_MEM *b = NULL;
35     int gs_doit[4];
36     char tmp_buf[80];
37 #ifdef CHARSET_EBCDIC
38     unsigned char ebcdic_buf[1024];
39 #endif
40 
41     if (buf == NULL) {
42         if ((b = BUF_MEM_new()) == NULL)
43             goto buferr;
44         if (!BUF_MEM_grow(b, 200))
45             goto buferr;
46         b->data[0] = '\0';
47         len = 200;
48     } else if (len == 0) {
49         return NULL;
50     }
51     if (a == NULL) {
52         if (b) {
53             buf = b->data;
54             OPENSSL_free(b);
55         }
56         strncpy(buf, "NO X509_NAME", len);
57         buf[len - 1] = '\0';
58         return buf;
59     }
60 
61     len--;                      /* space for '\0' */
62     l = 0;
63     for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
64         ne = sk_X509_NAME_ENTRY_value(a->entries, i);
65         n = OBJ_obj2nid(ne->object);
66         if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
67             i2t_ASN1_OBJECT(tmp_buf, sizeof(tmp_buf), ne->object);
68             s = tmp_buf;
69         }
70         l1 = strlen(s);
71 
72         type = ne->value->type;
73         num = ne->value->length;
74         if (num > NAME_ONELINE_MAX) {
75             ERR_raise(ERR_LIB_X509, X509_R_NAME_TOO_LONG);
76             goto end;
77         }
78         q = ne->value->data;
79 #ifdef CHARSET_EBCDIC
80         if (type == V_ASN1_GENERALSTRING ||
81             type == V_ASN1_VISIBLESTRING ||
82             type == V_ASN1_PRINTABLESTRING ||
83             type == V_ASN1_TELETEXSTRING ||
84             type == V_ASN1_IA5STRING) {
85             if (num > (int)sizeof(ebcdic_buf))
86                 num = sizeof(ebcdic_buf);
87             ascii2ebcdic(ebcdic_buf, q, num);
88             q = ebcdic_buf;
89         }
90 #endif
91 
92         if ((type == V_ASN1_GENERALSTRING) && ((num % 4) == 0)) {
93             gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 0;
94             for (j = 0; j < num; j++)
95                 if (q[j] != 0)
96                     gs_doit[j & 3] = 1;
97 
98             if (gs_doit[0] | gs_doit[1] | gs_doit[2])
99                 gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1;
100             else {
101                 gs_doit[0] = gs_doit[1] = gs_doit[2] = 0;
102                 gs_doit[3] = 1;
103             }
104         } else
105             gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1;
106 
107         for (l2 = j = 0; j < num; j++) {
108             if (!gs_doit[j & 3])
109                 continue;
110             l2++;
111             if (q[j] == '/' || q[j] == '+')
112                 l2++; /* char needs to be escaped */
113             else if ((ossl_toascii(q[j]) < ossl_toascii(' ')) ||
114                      (ossl_toascii(q[j]) > ossl_toascii('~')))
115                 l2 += 3;
116         }
117 
118         lold = l;
119         l += 1 + l1 + 1 + l2;
120         if (l > NAME_ONELINE_MAX) {
121             ERR_raise(ERR_LIB_X509, X509_R_NAME_TOO_LONG);
122             goto end;
123         }
124         if (b != NULL) {
125             if (!BUF_MEM_grow(b, l + 1))
126                 goto buferr;
127             p = &(b->data[lold]);
128         } else if (l > len) {
129             break;
130         } else
131             p = &(buf[lold]);
132         *(p++) = prev_set == ne->set ? '+' : '/';
133         memcpy(p, s, (unsigned int)l1);
134         p += l1;
135         *(p++) = '=';
136 
137 #ifndef CHARSET_EBCDIC          /* q was assigned above already. */
138         q = ne->value->data;
139 #endif
140 
141         for (j = 0; j < num; j++) {
142             if (!gs_doit[j & 3])
143                 continue;
144 #ifndef CHARSET_EBCDIC
145             n = q[j];
146             if ((n < ' ') || (n > '~')) {
147                 *(p++) = '\\';
148                 *(p++) = 'x';
149                 p += ossl_to_hex(p, n);
150             } else {
151                 if (n == '/' || n == '+')
152                     *(p++) = '\\';
153                 *(p++) = n;
154             }
155 #else
156             n = os_toascii[q[j]];
157             if ((n < os_toascii[' ']) || (n > os_toascii['~'])) {
158                 *(p++) = '\\';
159                 *(p++) = 'x';
160                 p += ossl_to_hex(p, n);
161             } else {
162                 if (n == os_toascii['/'] || n == os_toascii['+'])
163                     *(p++) = '\\';
164                 *(p++) = q[j];
165             }
166 #endif
167         }
168         *p = '\0';
169         prev_set = ne->set;
170     }
171     if (b != NULL) {
172         p = b->data;
173         OPENSSL_free(b);
174     } else
175         p = buf;
176     if (i == 0)
177         *p = '\0';
178     return p;
179  buferr:
180     ERR_raise(ERR_LIB_X509, ERR_R_BUF_LIB);
181  end:
182     BUF_MEM_free(b);
183     return NULL;
184 }
185