1 // Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <string.h>
16 
17 #include <openssl/mem.h>
18 #include <openssl/obj.h>
19 #include <openssl/stack.h>
20 #include <openssl/x509.h>
21 
22 #include "../internal.h"
23 #include "internal.h"
24 
25 
26 // X509_VERIFY_PARAM functions
27 
28 #define SET_HOST 0
29 #define ADD_HOST 1
30 
str_free(char * s)31 static void str_free(char *s) { OPENSSL_free(s); }
32 
int_x509_param_set_hosts(X509_VERIFY_PARAM * param,int mode,const char * name,size_t namelen)33 static int int_x509_param_set_hosts(X509_VERIFY_PARAM *param, int mode,
34                                     const char *name, size_t namelen) {
35   char *copy;
36 
37   if (name == NULL || namelen == 0) {
38     // Unlike OpenSSL, we reject trying to set or add an empty name.
39     return 0;
40   }
41 
42   // Refuse names with embedded NUL bytes.
43   // XXX: Do we need to push an error onto the error stack?
44   if (name && OPENSSL_memchr(name, '\0', namelen)) {
45     return 0;
46   }
47 
48   if (mode == SET_HOST && param->hosts) {
49     sk_OPENSSL_STRING_pop_free(param->hosts, str_free);
50     param->hosts = NULL;
51   }
52 
53   copy = OPENSSL_strndup(name, namelen);
54   if (copy == NULL) {
55     return 0;
56   }
57 
58   if (param->hosts == NULL &&
59       (param->hosts = sk_OPENSSL_STRING_new_null()) == NULL) {
60     OPENSSL_free(copy);
61     return 0;
62   }
63 
64   if (!sk_OPENSSL_STRING_push(param->hosts, copy)) {
65     OPENSSL_free(copy);
66     if (sk_OPENSSL_STRING_num(param->hosts) == 0) {
67       sk_OPENSSL_STRING_free(param->hosts);
68       param->hosts = NULL;
69     }
70     return 0;
71   }
72 
73   return 1;
74 }
75 
X509_VERIFY_PARAM_new(void)76 X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void) {
77   X509_VERIFY_PARAM *param = reinterpret_cast<X509_VERIFY_PARAM *>(
78       OPENSSL_zalloc(sizeof(X509_VERIFY_PARAM)));
79   if (!param) {
80     return NULL;
81   }
82   param->depth = -1;
83   return param;
84 }
85 
X509_VERIFY_PARAM_free(X509_VERIFY_PARAM * param)86 void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) {
87   if (param == NULL) {
88     return;
89   }
90   sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
91   sk_OPENSSL_STRING_pop_free(param->hosts, str_free);
92   OPENSSL_free(param->email);
93   OPENSSL_free(param->ip);
94   OPENSSL_free(param);
95 }
96 
should_copy(int dest_is_set,int src_is_set,int prefer_src)97 static int should_copy(int dest_is_set, int src_is_set, int prefer_src) {
98   if (prefer_src) {
99     // We prefer the source, so as long as there is a value to copy, copy it.
100     return src_is_set;
101   }
102 
103   // We prefer the destination, so only copy if the destination is unset.
104   return src_is_set && !dest_is_set;
105 }
106 
copy_int_param(int * dest,const int * src,int default_val,int prefer_src)107 static void copy_int_param(int *dest, const int *src, int default_val,
108                            int prefer_src) {
109   if (should_copy(*dest != default_val, *src != default_val, prefer_src)) {
110     *dest = *src;
111   }
112 }
113 
114 // x509_verify_param_copy copies fields from |src| to |dest|. If both |src| and
115 // |dest| have some field set, |prefer_src| determines whether |src| or |dest|'s
116 // version is used.
x509_verify_param_copy(X509_VERIFY_PARAM * dest,const X509_VERIFY_PARAM * src,int prefer_src)117 static int x509_verify_param_copy(X509_VERIFY_PARAM *dest,
118                                   const X509_VERIFY_PARAM *src,
119                                   int prefer_src) {
120   if (src == NULL) {
121     return 1;
122   }
123 
124   copy_int_param(&dest->purpose, &src->purpose, /*default_val=*/0, prefer_src);
125   copy_int_param(&dest->trust, &src->trust, /*default_val=*/0, prefer_src);
126   copy_int_param(&dest->depth, &src->depth, /*default_val=*/-1, prefer_src);
127 
128   // |check_time|, unlike all other parameters, does not honor |prefer_src|.
129   // This means |X509_VERIFY_PARAM_set1| will not overwrite it. This behavior
130   // comes from OpenSSL but may have been a bug.
131   if (!(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
132     dest->check_time = src->check_time;
133     // The source |X509_V_FLAG_USE_CHECK_TIME| flag, if set, is copied below.
134   }
135 
136   dest->flags |= src->flags;
137 
138   if (should_copy(dest->policies != NULL, src->policies != NULL, prefer_src)) {
139     if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies)) {
140       return 0;
141     }
142   }
143 
144   if (should_copy(dest->hosts != NULL, src->hosts != NULL, prefer_src)) {
145     sk_OPENSSL_STRING_pop_free(dest->hosts, str_free);
146     dest->hosts = NULL;
147     if (src->hosts) {
148       dest->hosts =
149           sk_OPENSSL_STRING_deep_copy(src->hosts, OPENSSL_strdup, str_free);
150       if (dest->hosts == NULL) {
151         return 0;
152       }
153       // Copy the host flags if and only if we're copying the host list. Note
154       // this means mechanisms like |X509_STORE_CTX_set_default| cannot be used
155       // to set host flags. E.g. we cannot change the defaults using
156       // |kDefaultParam| below.
157       dest->hostflags = src->hostflags;
158     }
159   }
160 
161   if (should_copy(dest->email != NULL, src->email != NULL, prefer_src)) {
162     if (!X509_VERIFY_PARAM_set1_email(dest, src->email, src->emaillen)) {
163       return 0;
164     }
165   }
166 
167   if (should_copy(dest->ip != NULL, src->ip != NULL, prefer_src)) {
168     if (!X509_VERIFY_PARAM_set1_ip(dest, src->ip, src->iplen)) {
169       return 0;
170     }
171   }
172 
173   dest->poison = src->poison;
174   return 1;
175 }
176 
X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM * dest,const X509_VERIFY_PARAM * src)177 int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
178                               const X509_VERIFY_PARAM *src) {
179   // Prefer the destination. That is, this function only changes unset
180   // parameters in |dest|.
181   return x509_verify_param_copy(dest, src, /*prefer_src=*/0);
182 }
183 
X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM * to,const X509_VERIFY_PARAM * from)184 int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
185                            const X509_VERIFY_PARAM *from) {
186   // Prefer the source. That is, values in |to| are only preserved if they were
187   // unset in |from|.
188   return x509_verify_param_copy(to, from, /*prefer_src=*/1);
189 }
190 
int_x509_param_set1(char ** pdest,size_t * pdestlen,const char * src,size_t srclen)191 static int int_x509_param_set1(char **pdest, size_t *pdestlen, const char *src,
192                                size_t srclen) {
193   void *tmp;
194   if (src == NULL || srclen == 0) {
195     // Unlike OpenSSL, we do not allow an empty string to disable previously
196     // configured checks.
197     return 0;
198   }
199 
200   tmp = OPENSSL_memdup(src, srclen);
201   if (!tmp) {
202     return 0;
203   }
204 
205   if (*pdest) {
206     OPENSSL_free(*pdest);
207   }
208   *pdest = reinterpret_cast<char *>(tmp);
209   if (pdestlen) {
210     *pdestlen = srclen;
211   }
212   return 1;
213 }
214 
X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM * param,unsigned long flags)215 int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags) {
216   param->flags |= flags;
217   return 1;
218 }
219 
X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM * param,unsigned long flags)220 int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
221                                   unsigned long flags) {
222   param->flags &= ~flags;
223   return 1;
224 }
225 
X509_VERIFY_PARAM_get_flags(const X509_VERIFY_PARAM * param)226 unsigned long X509_VERIFY_PARAM_get_flags(const X509_VERIFY_PARAM *param) {
227   return param->flags;
228 }
229 
X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM * param,int purpose)230 int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose) {
231   if (X509_PURPOSE_get0(purpose) == NULL) {
232     OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PURPOSE);
233     return 0;
234   }
235   param->purpose = purpose;
236   return 1;
237 }
238 
X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM * param,int trust)239 int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust) {
240   if (!X509_is_valid_trust_id(trust)) {
241     OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_TRUST_ID);
242     return 0;
243   }
244 
245   param->trust = trust;
246   return 1;
247 }
248 
X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM * param,int depth)249 void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth) {
250   param->depth = depth;
251 }
252 
X509_VERIFY_PARAM_set_time_posix(X509_VERIFY_PARAM * param,int64_t t)253 void X509_VERIFY_PARAM_set_time_posix(X509_VERIFY_PARAM *param, int64_t t) {
254   param->check_time = t;
255   param->flags |= X509_V_FLAG_USE_CHECK_TIME;
256 }
257 
X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM * param,time_t t)258 void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t) {
259   X509_VERIFY_PARAM_set_time_posix(param, t);
260 }
261 
X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM * param,ASN1_OBJECT * policy)262 int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
263                                   ASN1_OBJECT *policy) {
264   if (!param->policies) {
265     param->policies = sk_ASN1_OBJECT_new_null();
266     if (!param->policies) {
267       return 0;
268     }
269   }
270   if (!sk_ASN1_OBJECT_push(param->policies, policy)) {
271     return 0;
272   }
273   return 1;
274 }
275 
X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM * param,const STACK_OF (ASN1_OBJECT)* policies)276 int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
277                                     const STACK_OF(ASN1_OBJECT) *policies) {
278   if (!param) {
279     return 0;
280   }
281 
282   sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
283   if (!policies) {
284     param->policies = NULL;
285     return 1;
286   }
287 
288   param->policies =
289       sk_ASN1_OBJECT_deep_copy(policies, OBJ_dup, ASN1_OBJECT_free);
290   if (!param->policies) {
291     return 0;
292   }
293 
294   return 1;
295 }
296 
X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM * param,const char * name,size_t namelen)297 int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, const char *name,
298                                 size_t namelen) {
299   if (!int_x509_param_set_hosts(param, SET_HOST, name, namelen)) {
300     param->poison = 1;
301     return 0;
302   }
303   return 1;
304 }
305 
X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM * param,const char * name,size_t namelen)306 int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, const char *name,
307                                 size_t namelen) {
308   if (!int_x509_param_set_hosts(param, ADD_HOST, name, namelen)) {
309     param->poison = 1;
310     return 0;
311   }
312   return 1;
313 }
314 
X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM * param,unsigned int flags)315 void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
316                                      unsigned int flags) {
317   param->hostflags = flags;
318 }
319 
X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM * param,const char * email,size_t emaillen)320 int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email,
321                                  size_t emaillen) {
322   if (OPENSSL_memchr(email, '\0', emaillen) != NULL ||
323       !int_x509_param_set1(&param->email, &param->emaillen, email, emaillen)) {
324     param->poison = 1;
325     return 0;
326   }
327 
328   return 1;
329 }
330 
X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM * param,const unsigned char * ip,size_t iplen)331 int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip,
332                               size_t iplen) {
333   if ((iplen != 4 && iplen != 16) ||
334       !int_x509_param_set1((char **)&param->ip, &param->iplen, (char *)ip,
335                            iplen)) {
336     param->poison = 1;
337     return 0;
338   }
339 
340   return 1;
341 }
342 
X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM * param,const char * ipasc)343 int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc) {
344   unsigned char ipout[16];
345   size_t iplen;
346 
347   iplen = (size_t)x509v3_a2i_ipadd(ipout, ipasc);
348   if (iplen == 0) {
349     return 0;
350   }
351   return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
352 }
353 
X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM * param)354 int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param) {
355   return param->depth;
356 }
357 
358 static const X509_VERIFY_PARAM kDefaultParam = {
359     /*check_time=*/0,
360     /*flags=*/X509_V_FLAG_TRUSTED_FIRST,
361     /*purpose=*/0,
362     /*trust=*/0,
363     /*depth=*/100,
364     /*policies=*/nullptr,
365     /*hosts=*/nullptr,
366     /*hostflags=*/0,
367     /*email=*/nullptr,
368     /*emaillen=*/0,
369     /*ip=*/nullptr,
370     /*iplen=*/0,
371     /*poison=*/0,
372 };
373 
374 static const X509_VERIFY_PARAM kSMIMESignParam = {
375     /*check_time=*/0,
376     /*flags=*/0,
377     /*purpose=*/X509_PURPOSE_SMIME_SIGN,
378     /*trust=*/X509_TRUST_EMAIL,
379     /*depth=*/-1,
380     /*policies=*/nullptr,
381     /*hosts=*/nullptr,
382     /*hostflags=*/0,
383     /*email=*/nullptr,
384     /*emaillen=*/0,
385     /*ip=*/nullptr,
386     /*iplen=*/0,
387     /*poison=*/0,
388 };
389 
390 static const X509_VERIFY_PARAM kSSLClientParam = {
391     /*check_time=*/0,
392     /*flags=*/0,
393     /*purpose=*/X509_PURPOSE_SSL_CLIENT,
394     /*trust=*/X509_TRUST_SSL_CLIENT,
395     /*depth=*/-1,
396     /*policies=*/nullptr,
397     /*hosts=*/nullptr,
398     /*hostflags=*/0,
399     /*email=*/nullptr,
400     /*emaillen=*/0,
401     /*ip=*/nullptr,
402     /*iplen=*/0,
403     /*poison=*/0,
404 };
405 
406 static const X509_VERIFY_PARAM kSSLServerParam = {
407     /*check_time=*/0,
408     /*flags=*/0,
409     /*purpose=*/X509_PURPOSE_SSL_SERVER,
410     /*trust=*/X509_TRUST_SSL_SERVER,
411     /*depth=*/-1,
412     /*policies=*/nullptr,
413     /*hosts=*/nullptr,
414     /*hostflags=*/0,
415     /*email=*/nullptr,
416     /*emaillen=*/0,
417     /*ip=*/nullptr,
418     /*iplen=*/0,
419     /*poison=*/0,
420 };
421 
X509_VERIFY_PARAM_lookup(const char * name)422 const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name) {
423   if (strcmp(name, "default") == 0) {
424     return &kDefaultParam;
425   }
426   if (strcmp(name, "pkcs7") == 0) {
427     // PKCS#7 and S/MIME signing use the same defaults.
428     return &kSMIMESignParam;
429   }
430   if (strcmp(name, "smime_sign") == 0) {
431     return &kSMIMESignParam;
432   }
433   if (strcmp(name, "ssl_client") == 0) {
434     return &kSSLClientParam;
435   }
436   if (strcmp(name, "ssl_server") == 0) {
437     return &kSSLServerParam;
438   }
439   return NULL;
440 }
441