Overhaul 'crl' application, add a proper X509_CRL_print function and start
[openssl.git] / crypto / x509v3 / v3_utl.c
1 /* v3_utl.c */
2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3  * project 1999.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58 /* X509 v3 extension utilities */
59
60 #include <stdlib.h>
61 #include <string.h>
62 #include <ctype.h>
63 #include <pem.h>
64 #include <conf.h>
65 #include <err.h>
66 #include "x509v3.h"
67
68 static char * str_dup(char *str);
69 static char *strip_spaces(char *name);
70
71 static char *str_dup(str)
72 char *str;
73 {
74         char *tmp;
75         if(!(tmp = Malloc(strlen(str) + 1))) return NULL;
76         strcpy(tmp, str);
77         return tmp;
78 }
79
80 /* Add a CONF_VALUE name value pair to stack */
81
82 int X509V3_add_value(name, value, extlist)
83 char *name;
84 char *value;
85 STACK **extlist;
86 {
87         CONF_VALUE *vtmp = NULL;
88         char *tname = NULL, *tvalue = NULL;
89         if(name && !(tname = str_dup(name))) goto err;
90         if(value && !(tvalue = str_dup(value))) goto err;;
91         if(!(vtmp = (CONF_VALUE *)Malloc(sizeof(CONF_VALUE)))) goto err;
92         if(!*extlist && !(*extlist = sk_new(NULL))) goto err;
93         vtmp->section = NULL;
94         vtmp->name = tname;
95         vtmp->value = tvalue;
96         if(!sk_push(*extlist, (char *)vtmp)) goto err;
97         return 1;
98         err:
99         X509V3err(X509V3_F_X509V3_ADD_VALUE,ERR_R_MALLOC_FAILURE);
100         if(vtmp) Free(vtmp);
101         if(tname) Free(tname);
102         if(tvalue) Free(tvalue);
103         return 0;
104 }
105
106 /* Free function for STACK of CONF_VALUE */
107
108 void X509V3_conf_free(conf)
109 CONF_VALUE *conf;
110 {
111         if(!conf) return;
112         if(conf->name) Free(conf->name);
113         if(conf->value) Free(conf->value);
114         if(conf->section) Free(conf->section);
115         Free((char *)conf);
116 }
117
118 int X509V3_add_value_bool(name, asn1_bool, extlist)
119 char *name;
120 int asn1_bool;
121 STACK **extlist;
122 {
123         if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
124         return X509V3_add_value(name, "FALSE", extlist);
125 }
126
127 int X509V3_add_value_bool_nf(name, asn1_bool, extlist)
128 char *name;
129 int asn1_bool;
130 STACK **extlist;
131 {
132         if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
133         return 1;
134 }
135
136 char *i2s_ASN1_INTEGER(method, a)
137 X509V3_EXT_METHOD *method;
138 ASN1_INTEGER *a;
139 {
140         BIGNUM *bntmp = NULL;
141         char *strtmp = NULL;
142         if(!a) return NULL;
143         if(!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
144             !(strtmp = BN_bn2dec(bntmp)) )
145                 X509V3err(X509V3_F_I2S_ASN1_INTEGER,ERR_R_MALLOC_FAILURE);
146         BN_free(bntmp);
147         return strtmp;
148 }
149
150 int X509V3_add_value_int(name, aint, extlist)
151 char *name;
152 ASN1_INTEGER *aint;
153 STACK **extlist;
154 {
155         char *strtmp;
156         int ret;
157         if(!aint) return 1;
158         if(!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) return 0;
159         ret = X509V3_add_value(name, strtmp, extlist);
160         Free(strtmp);
161         return ret;
162 }
163
164 int X509V3_get_value_bool(value, asn1_bool)
165 CONF_VALUE *value;
166 int *asn1_bool;
167 {
168         char *btmp;
169         if(!(btmp = value->value)) goto err;
170         if(!strcmp(btmp, "TRUE") || !strcmp(btmp, "true")
171                  || !strcmp(btmp, "Y") || !strcmp(btmp, "y")
172                 || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
173                 *asn1_bool = 0xff;
174                 return 1;
175         } else if(!strcmp(btmp, "FALSE") || !strcmp(btmp, "false")
176                  || !strcmp(btmp, "N") || !strcmp(btmp, "n")
177                 || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
178                 *asn1_bool = 0;
179                 return 1;
180         }
181         err:
182         X509V3err(X509V3_F_X509V3_VALUE_GET_BOOL,X509V3_R_INVALID_BOOLEAN_STRING);
183         X509V3_conf_err(value);
184         return 0;
185 }
186
187 int X509V3_get_value_int(value, aint)
188 CONF_VALUE *value;
189 ASN1_INTEGER **aint;
190 {
191         BIGNUM *bn = NULL;
192         bn = BN_new();
193         if(!value->value) {
194                 X509V3err(X509V3_F_X509V3_GET_VALUE_INT,X509V3_R_INVALID_NULL_VALUE);
195                 X509V3_conf_err(value);
196                 return 0;
197         }
198         if(!BN_dec2bn(&bn, value->value)) {
199                 X509V3err(X509V3_F_X509V3_GET_VALUE_INT,X509V3_R_BN_DEC2BN_ERROR);
200                 X509V3_conf_err(value);
201                 return 0;
202         }
203
204         if(!(*aint = BN_to_ASN1_INTEGER(bn, NULL))) {
205                 X509V3err(X509V3_F_X509V3_GET_VALUE_INT,X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
206                 X509V3_conf_err(value);
207                 return 0;
208         }
209         BN_free(bn);
210         return 1;
211 }
212
213 #define HDR_NAME        1
214 #define HDR_VALUE       2
215
216 /*#define DEBUG*/
217
218 STACK *X509V3_parse_list(line)
219 char *line;
220 {
221         char *p, *q, c;
222         char *ntmp, *vtmp;
223         STACK *values = NULL;
224         char *linebuf;
225         int state;
226         /* We are going to modify the line so copy it first */
227         linebuf = str_dup(line);
228         state = HDR_NAME;
229         ntmp = NULL;
230         /* Go through all characters */
231         for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) {
232
233                 switch(state) {
234                         case HDR_NAME:
235                         if(c == ':') {
236                                 state = HDR_VALUE;
237                                 *p = 0;
238                                 ntmp = strip_spaces(q);
239                                 if(!ntmp) {
240                                         X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
241                                         goto err;
242                                 }
243                                 q = p + 1;
244                         } else if(c == ',') {
245                                 *p = 0;
246                                 ntmp = strip_spaces(q);
247                                 q = p + 1;
248 #ifdef DEBUG
249                                 printf("%s\n", ntmp);
250 #endif
251                                 if(!ntmp) {
252                                         X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
253                                         goto err;
254                                 }
255                                 X509V3_add_value(ntmp, NULL, &values);
256                         }
257                         break ;
258
259                         case HDR_VALUE:
260                         if(c == ',') {
261                                 state = HDR_NAME;
262                                 *p = 0;
263                                 vtmp = strip_spaces(q);
264 #ifdef DEBUG
265                                 printf("%s\n", ntmp);
266 #endif
267                                 if(!vtmp) {
268                                         X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE);
269                                         goto err;
270                                 }
271                                 X509V3_add_value(ntmp, vtmp, &values);
272                                 ntmp = NULL;
273                                 q = p + 1;
274                         }
275
276                 }
277         }
278
279         if(state == HDR_VALUE) {
280                 vtmp = strip_spaces(q);
281 #ifdef DEBUG
282                 printf("%s=%s\n", ntmp, vtmp);
283 #endif
284                 if(!vtmp) {
285                         X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE);
286                         goto err;
287                 }
288                 X509V3_add_value(ntmp, vtmp, &values);
289         } else {
290                 ntmp = strip_spaces(q);
291 #ifdef DEBUG
292                 printf("%s\n", ntmp);
293 #endif
294                 if(!ntmp) {
295                         X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
296                         goto err;
297                 }
298                 X509V3_add_value(ntmp, NULL, &values);
299         }
300 Free(linebuf);
301 return values;
302
303 err:
304 Free(linebuf);
305 sk_pop_free(values, X509V3_conf_free);
306 return NULL;
307
308 }
309
310 /* Delete leading and trailing spaces from a string */
311 static char *strip_spaces(name)
312 char *name;
313 {
314         char *p, *q;
315         /* Skip over leading spaces */
316         p = name;
317         while(*p && isspace(*p)) p++;
318         if(!*p) return NULL;
319         q = p + strlen(p) - 1;
320         while((q != p) && isspace(*q)) q--;
321         if(p != q) q[1] = 0;
322         if(!*p) return NULL;
323         return p;
324 }
325
326 /* hex string utilities */
327
328 /* Given a buffer of length 'len' return a Malloc'ed string with its
329  * hex representation
330  */
331
332 char *hex_to_string(buffer, len)
333 unsigned char *buffer;
334 long len;
335 {
336         char *tmp, *q;
337         unsigned char *p;
338         int i;
339         static char hexdig[] = "0123456789ABCDEF";
340         if(!buffer || !len) return NULL;
341         if(!(tmp = Malloc(len * 3 + 1))) {
342                 X509V3err(X509V3_F_HEX_TO_STRING,ERR_R_MALLOC_FAILURE);
343                 return NULL;
344         }
345         q = tmp;
346         for(i = 0, p = buffer; i < len; i++,p++) {
347                 *q++ = hexdig[(*p >> 4) & 0xf];
348                 *q++ = hexdig[*p & 0xf];
349                 *q++ = ':';
350         }
351         q[-1] = 0;
352         return tmp;
353 }
354
355 /* Give a string of hex digits convert to
356  * a buffer
357  */
358
359 unsigned char *string_to_hex(str, len)
360 char *str;
361 long *len;
362 {
363         unsigned char *hexbuf, *q;
364         unsigned char ch, cl, *p;
365         if(!str) {
366                 X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_INVALID_NULL_ARGUMENT);
367                 return NULL;
368         }
369         if(!(hexbuf = Malloc(strlen(str) >> 1))) goto err;
370         for(p = (unsigned char *)str, q = hexbuf; *p;) {
371                 ch = *p++;
372                 if(ch == ':') continue;
373                 cl = *p++;
374                 if(!cl) {
375                         X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ODD_NUMBER_OF_DIGITS);
376                         Free(hexbuf);
377                         return NULL;
378                 }
379                 if(isupper(ch)) ch = tolower(ch);
380                 if(isupper(cl)) cl = tolower(cl);
381
382                 if((ch >= '0') && (ch <= '9')) ch -= '0';
383                 else if ((ch >= 'a') && (ch <= 'f')) ch -= 'a' - 10;
384                 else goto badhex;
385
386                 if((cl >= '0') && (cl <= '9')) cl -= '0';
387                 else if ((cl >= 'a') && (cl <= 'f')) cl -= 'a' - 10;
388                 else goto badhex;
389
390                 *q++ = (ch << 4) | cl;
391         }
392
393         if(len) *len = q - hexbuf;
394
395         return hexbuf;
396
397         err:
398         if(hexbuf) Free(hexbuf);
399         X509V3err(X509V3_F_STRING_TO_HEX,ERR_R_MALLOC_FAILURE);
400         return NULL;
401
402         badhex:
403         Free(hexbuf);
404         X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ILLEGAL_HEX_DIGIT);
405         return NULL;
406
407 }
408
409 /* V2I name comparison function: returns zero if 'name' matches
410  * cmp or cmp.*
411  */
412
413 int name_cmp(name, cmp)
414 char *name;
415 char *cmp;
416 {
417         int len, ret;
418         char c;
419         len = strlen(cmp);
420         if((ret = strncmp(name, cmp, len))) return ret;
421         c = name[len];
422         if(!c || (c=='.')) return 0;
423         return 1;
424 }