• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&param->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(&param->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(&param->email, &param->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 **)&param->ip, &param->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