diff options
Diffstat (limited to 'src/lib/libcrypto/x509/by_dir.c')
-rw-r--r-- | src/lib/libcrypto/x509/by_dir.c | 226 |
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 | 76 | typedef struct lookup_dir_hashes_st |
79 | #endif | 77 | { |
78 | unsigned long hash; | ||
79 | int suffix; | ||
80 | } BY_DIR_HASH; | ||
81 | |||
82 | typedef 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 | ||
81 | typedef struct lookup_dir_st | 89 | typedef 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 | ||
95 | DECLARE_STACK_OF(BY_DIR_HASH) | ||
96 | DECLARE_STACK_OF(BY_DIR_ENTRY) | ||
97 | |||
90 | static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, | 98 | static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, |
91 | char **ret); | 99 | char **ret); |
92 | static int new_dir(X509_LOOKUP *lu); | 100 | static 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 | ||
172 | static void by_dir_hash_free(BY_DIR_HASH *hash) | ||
173 | { | ||
174 | OPENSSL_free(hash); | ||
175 | } | ||
176 | |||
177 | static 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 | |||
187 | static 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 | |||
167 | static void free_dir(X509_LOOKUP *lu) | 196 | static 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 | ||
181 | static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) | 208 | static 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 | ||
245 | static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, | 273 | static 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 | |||