1 /*
2 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3 * 2004.
4 */
5 /* ====================================================================
6 * Copyright (c) 2004 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 #include <string.h>
58
59 #include <openssl/mem.h>
60 #include <openssl/obj.h>
61 #include <openssl/stack.h>
62 #include <openssl/x509.h>
63 #include <openssl/x509v3.h>
64
65 #include "../internal.h"
66 #include "../x509v3/internal.h"
67 #include "internal.h"
68
69
70 // X509_VERIFY_PARAM functions
71
72 #define SET_HOST 0
73 #define ADD_HOST 1
74
str_free(char * s)75 static void str_free(char *s) { OPENSSL_free(s); }
76
77 #define string_stack_free(sk) sk_OPENSSL_STRING_pop_free(sk, str_free)
78
int_x509_param_set_hosts(X509_VERIFY_PARAM * param,int mode,const char * name,size_t namelen)79 static int int_x509_param_set_hosts(X509_VERIFY_PARAM *param, int mode,
80 const char *name, size_t namelen) {
81 char *copy;
82
83 if (name == NULL || namelen == 0) {
84 // Unlike OpenSSL, we reject trying to set or add an empty name.
85 return 0;
86 }
87
88 // Refuse names with embedded NUL bytes.
89 // XXX: Do we need to push an error onto the error stack?
90 if (name && OPENSSL_memchr(name, '\0', namelen)) {
91 return 0;
92 }
93
94 if (mode == SET_HOST && param->hosts) {
95 string_stack_free(param->hosts);
96 param->hosts = NULL;
97 }
98
99 copy = OPENSSL_strndup(name, namelen);
100 if (copy == NULL) {
101 return 0;
102 }
103
104 if (param->hosts == NULL &&
105 (param->hosts = sk_OPENSSL_STRING_new_null()) == NULL) {
106 OPENSSL_free(copy);
107 return 0;
108 }
109
110 if (!sk_OPENSSL_STRING_push(param->hosts, copy)) {
111 OPENSSL_free(copy);
112 if (sk_OPENSSL_STRING_num(param->hosts) == 0) {
113 sk_OPENSSL_STRING_free(param->hosts);
114 param->hosts = NULL;
115 }
116 return 0;
117 }
118
119 return 1;
120 }
121
x509_verify_param_zero(X509_VERIFY_PARAM * param)122 static void x509_verify_param_zero(X509_VERIFY_PARAM *param) {
123 if (!param) {
124 return;
125 }
126 param->name = NULL;
127 param->purpose = 0;
128 param->trust = 0;
129 // param->inh_flags = X509_VP_FLAG_DEFAULT;
130 param->inh_flags = 0;
131 param->flags = 0;
132 param->depth = -1;
133 if (param->policies) {
134 sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
135 param->policies = NULL;
136 }
137 if (param->hosts) {
138 string_stack_free(param->hosts);
139 param->hosts = NULL;
140 }
141 if (param->peername) {
142 OPENSSL_free(param->peername);
143 param->peername = NULL;
144 }
145 if (param->email) {
146 OPENSSL_free(param->email);
147 param->email = NULL;
148 param->emaillen = 0;
149 }
150 if (param->ip) {
151 OPENSSL_free(param->ip);
152 param->ip = NULL;
153 param->iplen = 0;
154 }
155 param->poison = 0;
156 }
157
X509_VERIFY_PARAM_new(void)158 X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void) {
159 X509_VERIFY_PARAM *param = OPENSSL_zalloc(sizeof(X509_VERIFY_PARAM));
160 if (!param) {
161 return NULL;
162 }
163 x509_verify_param_zero(param);
164 return param;
165 }
166
X509_VERIFY_PARAM_free(X509_VERIFY_PARAM * param)167 void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) {
168 if (param == NULL) {
169 return;
170 }
171 x509_verify_param_zero(param);
172 OPENSSL_free(param);
173 }
174
175 //-
176 // This function determines how parameters are "inherited" from one structure
177 // to another. There are several different ways this can happen.
178 //
179 // 1. If a child structure needs to have its values initialized from a parent
180 // they are simply copied across. For example SSL_CTX copied to SSL.
181 // 2. If the structure should take on values only if they are currently unset.
182 // For example the values in an SSL structure will take appropriate value
183 // for SSL servers or clients but only if the application has not set new
184 // ones.
185 //
186 // The "inh_flags" field determines how this function behaves.
187 //
188 // Normally any values which are set in the default are not copied from the
189 // destination and verify flags are ORed together.
190 //
191 // If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied
192 // to the destination. Effectively the values in "to" become default values
193 // which will be used only if nothing new is set in "from".
194 //
195 // If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether
196 // they are set or not. Flags is still Ored though.
197 //
198 // If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead
199 // of ORed.
200 //
201 // If X509_VP_FLAG_LOCKED is set then no values are copied.
202 //
203 // If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed
204 // after the next call.
205
206 // Macro to test if a field should be copied from src to dest
207
208 #define test_x509_verify_param_copy(field, def) \
209 (to_overwrite || \
210 ((src->field != (def)) && (to_default || (dest->field == (def)))))
211
212 // Macro to test and copy a field if necessary
213
214 #define x509_verify_param_copy(field, def) \
215 if (test_x509_verify_param_copy(field, def)) \
216 dest->field = src->field
217
X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM * dest,const X509_VERIFY_PARAM * src)218 int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
219 const X509_VERIFY_PARAM *src) {
220 unsigned long inh_flags;
221 int to_default, to_overwrite;
222 if (!src) {
223 return 1;
224 }
225 inh_flags = dest->inh_flags | src->inh_flags;
226
227 if (inh_flags & X509_VP_FLAG_ONCE) {
228 dest->inh_flags = 0;
229 }
230
231 if (inh_flags & X509_VP_FLAG_LOCKED) {
232 return 1;
233 }
234
235 if (inh_flags & X509_VP_FLAG_DEFAULT) {
236 to_default = 1;
237 } else {
238 to_default = 0;
239 }
240
241 if (inh_flags & X509_VP_FLAG_OVERWRITE) {
242 to_overwrite = 1;
243 } else {
244 to_overwrite = 0;
245 }
246
247 x509_verify_param_copy(purpose, 0);
248 x509_verify_param_copy(trust, 0);
249 x509_verify_param_copy(depth, -1);
250
251 // If overwrite or check time not set, copy across
252
253 if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
254 dest->check_time = src->check_time;
255 dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
256 // Don't need to copy flag: that is done below
257 }
258
259 if (inh_flags & X509_VP_FLAG_RESET_FLAGS) {
260 dest->flags = 0;
261 }
262
263 dest->flags |= src->flags;
264
265 if (test_x509_verify_param_copy(policies, NULL)) {
266 if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies)) {
267 return 0;
268 }
269 }
270
271 // Copy the host flags if and only if we're copying the host list
272 if (test_x509_verify_param_copy(hosts, NULL)) {
273 if (dest->hosts) {
274 string_stack_free(dest->hosts);
275 dest->hosts = NULL;
276 }
277 if (src->hosts) {
278 dest->hosts =
279 sk_OPENSSL_STRING_deep_copy(src->hosts, OPENSSL_strdup, str_free);
280 if (dest->hosts == NULL) {
281 return 0;
282 }
283 dest->hostflags = src->hostflags;
284 }
285 }
286
287 if (test_x509_verify_param_copy(email, NULL)) {
288 if (!X509_VERIFY_PARAM_set1_email(dest, src->email, src->emaillen)) {
289 return 0;
290 }
291 }
292
293 if (test_x509_verify_param_copy(ip, NULL)) {
294 if (!X509_VERIFY_PARAM_set1_ip(dest, src->ip, src->iplen)) {
295 return 0;
296 }
297 }
298
299 dest->poison = src->poison;
300
301 return 1;
302 }
303
X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM * to,const X509_VERIFY_PARAM * from)304 int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
305 const X509_VERIFY_PARAM *from) {
306 unsigned long save_flags = to->inh_flags;
307 int ret;
308 to->inh_flags |= X509_VP_FLAG_DEFAULT;
309 ret = X509_VERIFY_PARAM_inherit(to, from);
310 to->inh_flags = save_flags;
311 return ret;
312 }
313
int_x509_param_set1(char ** pdest,size_t * pdestlen,const char * src,size_t srclen)314 static int int_x509_param_set1(char **pdest, size_t *pdestlen, const char *src,
315 size_t srclen) {
316 void *tmp;
317 if (src == NULL || srclen == 0) {
318 // Unlike OpenSSL, we do not allow an empty string to disable previously
319 // configured checks.
320 return 0;
321 }
322
323 tmp = OPENSSL_memdup(src, srclen);
324 if (!tmp) {
325 return 0;
326 }
327
328 if (*pdest) {
329 OPENSSL_free(*pdest);
330 }
331 *pdest = tmp;
332 if (pdestlen) {
333 *pdestlen = srclen;
334 }
335 return 1;
336 }
337
X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM * param,const char * name)338 int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name) {
339 if (param->name) {
340 OPENSSL_free(param->name);
341 }
342 param->name = OPENSSL_strdup(name);
343 if (param->name) {
344 return 1;
345 }
346 return 0;
347 }
348
X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM * param,unsigned long flags)349 int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags) {
350 param->flags |= flags;
351 return 1;
352 }
353
X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM * param,unsigned long flags)354 int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
355 unsigned long flags) {
356 param->flags &= ~flags;
357 return 1;
358 }
359
X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM * param)360 unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param) {
361 return param->flags;
362 }
363
X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM * param,int purpose)364 int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose) {
365 return X509_PURPOSE_set(¶m->purpose, purpose);
366 }
367
X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM * param,int trust)368 int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust) {
369 return X509_TRUST_set(¶m->trust, trust);
370 }
371
X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM * param,int depth)372 void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth) {
373 param->depth = depth;
374 }
375
X509_VERIFY_PARAM_set_time_posix(X509_VERIFY_PARAM * param,int64_t t)376 void X509_VERIFY_PARAM_set_time_posix(X509_VERIFY_PARAM *param, int64_t t) {
377 param->check_time = t;
378 param->flags |= X509_V_FLAG_USE_CHECK_TIME;
379 }
380
X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM * param,time_t t)381 void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t) {
382 X509_VERIFY_PARAM_set_time_posix(param, t);
383 }
384
X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM * param,ASN1_OBJECT * policy)385 int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
386 ASN1_OBJECT *policy) {
387 if (!param->policies) {
388 param->policies = sk_ASN1_OBJECT_new_null();
389 if (!param->policies) {
390 return 0;
391 }
392 }
393 if (!sk_ASN1_OBJECT_push(param->policies, policy)) {
394 return 0;
395 }
396 return 1;
397 }
398
X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM * param,const STACK_OF (ASN1_OBJECT)* policies)399 int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
400 const STACK_OF(ASN1_OBJECT) *policies) {
401 if (!param) {
402 return 0;
403 }
404
405 sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
406 if (!policies) {
407 param->policies = NULL;
408 return 1;
409 }
410
411 param->policies =
412 sk_ASN1_OBJECT_deep_copy(policies, OBJ_dup, ASN1_OBJECT_free);
413 if (!param->policies) {
414 return 0;
415 }
416
417 return 1;
418 }
419
X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM * param,const char * name,size_t namelen)420 int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, const char *name,
421 size_t namelen) {
422 if (!int_x509_param_set_hosts(param, SET_HOST, name, namelen)) {
423 param->poison = 1;
424 return 0;
425 }
426 return 1;
427 }
428
X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM * param,const char * name,size_t namelen)429 int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, const char *name,
430 size_t namelen) {
431 if (!int_x509_param_set_hosts(param, ADD_HOST, name, namelen)) {
432 param->poison = 1;
433 return 0;
434 }
435 return 1;
436 }
437
X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM * param,unsigned int flags)438 void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
439 unsigned int flags) {
440 param->hostflags = flags;
441 }
442
X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM * param)443 char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param) {
444 return param->peername;
445 }
446
X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM * param,const char * email,size_t emaillen)447 int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email,
448 size_t emaillen) {
449 if (OPENSSL_memchr(email, '\0', emaillen) != NULL ||
450 !int_x509_param_set1(¶m->email, ¶m->emaillen, email, emaillen)) {
451 param->poison = 1;
452 return 0;
453 }
454
455 return 1;
456 }
457
X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM * param,const unsigned char * ip,size_t iplen)458 int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip,
459 size_t iplen) {
460 if ((iplen != 4 && iplen != 16) ||
461 !int_x509_param_set1((char **)¶m->ip, ¶m->iplen, (char *)ip,
462 iplen)) {
463 param->poison = 1;
464 return 0;
465 }
466
467 return 1;
468 }
469
X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM * param,const char * ipasc)470 int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc) {
471 unsigned char ipout[16];
472 size_t iplen;
473
474 iplen = (size_t)x509v3_a2i_ipadd(ipout, ipasc);
475 if (iplen == 0) {
476 return 0;
477 }
478 return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
479 }
480
X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM * param)481 int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param) {
482 return param->depth;
483 }
484
X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM * param)485 const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param) {
486 return param->name;
487 }
488
489 #define vpm_empty_id NULL, 0U, NULL, NULL, 0, NULL, 0, 0
490
491 // Default verify parameters: these are used for various applications and can
492 // be overridden by the user specified table. NB: the 'name' field *must* be
493 // in alphabetical order because it will be searched using OBJ_search.
494
495 static const X509_VERIFY_PARAM default_table[] = {
496 {(char *)"default", // X509 default parameters
497 0, // Check time
498 0, // internal flags
499 X509_V_FLAG_TRUSTED_FIRST, // flags
500 0, // purpose
501 0, // trust
502 100, // depth
503 NULL, // policies
504 vpm_empty_id},
505 {(char *)"pkcs7", // S/MIME sign parameters
506 0, // Check time
507 0, // internal flags
508 0, // flags
509 X509_PURPOSE_SMIME_SIGN, // purpose
510 X509_TRUST_EMAIL, // trust
511 -1, // depth
512 NULL, // policies
513 vpm_empty_id},
514 {(char *)"smime_sign", // S/MIME sign parameters
515 0, // Check time
516 0, // internal flags
517 0, // flags
518 X509_PURPOSE_SMIME_SIGN, // purpose
519 X509_TRUST_EMAIL, // trust
520 -1, // depth
521 NULL, // policies
522 vpm_empty_id},
523 {(char *)"ssl_client", // SSL/TLS client parameters
524 0, // Check time
525 0, // internal flags
526 0, // flags
527 X509_PURPOSE_SSL_CLIENT, // purpose
528 X509_TRUST_SSL_CLIENT, // trust
529 -1, // depth
530 NULL, // policies
531 vpm_empty_id},
532 {(char *)"ssl_server", // SSL/TLS server parameters
533 0, // Check time
534 0, // internal flags
535 0, // flags
536 X509_PURPOSE_SSL_SERVER, // purpose
537 X509_TRUST_SSL_SERVER, // trust
538 -1, // depth
539 NULL, // policies
540 vpm_empty_id}};
541
X509_VERIFY_PARAM_lookup(const char * name)542 const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name) {
543 for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(default_table); i++) {
544 if (strcmp(default_table[i].name, name) == 0) {
545 return &default_table[i];
546 }
547 }
548 return NULL;
549 }
550