summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/x509/by_dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/x509/by_dir.c')
-rw-r--r--src/lib/libcrypto/x509/by_dir.c226
1 files changed, 161 insertions, 65 deletions
diff --git a/src/lib/libcrypto/x509/by_dir.c b/src/lib/libcrypto/x509/by_dir.c
index 341e0ba6a4..27ca5150c1 100644
--- a/src/lib/libcrypto/x509/by_dir.c
+++ b/src/lib/libcrypto/x509/by_dir.c
@@ -65,28 +65,36 @@
65#ifndef NO_SYS_TYPES_H 65#ifndef NO_SYS_TYPES_H
66# include <sys/types.h> 66# include <sys/types.h>
67#endif 67#endif
68#ifdef MAC_OS_pre_X 68#ifndef OPENSSL_NO_POSIX_IO
69# include <stat.h>
70#else
71# include <sys/stat.h> 69# include <sys/stat.h>
72#endif 70#endif
73 71
74#include <openssl/lhash.h> 72#include <openssl/lhash.h>
75#include <openssl/x509.h> 73#include <openssl/x509.h>
76 74
77#ifdef _WIN32 75
78#define stat _stat 76typedef struct lookup_dir_hashes_st
79#endif 77 {
78 unsigned long hash;
79 int suffix;
80 } BY_DIR_HASH;
81
82typedef struct lookup_dir_entry_st
83 {
84 char *dir;
85 int dir_type;
86 STACK_OF(BY_DIR_HASH) *hashes;
87 } BY_DIR_ENTRY;
80 88
81typedef struct lookup_dir_st 89typedef struct lookup_dir_st
82 { 90 {
83 BUF_MEM *buffer; 91 BUF_MEM *buffer;
84 int num_dirs; 92 STACK_OF(BY_DIR_ENTRY) *dirs;
85 char **dirs;
86 int *dirs_type;
87 int num_dirs_alloced;
88 } BY_DIR; 93 } BY_DIR;
89 94
95DECLARE_STACK_OF(BY_DIR_HASH)
96DECLARE_STACK_OF(BY_DIR_ENTRY)
97
90static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, 98static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
91 char **ret); 99 char **ret);
92static int new_dir(X509_LOOKUP *lu); 100static int new_dir(X509_LOOKUP *lu);
@@ -127,7 +135,7 @@ static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
127 case X509_L_ADD_DIR: 135 case X509_L_ADD_DIR:
128 if (argl == X509_FILETYPE_DEFAULT) 136 if (argl == X509_FILETYPE_DEFAULT)
129 { 137 {
130 dir=(char *)Getenv(X509_get_default_cert_dir_env()); 138 dir=(char *)getenv(X509_get_default_cert_dir_env());
131 if (dir) 139 if (dir)
132 ret=add_cert_dir(ld,dir,X509_FILETYPE_PEM); 140 ret=add_cert_dir(ld,dir,X509_FILETYPE_PEM);
133 else 141 else
@@ -156,34 +164,51 @@ static int new_dir(X509_LOOKUP *lu)
156 OPENSSL_free(a); 164 OPENSSL_free(a);
157 return(0); 165 return(0);
158 } 166 }
159 a->num_dirs=0;
160 a->dirs=NULL; 167 a->dirs=NULL;
161 a->dirs_type=NULL;
162 a->num_dirs_alloced=0;
163 lu->method_data=(char *)a; 168 lu->method_data=(char *)a;
164 return(1); 169 return(1);
165 } 170 }
166 171
172static void by_dir_hash_free(BY_DIR_HASH *hash)
173 {
174 OPENSSL_free(hash);
175 }
176
177static int by_dir_hash_cmp(const BY_DIR_HASH * const *a,
178 const BY_DIR_HASH * const *b)
179 {
180 if ((*a)->hash > (*b)->hash)
181 return 1;
182 if ((*a)->hash < (*b)->hash)
183 return -1;
184 return 0;
185 }
186
187static void by_dir_entry_free(BY_DIR_ENTRY *ent)
188 {
189 if (ent->dir)
190 OPENSSL_free(ent->dir);
191 if (ent->hashes)
192 sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free);
193 OPENSSL_free(ent);
194 }
195
167static void free_dir(X509_LOOKUP *lu) 196static void free_dir(X509_LOOKUP *lu)
168 { 197 {
169 BY_DIR *a; 198 BY_DIR *a;
170 int i;
171 199
172 a=(BY_DIR *)lu->method_data; 200 a=(BY_DIR *)lu->method_data;
173 for (i=0; i<a->num_dirs; i++) 201 if (a->dirs != NULL)
174 if (a->dirs[i] != NULL) OPENSSL_free(a->dirs[i]); 202 sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free);
175 if (a->dirs != NULL) OPENSSL_free(a->dirs); 203 if (a->buffer != NULL)
176 if (a->dirs_type != NULL) OPENSSL_free(a->dirs_type); 204 BUF_MEM_free(a->buffer);
177 if (a->buffer != NULL) BUF_MEM_free(a->buffer);
178 OPENSSL_free(a); 205 OPENSSL_free(a);
179 } 206 }
180 207
181static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) 208static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
182 { 209 {
183 int j,len; 210 int j,len;
184 int *ip;
185 const char *s,*ss,*p; 211 const char *s,*ss,*p;
186 char **pp;
187 212
188 if (dir == NULL || !*dir) 213 if (dir == NULL || !*dir)
189 { 214 {
@@ -197,49 +222,52 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
197 { 222 {
198 if ((*p == LIST_SEPARATOR_CHAR) || (*p == '\0')) 223 if ((*p == LIST_SEPARATOR_CHAR) || (*p == '\0'))
199 { 224 {
225 BY_DIR_ENTRY *ent;
200 ss=s; 226 ss=s;
201 s=p+1; 227 s=p+1;
202 len=(int)(p-ss); 228 len=(int)(p-ss);
203 if (len == 0) continue; 229 if (len == 0) continue;
204 for (j=0; j<ctx->num_dirs; j++) 230 for (j=0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++)
205 if (strlen(ctx->dirs[j]) == (size_t)len && 231 {
206 strncmp(ctx->dirs[j],ss,(unsigned int)len) == 0) 232 ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j);
233 if (strlen(ent->dir) == (size_t)len &&
234 strncmp(ent->dir,ss,(unsigned int)len) == 0)
207 break; 235 break;
208 if (j<ctx->num_dirs) 236 }
237 if (j < sk_BY_DIR_ENTRY_num(ctx->dirs))
209 continue; 238 continue;
210 if (ctx->num_dirs_alloced < (ctx->num_dirs+1)) 239 if (ctx->dirs == NULL)
211 { 240 {
212 ctx->num_dirs_alloced+=10; 241 ctx->dirs = sk_BY_DIR_ENTRY_new_null();
213 pp=(char **)OPENSSL_malloc(ctx->num_dirs_alloced* 242 if (!ctx->dirs)
214 sizeof(char *));
215 ip=(int *)OPENSSL_malloc(ctx->num_dirs_alloced*
216 sizeof(int));
217 if ((pp == NULL) || (ip == NULL))
218 { 243 {
219 X509err(X509_F_ADD_CERT_DIR,ERR_R_MALLOC_FAILURE); 244 X509err(X509_F_ADD_CERT_DIR,ERR_R_MALLOC_FAILURE);
220 return(0); 245 return 0;
221 } 246 }
222 memcpy(pp,ctx->dirs,(ctx->num_dirs_alloced-10)*
223 sizeof(char *));
224 memcpy(ip,ctx->dirs_type,(ctx->num_dirs_alloced-10)*
225 sizeof(int));
226 if (ctx->dirs != NULL)
227 OPENSSL_free(ctx->dirs);
228 if (ctx->dirs_type != NULL)
229 OPENSSL_free(ctx->dirs_type);
230 ctx->dirs=pp;
231 ctx->dirs_type=ip;
232 } 247 }
233 ctx->dirs_type[ctx->num_dirs]=type; 248 ent = OPENSSL_malloc(sizeof(BY_DIR_ENTRY));
234 ctx->dirs[ctx->num_dirs]=(char *)OPENSSL_malloc((unsigned int)len+1); 249 if (!ent)
235 if (ctx->dirs[ctx->num_dirs] == NULL) return(0); 250 return 0;
236 strncpy(ctx->dirs[ctx->num_dirs],ss,(unsigned int)len); 251 ent->dir_type = type;
237 ctx->dirs[ctx->num_dirs][len]='\0'; 252 ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp);
238 ctx->num_dirs++; 253 ent->dir = OPENSSL_malloc((unsigned int)len+1);
254 if (!ent->dir || !ent->hashes)
255 {
256 by_dir_entry_free(ent);
257 return 0;
258 }
259 strncpy(ent->dir,ss,(unsigned int)len);
260 ent->dir[len] = '\0';
261 if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent))
262 {
263 by_dir_entry_free(ent);
264 return 0;
265 }
239 } 266 }
240 if (*p == '\0') break; 267 if (*p == '\0')
268 break;
241 } 269 }
242 return(1); 270 return 1;
243 } 271 }
244 272
245static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, 273static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
@@ -260,7 +288,6 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
260 int i,j,k; 288 int i,j,k;
261 unsigned long h; 289 unsigned long h;
262 BUF_MEM *b=NULL; 290 BUF_MEM *b=NULL;
263 struct stat st;
264 X509_OBJECT stmp,*tmp; 291 X509_OBJECT stmp,*tmp;
265 const char *postfix=""; 292 const char *postfix="";
266 293
@@ -296,20 +323,45 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
296 ctx=(BY_DIR *)xl->method_data; 323 ctx=(BY_DIR *)xl->method_data;
297 324
298 h=X509_NAME_hash(name); 325 h=X509_NAME_hash(name);
299 for (i=0; i<ctx->num_dirs; i++) 326 for (i=0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++)
300 { 327 {
301 j=strlen(ctx->dirs[i])+1+8+6+1+1; 328 BY_DIR_ENTRY *ent;
329 int idx;
330 BY_DIR_HASH htmp, *hent;
331 ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i);
332 j=strlen(ent->dir)+1+8+6+1+1;
302 if (!BUF_MEM_grow(b,j)) 333 if (!BUF_MEM_grow(b,j))
303 { 334 {
304 X509err(X509_F_GET_CERT_BY_SUBJECT,ERR_R_MALLOC_FAILURE); 335 X509err(X509_F_GET_CERT_BY_SUBJECT,ERR_R_MALLOC_FAILURE);
305 goto finish; 336 goto finish;
306 } 337 }
307 k=0; 338 if (type == X509_LU_CRL && ent->hashes)
339 {
340 htmp.hash = h;
341 CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE);
342 idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);
343 if (idx >= 0)
344 {
345 hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
346 k = hent->suffix;
347 }
348 else
349 {
350 hent = NULL;
351 k=0;
352 }
353 CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE);
354 }
355 else
356 {
357 k = 0;
358 hent = NULL;
359 }
308 for (;;) 360 for (;;)
309 { 361 {
310 char c = '/'; 362 char c = '/';
311#ifdef OPENSSL_SYS_VMS 363#ifdef OPENSSL_SYS_VMS
312 c = ctx->dirs[i][strlen(ctx->dirs[i])-1]; 364 c = ent->dir[strlen(ent->dir)-1];
313 if (c != ':' && c != '>' && c != ']') 365 if (c != ':' && c != '>' && c != ']')
314 { 366 {
315 /* If no separator is present, we assume the 367 /* If no separator is present, we assume the
@@ -330,41 +382,86 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
330 /* This is special. When c == '\0', no 382 /* This is special. When c == '\0', no
331 directory separator should be added. */ 383 directory separator should be added. */
332 BIO_snprintf(b->data,b->max, 384 BIO_snprintf(b->data,b->max,
333 "%s%08lx.%s%d",ctx->dirs[i],h, 385 "%s%08lx.%s%d",ent->dir,h,
334 postfix,k); 386 postfix,k);
335 } 387 }
336 else 388 else
337 { 389 {
338 BIO_snprintf(b->data,b->max, 390 BIO_snprintf(b->data,b->max,
339 "%s%c%08lx.%s%d",ctx->dirs[i],c,h, 391 "%s%c%08lx.%s%d",ent->dir,c,h,
340 postfix,k); 392 postfix,k);
341 } 393 }
342 k++; 394#ifndef OPENSSL_NO_POSIX_IO
395#ifdef _WIN32
396#define stat _stat
397#endif
398 {
399 struct stat st;
343 if (stat(b->data,&st) < 0) 400 if (stat(b->data,&st) < 0)
344 break; 401 break;
402 }
403#endif
345 /* found one. */ 404 /* found one. */
346 if (type == X509_LU_X509) 405 if (type == X509_LU_X509)
347 { 406 {
348 if ((X509_load_cert_file(xl,b->data, 407 if ((X509_load_cert_file(xl,b->data,
349 ctx->dirs_type[i])) == 0) 408 ent->dir_type)) == 0)
350 break; 409 break;
351 } 410 }
352 else if (type == X509_LU_CRL) 411 else if (type == X509_LU_CRL)
353 { 412 {
354 if ((X509_load_crl_file(xl,b->data, 413 if ((X509_load_crl_file(xl,b->data,
355 ctx->dirs_type[i])) == 0) 414 ent->dir_type)) == 0)
356 break; 415 break;
357 } 416 }
358 /* else case will caught higher up */ 417 /* else case will caught higher up */
418 k++;
359 } 419 }
360 420
361 /* we have added it to the cache so now pull 421 /* we have added it to the cache so now pull
362 * it out again */ 422 * it out again */
363 CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE); 423 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
364 j = sk_X509_OBJECT_find(xl->store_ctx->objs,&stmp); 424 j = sk_X509_OBJECT_find(xl->store_ctx->objs,&stmp);
365 if(j != -1) tmp=sk_X509_OBJECT_value(xl->store_ctx->objs,j); 425 if(j != -1) tmp=sk_X509_OBJECT_value(xl->store_ctx->objs,j);
366 else tmp = NULL; 426 else tmp = NULL;
367 CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE); 427 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
428
429
430 /* If a CRL, update the last file suffix added for this */
431
432 if (type == X509_LU_CRL)
433 {
434 CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
435 /* Look for entry again in case another thread added
436 * an entry first.
437 */
438 if (!hent)
439 {
440 htmp.hash = h;
441 idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);
442 if (idx >= 0)
443 hent =
444 sk_BY_DIR_HASH_value(ent->hashes, idx);
445 }
446 if (!hent)
447 {
448 hent = OPENSSL_malloc(sizeof(BY_DIR_HASH));
449 hent->hash = h;
450 hent->suffix = k;
451 if (!sk_BY_DIR_HASH_push(ent->hashes, hent))
452 {
453 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
454 OPENSSL_free(hent);
455 ok = 0;
456 goto finish;
457 }
458 }
459 else if (hent->suffix < k)
460 hent->suffix = k;
461
462 CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
463
464 }
368 465
369 if (tmp != NULL) 466 if (tmp != NULL)
370 { 467 {
@@ -383,4 +480,3 @@ finish:
383 if (b != NULL) BUF_MEM_free(b); 480 if (b != NULL) BUF_MEM_free(b);
384 return(ok); 481 return(ok);
385 } 482 }
386