| lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. | 
|  | 3 | * | 
|  | 4 | * Licensed under the OpenSSL license (the "License").  You may not use | 
|  | 5 | * this file except in compliance with the License.  You can obtain a copy | 
|  | 6 | * in the file LICENSE in the source distribution or at | 
|  | 7 | * https://www.openssl.org/source/license.html | 
|  | 8 | */ | 
|  | 9 |  | 
|  | 10 | #if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) | 
|  | 11 | /* | 
|  | 12 | * On VMS, you need to define this to get the declaration of fileno().  The | 
|  | 13 | * value 2 is to make sure no function defined in POSIX-2 is left undefined. | 
|  | 14 | */ | 
|  | 15 | # define _POSIX_C_SOURCE 2 | 
|  | 16 | #endif | 
|  | 17 |  | 
|  | 18 | #include <stdio.h> | 
|  | 19 | #include <stdlib.h> | 
|  | 20 | #include <string.h> | 
|  | 21 | #include <sys/types.h> | 
|  | 22 | #ifndef OPENSSL_NO_POSIX_IO | 
|  | 23 | # include <sys/stat.h> | 
|  | 24 | # include <fcntl.h> | 
|  | 25 | #endif | 
|  | 26 | #include <ctype.h> | 
|  | 27 | #include <errno.h> | 
|  | 28 | #include <openssl/err.h> | 
|  | 29 | #include <openssl/x509.h> | 
|  | 30 | #include <openssl/x509v3.h> | 
|  | 31 | #include <openssl/pem.h> | 
|  | 32 | #include <openssl/pkcs12.h> | 
|  | 33 | #include <openssl/ui.h> | 
|  | 34 | #include <openssl/safestack.h> | 
|  | 35 | #ifndef OPENSSL_NO_ENGINE | 
|  | 36 | # include <openssl/engine.h> | 
|  | 37 | #endif | 
|  | 38 | #ifndef OPENSSL_NO_RSA | 
|  | 39 | # include <openssl/rsa.h> | 
|  | 40 | #endif | 
|  | 41 | #include <openssl/bn.h> | 
|  | 42 | #include <openssl/ssl.h> | 
|  | 43 | #include "apps.h" | 
|  | 44 |  | 
|  | 45 | #ifdef _WIN32 | 
|  | 46 | static int WIN32_rename(const char *from, const char *to); | 
|  | 47 | # define rename(from,to) WIN32_rename((from),(to)) | 
|  | 48 | #endif | 
|  | 49 |  | 
|  | 50 | #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) | 
|  | 51 | # include <conio.h> | 
|  | 52 | #endif | 
|  | 53 |  | 
|  | 54 | #if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) | 
|  | 55 | # define _kbhit kbhit | 
|  | 56 | #endif | 
|  | 57 |  | 
|  | 58 | typedef struct { | 
|  | 59 | const char *name; | 
|  | 60 | unsigned long flag; | 
|  | 61 | unsigned long mask; | 
|  | 62 | } NAME_EX_TBL; | 
|  | 63 |  | 
|  | 64 | static UI_METHOD *ui_method = NULL; | 
|  | 65 | static const UI_METHOD *ui_fallback_method = NULL; | 
|  | 66 |  | 
|  | 67 | static int set_table_opts(unsigned long *flags, const char *arg, | 
|  | 68 | const NAME_EX_TBL * in_tbl); | 
|  | 69 | static int set_multi_opts(unsigned long *flags, const char *arg, | 
|  | 70 | const NAME_EX_TBL * in_tbl); | 
|  | 71 |  | 
|  | 72 | int app_init(long mesgwin); | 
|  | 73 |  | 
|  | 74 | int chopup_args(ARGS *arg, char *buf) | 
|  | 75 | { | 
|  | 76 | int quoted; | 
|  | 77 | char c = '\0', *p = NULL; | 
|  | 78 |  | 
|  | 79 | arg->argc = 0; | 
|  | 80 | if (arg->size == 0) { | 
|  | 81 | arg->size = 20; | 
|  | 82 | arg->argv = app_malloc(sizeof(*arg->argv) * arg->size, "argv space"); | 
|  | 83 | } | 
|  | 84 |  | 
|  | 85 | for (p = buf;;) { | 
|  | 86 | /* Skip whitespace. */ | 
|  | 87 | while (*p && isspace(_UC(*p))) | 
|  | 88 | p++; | 
|  | 89 | if (!*p) | 
|  | 90 | break; | 
|  | 91 |  | 
|  | 92 | /* The start of something good :-) */ | 
|  | 93 | if (arg->argc >= arg->size) { | 
|  | 94 | char **tmp; | 
|  | 95 | arg->size += 20; | 
|  | 96 | tmp = OPENSSL_realloc(arg->argv, sizeof(*arg->argv) * arg->size); | 
|  | 97 | if (tmp == NULL) | 
|  | 98 | return 0; | 
|  | 99 | arg->argv = tmp; | 
|  | 100 | } | 
|  | 101 | quoted = *p == '\'' || *p == '"'; | 
|  | 102 | if (quoted) | 
|  | 103 | c = *p++; | 
|  | 104 | arg->argv[arg->argc++] = p; | 
|  | 105 |  | 
|  | 106 | /* now look for the end of this */ | 
|  | 107 | if (quoted) { | 
|  | 108 | while (*p && *p != c) | 
|  | 109 | p++; | 
|  | 110 | *p++ = '\0'; | 
|  | 111 | } else { | 
|  | 112 | while (*p && !isspace(_UC(*p))) | 
|  | 113 | p++; | 
|  | 114 | if (*p) | 
|  | 115 | *p++ = '\0'; | 
|  | 116 | } | 
|  | 117 | } | 
|  | 118 | arg->argv[arg->argc] = NULL; | 
|  | 119 | return 1; | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 | #ifndef APP_INIT | 
|  | 123 | int app_init(long mesgwin) | 
|  | 124 | { | 
|  | 125 | return 1; | 
|  | 126 | } | 
|  | 127 | #endif | 
|  | 128 |  | 
|  | 129 | int ctx_set_verify_locations(SSL_CTX *ctx, const char *CAfile, | 
|  | 130 | const char *CApath, int noCAfile, int noCApath) | 
|  | 131 | { | 
|  | 132 | if (CAfile == NULL && CApath == NULL) { | 
|  | 133 | if (!noCAfile && SSL_CTX_set_default_verify_file(ctx) <= 0) | 
|  | 134 | return 0; | 
|  | 135 | if (!noCApath && SSL_CTX_set_default_verify_dir(ctx) <= 0) | 
|  | 136 | return 0; | 
|  | 137 |  | 
|  | 138 | return 1; | 
|  | 139 | } | 
|  | 140 | return SSL_CTX_load_verify_locations(ctx, CAfile, CApath); | 
|  | 141 | } | 
|  | 142 |  | 
|  | 143 | #ifndef OPENSSL_NO_CT | 
|  | 144 |  | 
|  | 145 | int ctx_set_ctlog_list_file(SSL_CTX *ctx, const char *path) | 
|  | 146 | { | 
|  | 147 | if (path == NULL) | 
|  | 148 | return SSL_CTX_set_default_ctlog_list_file(ctx); | 
|  | 149 |  | 
|  | 150 | return SSL_CTX_set_ctlog_list_file(ctx, path); | 
|  | 151 | } | 
|  | 152 |  | 
|  | 153 | #endif | 
|  | 154 |  | 
|  | 155 | static unsigned long nmflag = 0; | 
|  | 156 | static char nmflag_set = 0; | 
|  | 157 |  | 
|  | 158 | int set_nameopt(const char *arg) | 
|  | 159 | { | 
|  | 160 | int ret = set_name_ex(&nmflag, arg); | 
|  | 161 |  | 
|  | 162 | if (ret) | 
|  | 163 | nmflag_set = 1; | 
|  | 164 |  | 
|  | 165 | return ret; | 
|  | 166 | } | 
|  | 167 |  | 
|  | 168 | unsigned long get_nameopt(void) | 
|  | 169 | { | 
|  | 170 | return (nmflag_set) ? nmflag : XN_FLAG_ONELINE; | 
|  | 171 | } | 
|  | 172 |  | 
|  | 173 | int dump_cert_text(BIO *out, X509 *x) | 
|  | 174 | { | 
|  | 175 | print_name(out, "subject=", X509_get_subject_name(x), get_nameopt()); | 
|  | 176 | BIO_puts(out, "\n"); | 
|  | 177 | print_name(out, "issuer=", X509_get_issuer_name(x), get_nameopt()); | 
|  | 178 | BIO_puts(out, "\n"); | 
|  | 179 |  | 
|  | 180 | return 0; | 
|  | 181 | } | 
|  | 182 |  | 
|  | 183 | static int ui_open(UI *ui) | 
|  | 184 | { | 
|  | 185 | int (*opener)(UI *ui) = UI_method_get_opener(ui_fallback_method); | 
|  | 186 |  | 
|  | 187 | if (opener) | 
|  | 188 | return opener(ui); | 
|  | 189 | return 1; | 
|  | 190 | } | 
|  | 191 |  | 
|  | 192 | static int ui_read(UI *ui, UI_STRING *uis) | 
|  | 193 | { | 
|  | 194 | int (*reader)(UI *ui, UI_STRING *uis) = NULL; | 
|  | 195 |  | 
|  | 196 | if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD | 
|  | 197 | && UI_get0_user_data(ui)) { | 
|  | 198 | switch (UI_get_string_type(uis)) { | 
|  | 199 | case UIT_PROMPT: | 
|  | 200 | case UIT_VERIFY: | 
|  | 201 | { | 
|  | 202 | const char *password = | 
|  | 203 | ((PW_CB_DATA *)UI_get0_user_data(ui))->password; | 
|  | 204 | if (password && password[0] != '\0') { | 
|  | 205 | UI_set_result(ui, uis, password); | 
|  | 206 | return 1; | 
|  | 207 | } | 
|  | 208 | } | 
|  | 209 | break; | 
|  | 210 | case UIT_NONE: | 
|  | 211 | case UIT_BOOLEAN: | 
|  | 212 | case UIT_INFO: | 
|  | 213 | case UIT_ERROR: | 
|  | 214 | break; | 
|  | 215 | } | 
|  | 216 | } | 
|  | 217 |  | 
|  | 218 | reader = UI_method_get_reader(ui_fallback_method); | 
|  | 219 | if (reader) | 
|  | 220 | return reader(ui, uis); | 
|  | 221 | return 1; | 
|  | 222 | } | 
|  | 223 |  | 
|  | 224 | static int ui_write(UI *ui, UI_STRING *uis) | 
|  | 225 | { | 
|  | 226 | int (*writer)(UI *ui, UI_STRING *uis) = NULL; | 
|  | 227 |  | 
|  | 228 | if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD | 
|  | 229 | && UI_get0_user_data(ui)) { | 
|  | 230 | switch (UI_get_string_type(uis)) { | 
|  | 231 | case UIT_PROMPT: | 
|  | 232 | case UIT_VERIFY: | 
|  | 233 | { | 
|  | 234 | const char *password = | 
|  | 235 | ((PW_CB_DATA *)UI_get0_user_data(ui))->password; | 
|  | 236 | if (password && password[0] != '\0') | 
|  | 237 | return 1; | 
|  | 238 | } | 
|  | 239 | break; | 
|  | 240 | case UIT_NONE: | 
|  | 241 | case UIT_BOOLEAN: | 
|  | 242 | case UIT_INFO: | 
|  | 243 | case UIT_ERROR: | 
|  | 244 | break; | 
|  | 245 | } | 
|  | 246 | } | 
|  | 247 |  | 
|  | 248 | writer = UI_method_get_writer(ui_fallback_method); | 
|  | 249 | if (writer) | 
|  | 250 | return writer(ui, uis); | 
|  | 251 | return 1; | 
|  | 252 | } | 
|  | 253 |  | 
|  | 254 | static int ui_close(UI *ui) | 
|  | 255 | { | 
|  | 256 | int (*closer)(UI *ui) = UI_method_get_closer(ui_fallback_method); | 
|  | 257 |  | 
|  | 258 | if (closer) | 
|  | 259 | return closer(ui); | 
|  | 260 | return 1; | 
|  | 261 | } | 
|  | 262 |  | 
|  | 263 | int setup_ui_method(void) | 
|  | 264 | { | 
|  | 265 | ui_fallback_method = UI_null(); | 
|  | 266 | #ifndef OPENSSL_NO_UI_CONSOLE | 
|  | 267 | ui_fallback_method = UI_OpenSSL(); | 
|  | 268 | #endif | 
|  | 269 | ui_method = UI_create_method("OpenSSL application user interface"); | 
|  | 270 | UI_method_set_opener(ui_method, ui_open); | 
|  | 271 | UI_method_set_reader(ui_method, ui_read); | 
|  | 272 | UI_method_set_writer(ui_method, ui_write); | 
|  | 273 | UI_method_set_closer(ui_method, ui_close); | 
|  | 274 | return 0; | 
|  | 275 | } | 
|  | 276 |  | 
|  | 277 | void destroy_ui_method(void) | 
|  | 278 | { | 
|  | 279 | if (ui_method) { | 
|  | 280 | UI_destroy_method(ui_method); | 
|  | 281 | ui_method = NULL; | 
|  | 282 | } | 
|  | 283 | } | 
|  | 284 |  | 
|  | 285 | const UI_METHOD *get_ui_method(void) | 
|  | 286 | { | 
|  | 287 | return ui_method; | 
|  | 288 | } | 
|  | 289 |  | 
|  | 290 | int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_tmp) | 
|  | 291 | { | 
|  | 292 | int res = 0; | 
|  | 293 | UI *ui = NULL; | 
|  | 294 | PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp; | 
|  | 295 |  | 
|  | 296 | ui = UI_new_method(ui_method); | 
|  | 297 | if (ui) { | 
|  | 298 | int ok = 0; | 
|  | 299 | char *buff = NULL; | 
|  | 300 | int ui_flags = 0; | 
|  | 301 | const char *prompt_info = NULL; | 
|  | 302 | char *prompt; | 
|  | 303 | int pw_min_len = PW_MIN_LENGTH; | 
|  | 304 |  | 
|  | 305 | if (cb_data != NULL && cb_data->prompt_info != NULL) | 
|  | 306 | prompt_info = cb_data->prompt_info; | 
|  | 307 | if (cb_data != NULL && cb_data->password != NULL | 
|  | 308 | && *(const char*)cb_data->password != '\0') | 
|  | 309 | pw_min_len = 1; | 
|  | 310 | else if (!verify) | 
|  | 311 | pw_min_len = 0; | 
|  | 312 | prompt = UI_construct_prompt(ui, "pass phrase", prompt_info); | 
|  | 313 | if (!prompt) { | 
|  | 314 | BIO_printf(bio_err, "Out of memory\n"); | 
|  | 315 | UI_free(ui); | 
|  | 316 | return 0; | 
|  | 317 | } | 
|  | 318 |  | 
|  | 319 | ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD; | 
|  | 320 | UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); | 
|  | 321 |  | 
|  | 322 | /* We know that there is no previous user data to return to us */ | 
|  | 323 | (void)UI_add_user_data(ui, cb_data); | 
|  | 324 |  | 
|  | 325 | ok = UI_add_input_string(ui, prompt, ui_flags, buf, | 
|  | 326 | pw_min_len, bufsiz - 1); | 
|  | 327 |  | 
|  | 328 | if (ok >= 0 && verify) { | 
|  | 329 | buff = app_malloc(bufsiz, "password buffer"); | 
|  | 330 | ok = UI_add_verify_string(ui, prompt, ui_flags, buff, | 
|  | 331 | pw_min_len, bufsiz - 1, buf); | 
|  | 332 | } | 
|  | 333 | if (ok >= 0) | 
|  | 334 | do { | 
|  | 335 | ok = UI_process(ui); | 
|  | 336 | } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); | 
|  | 337 |  | 
|  | 338 | OPENSSL_clear_free(buff, (unsigned int)bufsiz); | 
|  | 339 |  | 
|  | 340 | if (ok >= 0) | 
|  | 341 | res = strlen(buf); | 
|  | 342 | if (ok == -1) { | 
|  | 343 | BIO_printf(bio_err, "User interface error\n"); | 
|  | 344 | ERR_print_errors(bio_err); | 
|  | 345 | OPENSSL_cleanse(buf, (unsigned int)bufsiz); | 
|  | 346 | res = 0; | 
|  | 347 | } | 
|  | 348 | if (ok == -2) { | 
|  | 349 | BIO_printf(bio_err, "aborted!\n"); | 
|  | 350 | OPENSSL_cleanse(buf, (unsigned int)bufsiz); | 
|  | 351 | res = 0; | 
|  | 352 | } | 
|  | 353 | UI_free(ui); | 
|  | 354 | OPENSSL_free(prompt); | 
|  | 355 | } | 
|  | 356 | return res; | 
|  | 357 | } | 
|  | 358 |  | 
|  | 359 | static char *app_get_pass(const char *arg, int keepbio); | 
|  | 360 |  | 
|  | 361 | int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2) | 
|  | 362 | { | 
|  | 363 | int same; | 
|  | 364 | if (arg2 == NULL || arg1 == NULL || strcmp(arg1, arg2)) | 
|  | 365 | same = 0; | 
|  | 366 | else | 
|  | 367 | same = 1; | 
|  | 368 | if (arg1 != NULL) { | 
|  | 369 | *pass1 = app_get_pass(arg1, same); | 
|  | 370 | if (*pass1 == NULL) | 
|  | 371 | return 0; | 
|  | 372 | } else if (pass1 != NULL) { | 
|  | 373 | *pass1 = NULL; | 
|  | 374 | } | 
|  | 375 | if (arg2 != NULL) { | 
|  | 376 | *pass2 = app_get_pass(arg2, same ? 2 : 0); | 
|  | 377 | if (*pass2 == NULL) | 
|  | 378 | return 0; | 
|  | 379 | } else if (pass2 != NULL) { | 
|  | 380 | *pass2 = NULL; | 
|  | 381 | } | 
|  | 382 | return 1; | 
|  | 383 | } | 
|  | 384 |  | 
|  | 385 | static char *app_get_pass(const char *arg, int keepbio) | 
|  | 386 | { | 
|  | 387 | char *tmp, tpass[APP_PASS_LEN]; | 
|  | 388 | static BIO *pwdbio = NULL; | 
|  | 389 | int i; | 
|  | 390 |  | 
|  | 391 | if (strncmp(arg, "pass:", 5) == 0) | 
|  | 392 | return OPENSSL_strdup(arg + 5); | 
|  | 393 | if (strncmp(arg, "env:", 4) == 0) { | 
|  | 394 | tmp = getenv(arg + 4); | 
|  | 395 | if (tmp == NULL) { | 
|  | 396 | BIO_printf(bio_err, "Can't read environment variable %s\n", arg + 4); | 
|  | 397 | return NULL; | 
|  | 398 | } | 
|  | 399 | return OPENSSL_strdup(tmp); | 
|  | 400 | } | 
|  | 401 | if (!keepbio || pwdbio == NULL) { | 
|  | 402 | if (strncmp(arg, "file:", 5) == 0) { | 
|  | 403 | pwdbio = BIO_new_file(arg + 5, "r"); | 
|  | 404 | if (pwdbio == NULL) { | 
|  | 405 | BIO_printf(bio_err, "Can't open file %s\n", arg + 5); | 
|  | 406 | return NULL; | 
|  | 407 | } | 
|  | 408 | #if !defined(_WIN32) | 
|  | 409 | /* | 
|  | 410 | * Under _WIN32, which covers even Win64 and CE, file | 
|  | 411 | * descriptors referenced by BIO_s_fd are not inherited | 
|  | 412 | * by child process and therefore below is not an option. | 
|  | 413 | * It could have been an option if bss_fd.c was operating | 
|  | 414 | * on real Windows descriptors, such as those obtained | 
|  | 415 | * with CreateFile. | 
|  | 416 | */ | 
|  | 417 | } else if (strncmp(arg, "fd:", 3) == 0) { | 
|  | 418 | BIO *btmp; | 
|  | 419 | i = atoi(arg + 3); | 
|  | 420 | if (i >= 0) | 
|  | 421 | pwdbio = BIO_new_fd(i, BIO_NOCLOSE); | 
|  | 422 | if ((i < 0) || !pwdbio) { | 
|  | 423 | BIO_printf(bio_err, "Can't access file descriptor %s\n", arg + 3); | 
|  | 424 | return NULL; | 
|  | 425 | } | 
|  | 426 | /* | 
|  | 427 | * Can't do BIO_gets on an fd BIO so add a buffering BIO | 
|  | 428 | */ | 
|  | 429 | btmp = BIO_new(BIO_f_buffer()); | 
|  | 430 | pwdbio = BIO_push(btmp, pwdbio); | 
|  | 431 | #endif | 
|  | 432 | } else if (strcmp(arg, "stdin") == 0) { | 
|  | 433 | pwdbio = dup_bio_in(FORMAT_TEXT); | 
|  | 434 | if (!pwdbio) { | 
|  | 435 | BIO_printf(bio_err, "Can't open BIO for stdin\n"); | 
|  | 436 | return NULL; | 
|  | 437 | } | 
|  | 438 | } else { | 
|  | 439 | BIO_printf(bio_err, "Invalid password argument \"%s\"\n", arg); | 
|  | 440 | return NULL; | 
|  | 441 | } | 
|  | 442 | } | 
|  | 443 | i = BIO_gets(pwdbio, tpass, APP_PASS_LEN); | 
|  | 444 | if (keepbio != 1) { | 
|  | 445 | BIO_free_all(pwdbio); | 
|  | 446 | pwdbio = NULL; | 
|  | 447 | } | 
|  | 448 | if (i <= 0) { | 
|  | 449 | BIO_printf(bio_err, "Error reading password from BIO\n"); | 
|  | 450 | return NULL; | 
|  | 451 | } | 
|  | 452 | tmp = strchr(tpass, '\n'); | 
|  | 453 | if (tmp != NULL) | 
|  | 454 | *tmp = 0; | 
|  | 455 | return OPENSSL_strdup(tpass); | 
|  | 456 | } | 
|  | 457 |  | 
|  | 458 | CONF *app_load_config_bio(BIO *in, const char *filename) | 
|  | 459 | { | 
|  | 460 | long errorline = -1; | 
|  | 461 | CONF *conf; | 
|  | 462 | int i; | 
|  | 463 |  | 
|  | 464 | conf = NCONF_new(NULL); | 
|  | 465 | i = NCONF_load_bio(conf, in, &errorline); | 
|  | 466 | if (i > 0) | 
|  | 467 | return conf; | 
|  | 468 |  | 
|  | 469 | if (errorline <= 0) { | 
|  | 470 | BIO_printf(bio_err, "%s: Can't load ", opt_getprog()); | 
|  | 471 | } else { | 
|  | 472 | BIO_printf(bio_err, "%s: Error on line %ld of ", opt_getprog(), | 
|  | 473 | errorline); | 
|  | 474 | } | 
|  | 475 | if (filename != NULL) | 
|  | 476 | BIO_printf(bio_err, "config file \"%s\"\n", filename); | 
|  | 477 | else | 
|  | 478 | BIO_printf(bio_err, "config input"); | 
|  | 479 |  | 
|  | 480 | NCONF_free(conf); | 
|  | 481 | return NULL; | 
|  | 482 | } | 
|  | 483 |  | 
|  | 484 | CONF *app_load_config(const char *filename) | 
|  | 485 | { | 
|  | 486 | BIO *in; | 
|  | 487 | CONF *conf; | 
|  | 488 |  | 
|  | 489 | in = bio_open_default(filename, 'r', FORMAT_TEXT); | 
|  | 490 | if (in == NULL) | 
|  | 491 | return NULL; | 
|  | 492 |  | 
|  | 493 | conf = app_load_config_bio(in, filename); | 
|  | 494 | BIO_free(in); | 
|  | 495 | return conf; | 
|  | 496 | } | 
|  | 497 |  | 
|  | 498 | CONF *app_load_config_quiet(const char *filename) | 
|  | 499 | { | 
|  | 500 | BIO *in; | 
|  | 501 | CONF *conf; | 
|  | 502 |  | 
|  | 503 | in = bio_open_default_quiet(filename, 'r', FORMAT_TEXT); | 
|  | 504 | if (in == NULL) | 
|  | 505 | return NULL; | 
|  | 506 |  | 
|  | 507 | conf = app_load_config_bio(in, filename); | 
|  | 508 | BIO_free(in); | 
|  | 509 | return conf; | 
|  | 510 | } | 
|  | 511 |  | 
|  | 512 | int app_load_modules(const CONF *config) | 
|  | 513 | { | 
|  | 514 | CONF *to_free = NULL; | 
|  | 515 |  | 
|  | 516 | if (config == NULL) | 
|  | 517 | config = to_free = app_load_config_quiet(default_config_file); | 
|  | 518 | if (config == NULL) | 
|  | 519 | return 1; | 
|  | 520 |  | 
|  | 521 | if (CONF_modules_load(config, NULL, 0) <= 0) { | 
|  | 522 | BIO_printf(bio_err, "Error configuring OpenSSL modules\n"); | 
|  | 523 | ERR_print_errors(bio_err); | 
|  | 524 | NCONF_free(to_free); | 
|  | 525 | return 0; | 
|  | 526 | } | 
|  | 527 | NCONF_free(to_free); | 
|  | 528 | return 1; | 
|  | 529 | } | 
|  | 530 |  | 
|  | 531 | int add_oid_section(CONF *conf) | 
|  | 532 | { | 
|  | 533 | char *p; | 
|  | 534 | STACK_OF(CONF_VALUE) *sktmp; | 
|  | 535 | CONF_VALUE *cnf; | 
|  | 536 | int i; | 
|  | 537 |  | 
|  | 538 | if ((p = NCONF_get_string(conf, NULL, "oid_section")) == NULL) { | 
|  | 539 | ERR_clear_error(); | 
|  | 540 | return 1; | 
|  | 541 | } | 
|  | 542 | if ((sktmp = NCONF_get_section(conf, p)) == NULL) { | 
|  | 543 | BIO_printf(bio_err, "problem loading oid section %s\n", p); | 
|  | 544 | return 0; | 
|  | 545 | } | 
|  | 546 | for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { | 
|  | 547 | cnf = sk_CONF_VALUE_value(sktmp, i); | 
|  | 548 | if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) { | 
|  | 549 | BIO_printf(bio_err, "problem creating object %s=%s\n", | 
|  | 550 | cnf->name, cnf->value); | 
|  | 551 | return 0; | 
|  | 552 | } | 
|  | 553 | } | 
|  | 554 | return 1; | 
|  | 555 | } | 
|  | 556 |  | 
|  | 557 | static int load_pkcs12(BIO *in, const char *desc, | 
|  | 558 | pem_password_cb *pem_cb, void *cb_data, | 
|  | 559 | EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca) | 
|  | 560 | { | 
|  | 561 | const char *pass; | 
|  | 562 | char tpass[PEM_BUFSIZE]; | 
|  | 563 | int len, ret = 0; | 
|  | 564 | PKCS12 *p12; | 
|  | 565 | p12 = d2i_PKCS12_bio(in, NULL); | 
|  | 566 | if (p12 == NULL) { | 
|  | 567 | BIO_printf(bio_err, "Error loading PKCS12 file for %s\n", desc); | 
|  | 568 | goto die; | 
|  | 569 | } | 
|  | 570 | /* See if an empty password will do */ | 
|  | 571 | if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0)) { | 
|  | 572 | pass = ""; | 
|  | 573 | } else { | 
|  | 574 | if (!pem_cb) | 
|  | 575 | pem_cb = (pem_password_cb *)password_callback; | 
|  | 576 | len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data); | 
|  | 577 | if (len < 0) { | 
|  | 578 | BIO_printf(bio_err, "Passphrase callback error for %s\n", desc); | 
|  | 579 | goto die; | 
|  | 580 | } | 
|  | 581 | if (len < PEM_BUFSIZE) | 
|  | 582 | tpass[len] = 0; | 
|  | 583 | if (!PKCS12_verify_mac(p12, tpass, len)) { | 
|  | 584 | BIO_printf(bio_err, | 
|  | 585 | "Mac verify error (wrong password?) in PKCS12 file for %s\n", | 
|  | 586 | desc); | 
|  | 587 | goto die; | 
|  | 588 | } | 
|  | 589 | pass = tpass; | 
|  | 590 | } | 
|  | 591 | ret = PKCS12_parse(p12, pass, pkey, cert, ca); | 
|  | 592 | die: | 
|  | 593 | PKCS12_free(p12); | 
|  | 594 | return ret; | 
|  | 595 | } | 
|  | 596 |  | 
|  | 597 | #if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK) | 
|  | 598 | static int load_cert_crl_http(const char *url, X509 **pcert, X509_CRL **pcrl) | 
|  | 599 | { | 
|  | 600 | char *host = NULL, *port = NULL, *path = NULL; | 
|  | 601 | BIO *bio = NULL; | 
|  | 602 | OCSP_REQ_CTX *rctx = NULL; | 
|  | 603 | int use_ssl, rv = 0; | 
|  | 604 | if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl)) | 
|  | 605 | goto err; | 
|  | 606 | if (use_ssl) { | 
|  | 607 | BIO_puts(bio_err, "https not supported\n"); | 
|  | 608 | goto err; | 
|  | 609 | } | 
|  | 610 | bio = BIO_new_connect(host); | 
|  | 611 | if (!bio || !BIO_set_conn_port(bio, port)) | 
|  | 612 | goto err; | 
|  | 613 | rctx = OCSP_REQ_CTX_new(bio, 1024); | 
|  | 614 | if (rctx == NULL) | 
|  | 615 | goto err; | 
|  | 616 | if (!OCSP_REQ_CTX_http(rctx, "GET", path)) | 
|  | 617 | goto err; | 
|  | 618 | if (!OCSP_REQ_CTX_add1_header(rctx, "Host", host)) | 
|  | 619 | goto err; | 
|  | 620 | if (pcert) { | 
|  | 621 | do { | 
|  | 622 | rv = X509_http_nbio(rctx, pcert); | 
|  | 623 | } while (rv == -1); | 
|  | 624 | } else { | 
|  | 625 | do { | 
|  | 626 | rv = X509_CRL_http_nbio(rctx, pcrl); | 
|  | 627 | } while (rv == -1); | 
|  | 628 | } | 
|  | 629 |  | 
|  | 630 | err: | 
|  | 631 | OPENSSL_free(host); | 
|  | 632 | OPENSSL_free(path); | 
|  | 633 | OPENSSL_free(port); | 
|  | 634 | BIO_free_all(bio); | 
|  | 635 | OCSP_REQ_CTX_free(rctx); | 
|  | 636 | if (rv != 1) { | 
|  | 637 | BIO_printf(bio_err, "Error loading %s from %s\n", | 
|  | 638 | pcert ? "certificate" : "CRL", url); | 
|  | 639 | ERR_print_errors(bio_err); | 
|  | 640 | } | 
|  | 641 | return rv; | 
|  | 642 | } | 
|  | 643 | #endif | 
|  | 644 |  | 
|  | 645 | X509 *load_cert(const char *file, int format, const char *cert_descrip) | 
|  | 646 | { | 
|  | 647 | X509 *x = NULL; | 
|  | 648 | BIO *cert; | 
|  | 649 |  | 
|  | 650 | if (format == FORMAT_HTTP) { | 
|  | 651 | #if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK) | 
|  | 652 | load_cert_crl_http(file, &x, NULL); | 
|  | 653 | #endif | 
|  | 654 | return x; | 
|  | 655 | } | 
|  | 656 |  | 
|  | 657 | if (file == NULL) { | 
|  | 658 | unbuffer(stdin); | 
|  | 659 | cert = dup_bio_in(format); | 
|  | 660 | } else { | 
|  | 661 | cert = bio_open_default(file, 'r', format); | 
|  | 662 | } | 
|  | 663 | if (cert == NULL) | 
|  | 664 | goto end; | 
|  | 665 |  | 
|  | 666 | if (format == FORMAT_ASN1) { | 
|  | 667 | x = d2i_X509_bio(cert, NULL); | 
|  | 668 | } else if (format == FORMAT_PEM) { | 
|  | 669 | x = PEM_read_bio_X509_AUX(cert, NULL, | 
|  | 670 | (pem_password_cb *)password_callback, NULL); | 
|  | 671 | } else if (format == FORMAT_PKCS12) { | 
|  | 672 | if (!load_pkcs12(cert, cert_descrip, NULL, NULL, NULL, &x, NULL)) | 
|  | 673 | goto end; | 
|  | 674 | } else { | 
|  | 675 | BIO_printf(bio_err, "bad input format specified for %s\n", cert_descrip); | 
|  | 676 | goto end; | 
|  | 677 | } | 
|  | 678 | end: | 
|  | 679 | if (x == NULL) { | 
|  | 680 | BIO_printf(bio_err, "unable to load certificate\n"); | 
|  | 681 | ERR_print_errors(bio_err); | 
|  | 682 | } | 
|  | 683 | BIO_free(cert); | 
|  | 684 | return x; | 
|  | 685 | } | 
|  | 686 |  | 
|  | 687 | X509_CRL *load_crl(const char *infile, int format) | 
|  | 688 | { | 
|  | 689 | X509_CRL *x = NULL; | 
|  | 690 | BIO *in = NULL; | 
|  | 691 |  | 
|  | 692 | if (format == FORMAT_HTTP) { | 
|  | 693 | #if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK) | 
|  | 694 | load_cert_crl_http(infile, NULL, &x); | 
|  | 695 | #endif | 
|  | 696 | return x; | 
|  | 697 | } | 
|  | 698 |  | 
|  | 699 | in = bio_open_default(infile, 'r', format); | 
|  | 700 | if (in == NULL) | 
|  | 701 | goto end; | 
|  | 702 | if (format == FORMAT_ASN1) { | 
|  | 703 | x = d2i_X509_CRL_bio(in, NULL); | 
|  | 704 | } else if (format == FORMAT_PEM) { | 
|  | 705 | x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); | 
|  | 706 | } else { | 
|  | 707 | BIO_printf(bio_err, "bad input format specified for input crl\n"); | 
|  | 708 | goto end; | 
|  | 709 | } | 
|  | 710 | if (x == NULL) { | 
|  | 711 | BIO_printf(bio_err, "unable to load CRL\n"); | 
|  | 712 | ERR_print_errors(bio_err); | 
|  | 713 | goto end; | 
|  | 714 | } | 
|  | 715 |  | 
|  | 716 | end: | 
|  | 717 | BIO_free(in); | 
|  | 718 | return x; | 
|  | 719 | } | 
|  | 720 |  | 
|  | 721 | EVP_PKEY *load_key(const char *file, int format, int maybe_stdin, | 
|  | 722 | const char *pass, ENGINE *e, const char *key_descrip) | 
|  | 723 | { | 
|  | 724 | BIO *key = NULL; | 
|  | 725 | EVP_PKEY *pkey = NULL; | 
|  | 726 | PW_CB_DATA cb_data; | 
|  | 727 |  | 
|  | 728 | cb_data.password = pass; | 
|  | 729 | cb_data.prompt_info = file; | 
|  | 730 |  | 
|  | 731 | if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) { | 
|  | 732 | BIO_printf(bio_err, "no keyfile specified\n"); | 
|  | 733 | goto end; | 
|  | 734 | } | 
|  | 735 | if (format == FORMAT_ENGINE) { | 
|  | 736 | if (e == NULL) { | 
|  | 737 | BIO_printf(bio_err, "no engine specified\n"); | 
|  | 738 | } else { | 
|  | 739 | #ifndef OPENSSL_NO_ENGINE | 
|  | 740 | if (ENGINE_init(e)) { | 
|  | 741 | pkey = ENGINE_load_private_key(e, file, ui_method, &cb_data); | 
|  | 742 | ENGINE_finish(e); | 
|  | 743 | } | 
|  | 744 | if (pkey == NULL) { | 
|  | 745 | BIO_printf(bio_err, "cannot load %s from engine\n", key_descrip); | 
|  | 746 | ERR_print_errors(bio_err); | 
|  | 747 | } | 
|  | 748 | #else | 
|  | 749 | BIO_printf(bio_err, "engines not supported\n"); | 
|  | 750 | #endif | 
|  | 751 | } | 
|  | 752 | goto end; | 
|  | 753 | } | 
|  | 754 | if (file == NULL && maybe_stdin) { | 
|  | 755 | unbuffer(stdin); | 
|  | 756 | key = dup_bio_in(format); | 
|  | 757 | } else { | 
|  | 758 | key = bio_open_default(file, 'r', format); | 
|  | 759 | } | 
|  | 760 | if (key == NULL) | 
|  | 761 | goto end; | 
|  | 762 | if (format == FORMAT_ASN1) { | 
|  | 763 | pkey = d2i_PrivateKey_bio(key, NULL); | 
|  | 764 | } else if (format == FORMAT_PEM) { | 
|  | 765 | pkey = PEM_read_bio_PrivateKey(key, NULL, | 
|  | 766 | (pem_password_cb *)password_callback, | 
|  | 767 | &cb_data); | 
|  | 768 | } else if (format == FORMAT_PKCS12) { | 
|  | 769 | if (!load_pkcs12(key, key_descrip, | 
|  | 770 | (pem_password_cb *)password_callback, &cb_data, | 
|  | 771 | &pkey, NULL, NULL)) | 
|  | 772 | goto end; | 
|  | 773 | #if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4) | 
|  | 774 | } else if (format == FORMAT_MSBLOB) { | 
|  | 775 | pkey = b2i_PrivateKey_bio(key); | 
|  | 776 | } else if (format == FORMAT_PVK) { | 
|  | 777 | pkey = b2i_PVK_bio(key, (pem_password_cb *)password_callback, | 
|  | 778 | &cb_data); | 
|  | 779 | #endif | 
|  | 780 | } else { | 
|  | 781 | BIO_printf(bio_err, "bad input format specified for key file\n"); | 
|  | 782 | goto end; | 
|  | 783 | } | 
|  | 784 | end: | 
|  | 785 | BIO_free(key); | 
|  | 786 | if (pkey == NULL) { | 
|  | 787 | BIO_printf(bio_err, "unable to load %s\n", key_descrip); | 
|  | 788 | ERR_print_errors(bio_err); | 
|  | 789 | } | 
|  | 790 | return pkey; | 
|  | 791 | } | 
|  | 792 |  | 
|  | 793 | EVP_PKEY *load_pubkey(const char *file, int format, int maybe_stdin, | 
|  | 794 | const char *pass, ENGINE *e, const char *key_descrip) | 
|  | 795 | { | 
|  | 796 | BIO *key = NULL; | 
|  | 797 | EVP_PKEY *pkey = NULL; | 
|  | 798 | PW_CB_DATA cb_data; | 
|  | 799 |  | 
|  | 800 | cb_data.password = pass; | 
|  | 801 | cb_data.prompt_info = file; | 
|  | 802 |  | 
|  | 803 | if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) { | 
|  | 804 | BIO_printf(bio_err, "no keyfile specified\n"); | 
|  | 805 | goto end; | 
|  | 806 | } | 
|  | 807 | if (format == FORMAT_ENGINE) { | 
|  | 808 | if (e == NULL) { | 
|  | 809 | BIO_printf(bio_err, "no engine specified\n"); | 
|  | 810 | } else { | 
|  | 811 | #ifndef OPENSSL_NO_ENGINE | 
|  | 812 | pkey = ENGINE_load_public_key(e, file, ui_method, &cb_data); | 
|  | 813 | if (pkey == NULL) { | 
|  | 814 | BIO_printf(bio_err, "cannot load %s from engine\n", key_descrip); | 
|  | 815 | ERR_print_errors(bio_err); | 
|  | 816 | } | 
|  | 817 | #else | 
|  | 818 | BIO_printf(bio_err, "engines not supported\n"); | 
|  | 819 | #endif | 
|  | 820 | } | 
|  | 821 | goto end; | 
|  | 822 | } | 
|  | 823 | if (file == NULL && maybe_stdin) { | 
|  | 824 | unbuffer(stdin); | 
|  | 825 | key = dup_bio_in(format); | 
|  | 826 | } else { | 
|  | 827 | key = bio_open_default(file, 'r', format); | 
|  | 828 | } | 
|  | 829 | if (key == NULL) | 
|  | 830 | goto end; | 
|  | 831 | if (format == FORMAT_ASN1) { | 
|  | 832 | pkey = d2i_PUBKEY_bio(key, NULL); | 
|  | 833 | } else if (format == FORMAT_ASN1RSA) { | 
|  | 834 | #ifndef OPENSSL_NO_RSA | 
|  | 835 | RSA *rsa; | 
|  | 836 | rsa = d2i_RSAPublicKey_bio(key, NULL); | 
|  | 837 | if (rsa) { | 
|  | 838 | pkey = EVP_PKEY_new(); | 
|  | 839 | if (pkey != NULL) | 
|  | 840 | EVP_PKEY_set1_RSA(pkey, rsa); | 
|  | 841 | RSA_free(rsa); | 
|  | 842 | } else | 
|  | 843 | #else | 
|  | 844 | BIO_printf(bio_err, "RSA keys not supported\n"); | 
|  | 845 | #endif | 
|  | 846 | pkey = NULL; | 
|  | 847 | } else if (format == FORMAT_PEMRSA) { | 
|  | 848 | #ifndef OPENSSL_NO_RSA | 
|  | 849 | RSA *rsa; | 
|  | 850 | rsa = PEM_read_bio_RSAPublicKey(key, NULL, | 
|  | 851 | (pem_password_cb *)password_callback, | 
|  | 852 | &cb_data); | 
|  | 853 | if (rsa != NULL) { | 
|  | 854 | pkey = EVP_PKEY_new(); | 
|  | 855 | if (pkey != NULL) | 
|  | 856 | EVP_PKEY_set1_RSA(pkey, rsa); | 
|  | 857 | RSA_free(rsa); | 
|  | 858 | } else | 
|  | 859 | #else | 
|  | 860 | BIO_printf(bio_err, "RSA keys not supported\n"); | 
|  | 861 | #endif | 
|  | 862 | pkey = NULL; | 
|  | 863 | } else if (format == FORMAT_PEM) { | 
|  | 864 | pkey = PEM_read_bio_PUBKEY(key, NULL, | 
|  | 865 | (pem_password_cb *)password_callback, | 
|  | 866 | &cb_data); | 
|  | 867 | #if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) | 
|  | 868 | } else if (format == FORMAT_MSBLOB) { | 
|  | 869 | pkey = b2i_PublicKey_bio(key); | 
|  | 870 | #endif | 
|  | 871 | } | 
|  | 872 | end: | 
|  | 873 | BIO_free(key); | 
|  | 874 | if (pkey == NULL) | 
|  | 875 | BIO_printf(bio_err, "unable to load %s\n", key_descrip); | 
|  | 876 | return pkey; | 
|  | 877 | } | 
|  | 878 |  | 
|  | 879 | static int load_certs_crls(const char *file, int format, | 
|  | 880 | const char *pass, const char *desc, | 
|  | 881 | STACK_OF(X509) **pcerts, | 
|  | 882 | STACK_OF(X509_CRL) **pcrls) | 
|  | 883 | { | 
|  | 884 | int i; | 
|  | 885 | BIO *bio; | 
|  | 886 | STACK_OF(X509_INFO) *xis = NULL; | 
|  | 887 | X509_INFO *xi; | 
|  | 888 | PW_CB_DATA cb_data; | 
|  | 889 | int rv = 0; | 
|  | 890 |  | 
|  | 891 | cb_data.password = pass; | 
|  | 892 | cb_data.prompt_info = file; | 
|  | 893 |  | 
|  | 894 | if (format != FORMAT_PEM) { | 
|  | 895 | BIO_printf(bio_err, "bad input format specified for %s\n", desc); | 
|  | 896 | return 0; | 
|  | 897 | } | 
|  | 898 |  | 
|  | 899 | bio = bio_open_default(file, 'r', FORMAT_PEM); | 
|  | 900 | if (bio == NULL) | 
|  | 901 | return 0; | 
|  | 902 |  | 
|  | 903 | xis = PEM_X509_INFO_read_bio(bio, NULL, | 
|  | 904 | (pem_password_cb *)password_callback, | 
|  | 905 | &cb_data); | 
|  | 906 |  | 
|  | 907 | BIO_free(bio); | 
|  | 908 |  | 
|  | 909 | if (pcerts != NULL && *pcerts == NULL) { | 
|  | 910 | *pcerts = sk_X509_new_null(); | 
|  | 911 | if (*pcerts == NULL) | 
|  | 912 | goto end; | 
|  | 913 | } | 
|  | 914 |  | 
|  | 915 | if (pcrls != NULL && *pcrls == NULL) { | 
|  | 916 | *pcrls = sk_X509_CRL_new_null(); | 
|  | 917 | if (*pcrls == NULL) | 
|  | 918 | goto end; | 
|  | 919 | } | 
|  | 920 |  | 
|  | 921 | for (i = 0; i < sk_X509_INFO_num(xis); i++) { | 
|  | 922 | xi = sk_X509_INFO_value(xis, i); | 
|  | 923 | if (xi->x509 != NULL && pcerts != NULL) { | 
|  | 924 | if (!sk_X509_push(*pcerts, xi->x509)) | 
|  | 925 | goto end; | 
|  | 926 | xi->x509 = NULL; | 
|  | 927 | } | 
|  | 928 | if (xi->crl != NULL && pcrls != NULL) { | 
|  | 929 | if (!sk_X509_CRL_push(*pcrls, xi->crl)) | 
|  | 930 | goto end; | 
|  | 931 | xi->crl = NULL; | 
|  | 932 | } | 
|  | 933 | } | 
|  | 934 |  | 
|  | 935 | if (pcerts != NULL && sk_X509_num(*pcerts) > 0) | 
|  | 936 | rv = 1; | 
|  | 937 |  | 
|  | 938 | if (pcrls != NULL && sk_X509_CRL_num(*pcrls) > 0) | 
|  | 939 | rv = 1; | 
|  | 940 |  | 
|  | 941 | end: | 
|  | 942 |  | 
|  | 943 | sk_X509_INFO_pop_free(xis, X509_INFO_free); | 
|  | 944 |  | 
|  | 945 | if (rv == 0) { | 
|  | 946 | if (pcerts != NULL) { | 
|  | 947 | sk_X509_pop_free(*pcerts, X509_free); | 
|  | 948 | *pcerts = NULL; | 
|  | 949 | } | 
|  | 950 | if (pcrls != NULL) { | 
|  | 951 | sk_X509_CRL_pop_free(*pcrls, X509_CRL_free); | 
|  | 952 | *pcrls = NULL; | 
|  | 953 | } | 
|  | 954 | BIO_printf(bio_err, "unable to load %s\n", | 
|  | 955 | pcerts ? "certificates" : "CRLs"); | 
|  | 956 | ERR_print_errors(bio_err); | 
|  | 957 | } | 
|  | 958 | return rv; | 
|  | 959 | } | 
|  | 960 |  | 
|  | 961 | void* app_malloc(int sz, const char *what) | 
|  | 962 | { | 
|  | 963 | void *vp = OPENSSL_malloc(sz); | 
|  | 964 |  | 
|  | 965 | if (vp == NULL) { | 
|  | 966 | BIO_printf(bio_err, "%s: Could not allocate %d bytes for %s\n", | 
|  | 967 | opt_getprog(), sz, what); | 
|  | 968 | ERR_print_errors(bio_err); | 
|  | 969 | exit(1); | 
|  | 970 | } | 
|  | 971 | return vp; | 
|  | 972 | } | 
|  | 973 |  | 
|  | 974 | /* | 
|  | 975 | * Initialize or extend, if *certs != NULL, a certificate stack. | 
|  | 976 | */ | 
|  | 977 | int load_certs(const char *file, STACK_OF(X509) **certs, int format, | 
|  | 978 | const char *pass, const char *desc) | 
|  | 979 | { | 
|  | 980 | return load_certs_crls(file, format, pass, desc, certs, NULL); | 
|  | 981 | } | 
|  | 982 |  | 
|  | 983 | /* | 
|  | 984 | * Initialize or extend, if *crls != NULL, a certificate stack. | 
|  | 985 | */ | 
|  | 986 | int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format, | 
|  | 987 | const char *pass, const char *desc) | 
|  | 988 | { | 
|  | 989 | return load_certs_crls(file, format, pass, desc, NULL, crls); | 
|  | 990 | } | 
|  | 991 |  | 
|  | 992 | #define X509V3_EXT_UNKNOWN_MASK         (0xfL << 16) | 
|  | 993 | /* Return error for unknown extensions */ | 
|  | 994 | #define X509V3_EXT_DEFAULT              0 | 
|  | 995 | /* Print error for unknown extensions */ | 
|  | 996 | #define X509V3_EXT_ERROR_UNKNOWN        (1L << 16) | 
|  | 997 | /* ASN1 parse unknown extensions */ | 
|  | 998 | #define X509V3_EXT_PARSE_UNKNOWN        (2L << 16) | 
|  | 999 | /* BIO_dump unknown extensions */ | 
|  | 1000 | #define X509V3_EXT_DUMP_UNKNOWN         (3L << 16) | 
|  | 1001 |  | 
|  | 1002 | #define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \ | 
|  | 1003 | X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION) | 
|  | 1004 |  | 
|  | 1005 | int set_cert_ex(unsigned long *flags, const char *arg) | 
|  | 1006 | { | 
|  | 1007 | static const NAME_EX_TBL cert_tbl[] = { | 
|  | 1008 | {"compatible", X509_FLAG_COMPAT, 0xffffffffl}, | 
|  | 1009 | {"ca_default", X509_FLAG_CA, 0xffffffffl}, | 
|  | 1010 | {"no_header", X509_FLAG_NO_HEADER, 0}, | 
|  | 1011 | {"no_version", X509_FLAG_NO_VERSION, 0}, | 
|  | 1012 | {"no_serial", X509_FLAG_NO_SERIAL, 0}, | 
|  | 1013 | {"no_signame", X509_FLAG_NO_SIGNAME, 0}, | 
|  | 1014 | {"no_validity", X509_FLAG_NO_VALIDITY, 0}, | 
|  | 1015 | {"no_subject", X509_FLAG_NO_SUBJECT, 0}, | 
|  | 1016 | {"no_issuer", X509_FLAG_NO_ISSUER, 0}, | 
|  | 1017 | {"no_pubkey", X509_FLAG_NO_PUBKEY, 0}, | 
|  | 1018 | {"no_extensions", X509_FLAG_NO_EXTENSIONS, 0}, | 
|  | 1019 | {"no_sigdump", X509_FLAG_NO_SIGDUMP, 0}, | 
|  | 1020 | {"no_aux", X509_FLAG_NO_AUX, 0}, | 
|  | 1021 | {"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0}, | 
|  | 1022 | {"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK}, | 
|  | 1023 | {"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, | 
|  | 1024 | {"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, | 
|  | 1025 | {"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, | 
|  | 1026 | {NULL, 0, 0} | 
|  | 1027 | }; | 
|  | 1028 | return set_multi_opts(flags, arg, cert_tbl); | 
|  | 1029 | } | 
|  | 1030 |  | 
|  | 1031 | int set_name_ex(unsigned long *flags, const char *arg) | 
|  | 1032 | { | 
|  | 1033 | static const NAME_EX_TBL ex_tbl[] = { | 
|  | 1034 | {"esc_2253", ASN1_STRFLGS_ESC_2253, 0}, | 
|  | 1035 | {"esc_2254", ASN1_STRFLGS_ESC_2254, 0}, | 
|  | 1036 | {"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0}, | 
|  | 1037 | {"esc_msb", ASN1_STRFLGS_ESC_MSB, 0}, | 
|  | 1038 | {"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0}, | 
|  | 1039 | {"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0}, | 
|  | 1040 | {"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0}, | 
|  | 1041 | {"show_type", ASN1_STRFLGS_SHOW_TYPE, 0}, | 
|  | 1042 | {"dump_all", ASN1_STRFLGS_DUMP_ALL, 0}, | 
|  | 1043 | {"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0}, | 
|  | 1044 | {"dump_der", ASN1_STRFLGS_DUMP_DER, 0}, | 
|  | 1045 | {"compat", XN_FLAG_COMPAT, 0xffffffffL}, | 
|  | 1046 | {"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK}, | 
|  | 1047 | {"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK}, | 
|  | 1048 | {"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK}, | 
|  | 1049 | {"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK}, | 
|  | 1050 | {"dn_rev", XN_FLAG_DN_REV, 0}, | 
|  | 1051 | {"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK}, | 
|  | 1052 | {"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK}, | 
|  | 1053 | {"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK}, | 
|  | 1054 | {"align", XN_FLAG_FN_ALIGN, 0}, | 
|  | 1055 | {"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK}, | 
|  | 1056 | {"space_eq", XN_FLAG_SPC_EQ, 0}, | 
|  | 1057 | {"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0}, | 
|  | 1058 | {"RFC2253", XN_FLAG_RFC2253, 0xffffffffL}, | 
|  | 1059 | {"oneline", XN_FLAG_ONELINE, 0xffffffffL}, | 
|  | 1060 | {"multiline", XN_FLAG_MULTILINE, 0xffffffffL}, | 
|  | 1061 | {"ca_default", XN_FLAG_MULTILINE, 0xffffffffL}, | 
|  | 1062 | {NULL, 0, 0} | 
|  | 1063 | }; | 
|  | 1064 | if (set_multi_opts(flags, arg, ex_tbl) == 0) | 
|  | 1065 | return 0; | 
|  | 1066 | if (*flags != XN_FLAG_COMPAT | 
|  | 1067 | && (*flags & XN_FLAG_SEP_MASK) == 0) | 
|  | 1068 | *flags |= XN_FLAG_SEP_CPLUS_SPC; | 
|  | 1069 | return 1; | 
|  | 1070 | } | 
|  | 1071 |  | 
|  | 1072 | int set_ext_copy(int *copy_type, const char *arg) | 
|  | 1073 | { | 
|  | 1074 | if (strcasecmp(arg, "none") == 0) | 
|  | 1075 | *copy_type = EXT_COPY_NONE; | 
|  | 1076 | else if (strcasecmp(arg, "copy") == 0) | 
|  | 1077 | *copy_type = EXT_COPY_ADD; | 
|  | 1078 | else if (strcasecmp(arg, "copyall") == 0) | 
|  | 1079 | *copy_type = EXT_COPY_ALL; | 
|  | 1080 | else | 
|  | 1081 | return 0; | 
|  | 1082 | return 1; | 
|  | 1083 | } | 
|  | 1084 |  | 
|  | 1085 | int copy_extensions(X509 *x, X509_REQ *req, int copy_type) | 
|  | 1086 | { | 
|  | 1087 | STACK_OF(X509_EXTENSION) *exts = NULL; | 
|  | 1088 | X509_EXTENSION *ext, *tmpext; | 
|  | 1089 | ASN1_OBJECT *obj; | 
|  | 1090 | int i, idx, ret = 0; | 
|  | 1091 | if (!x || !req || (copy_type == EXT_COPY_NONE)) | 
|  | 1092 | return 1; | 
|  | 1093 | exts = X509_REQ_get_extensions(req); | 
|  | 1094 |  | 
|  | 1095 | for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { | 
|  | 1096 | ext = sk_X509_EXTENSION_value(exts, i); | 
|  | 1097 | obj = X509_EXTENSION_get_object(ext); | 
|  | 1098 | idx = X509_get_ext_by_OBJ(x, obj, -1); | 
|  | 1099 | /* Does extension exist? */ | 
|  | 1100 | if (idx != -1) { | 
|  | 1101 | /* If normal copy don't override existing extension */ | 
|  | 1102 | if (copy_type == EXT_COPY_ADD) | 
|  | 1103 | continue; | 
|  | 1104 | /* Delete all extensions of same type */ | 
|  | 1105 | do { | 
|  | 1106 | tmpext = X509_get_ext(x, idx); | 
|  | 1107 | X509_delete_ext(x, idx); | 
|  | 1108 | X509_EXTENSION_free(tmpext); | 
|  | 1109 | idx = X509_get_ext_by_OBJ(x, obj, -1); | 
|  | 1110 | } while (idx != -1); | 
|  | 1111 | } | 
|  | 1112 | if (!X509_add_ext(x, ext, -1)) | 
|  | 1113 | goto end; | 
|  | 1114 | } | 
|  | 1115 |  | 
|  | 1116 | ret = 1; | 
|  | 1117 |  | 
|  | 1118 | end: | 
|  | 1119 |  | 
|  | 1120 | sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); | 
|  | 1121 |  | 
|  | 1122 | return ret; | 
|  | 1123 | } | 
|  | 1124 |  | 
|  | 1125 | static int set_multi_opts(unsigned long *flags, const char *arg, | 
|  | 1126 | const NAME_EX_TBL * in_tbl) | 
|  | 1127 | { | 
|  | 1128 | STACK_OF(CONF_VALUE) *vals; | 
|  | 1129 | CONF_VALUE *val; | 
|  | 1130 | int i, ret = 1; | 
|  | 1131 | if (!arg) | 
|  | 1132 | return 0; | 
|  | 1133 | vals = X509V3_parse_list(arg); | 
|  | 1134 | for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { | 
|  | 1135 | val = sk_CONF_VALUE_value(vals, i); | 
|  | 1136 | if (!set_table_opts(flags, val->name, in_tbl)) | 
|  | 1137 | ret = 0; | 
|  | 1138 | } | 
|  | 1139 | sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); | 
|  | 1140 | return ret; | 
|  | 1141 | } | 
|  | 1142 |  | 
|  | 1143 | static int set_table_opts(unsigned long *flags, const char *arg, | 
|  | 1144 | const NAME_EX_TBL * in_tbl) | 
|  | 1145 | { | 
|  | 1146 | char c; | 
|  | 1147 | const NAME_EX_TBL *ptbl; | 
|  | 1148 | c = arg[0]; | 
|  | 1149 |  | 
|  | 1150 | if (c == '-') { | 
|  | 1151 | c = 0; | 
|  | 1152 | arg++; | 
|  | 1153 | } else if (c == '+') { | 
|  | 1154 | c = 1; | 
|  | 1155 | arg++; | 
|  | 1156 | } else { | 
|  | 1157 | c = 1; | 
|  | 1158 | } | 
|  | 1159 |  | 
|  | 1160 | for (ptbl = in_tbl; ptbl->name; ptbl++) { | 
|  | 1161 | if (strcasecmp(arg, ptbl->name) == 0) { | 
|  | 1162 | *flags &= ~ptbl->mask; | 
|  | 1163 | if (c) | 
|  | 1164 | *flags |= ptbl->flag; | 
|  | 1165 | else | 
|  | 1166 | *flags &= ~ptbl->flag; | 
|  | 1167 | return 1; | 
|  | 1168 | } | 
|  | 1169 | } | 
|  | 1170 | return 0; | 
|  | 1171 | } | 
|  | 1172 |  | 
|  | 1173 | void print_name(BIO *out, const char *title, X509_NAME *nm, | 
|  | 1174 | unsigned long lflags) | 
|  | 1175 | { | 
|  | 1176 | char *buf; | 
|  | 1177 | char mline = 0; | 
|  | 1178 | int indent = 0; | 
|  | 1179 |  | 
|  | 1180 | if (title) | 
|  | 1181 | BIO_puts(out, title); | 
|  | 1182 | if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { | 
|  | 1183 | mline = 1; | 
|  | 1184 | indent = 4; | 
|  | 1185 | } | 
|  | 1186 | if (lflags == XN_FLAG_COMPAT) { | 
|  | 1187 | buf = X509_NAME_oneline(nm, 0, 0); | 
|  | 1188 | BIO_puts(out, buf); | 
|  | 1189 | BIO_puts(out, "\n"); | 
|  | 1190 | OPENSSL_free(buf); | 
|  | 1191 | } else { | 
|  | 1192 | if (mline) | 
|  | 1193 | BIO_puts(out, "\n"); | 
|  | 1194 | X509_NAME_print_ex(out, nm, indent, lflags); | 
|  | 1195 | BIO_puts(out, "\n"); | 
|  | 1196 | } | 
|  | 1197 | } | 
|  | 1198 |  | 
|  | 1199 | void print_bignum_var(BIO *out, const BIGNUM *in, const char *var, | 
|  | 1200 | int len, unsigned char *buffer) | 
|  | 1201 | { | 
|  | 1202 | BIO_printf(out, "    static unsigned char %s_%d[] = {", var, len); | 
|  | 1203 | if (BN_is_zero(in)) { | 
|  | 1204 | BIO_printf(out, "\n        0x00"); | 
|  | 1205 | } else { | 
|  | 1206 | int i, l; | 
|  | 1207 |  | 
|  | 1208 | l = BN_bn2bin(in, buffer); | 
|  | 1209 | for (i = 0; i < l; i++) { | 
|  | 1210 | BIO_printf(out, (i % 10) == 0 ? "\n        " : " "); | 
|  | 1211 | if (i < l - 1) | 
|  | 1212 | BIO_printf(out, "0x%02X,", buffer[i]); | 
|  | 1213 | else | 
|  | 1214 | BIO_printf(out, "0x%02X", buffer[i]); | 
|  | 1215 | } | 
|  | 1216 | } | 
|  | 1217 | BIO_printf(out, "\n    };\n"); | 
|  | 1218 | } | 
|  | 1219 |  | 
|  | 1220 | void print_array(BIO *out, const char* title, int len, const unsigned char* d) | 
|  | 1221 | { | 
|  | 1222 | int i; | 
|  | 1223 |  | 
|  | 1224 | BIO_printf(out, "unsigned char %s[%d] = {", title, len); | 
|  | 1225 | for (i = 0; i < len; i++) { | 
|  | 1226 | if ((i % 10) == 0) | 
|  | 1227 | BIO_printf(out, "\n    "); | 
|  | 1228 | if (i < len - 1) | 
|  | 1229 | BIO_printf(out, "0x%02X, ", d[i]); | 
|  | 1230 | else | 
|  | 1231 | BIO_printf(out, "0x%02X", d[i]); | 
|  | 1232 | } | 
|  | 1233 | BIO_printf(out, "\n};\n"); | 
|  | 1234 | } | 
|  | 1235 |  | 
|  | 1236 | X509_STORE *setup_verify(const char *CAfile, const char *CApath, int noCAfile, int noCApath) | 
|  | 1237 | { | 
|  | 1238 | X509_STORE *store = X509_STORE_new(); | 
|  | 1239 | X509_LOOKUP *lookup; | 
|  | 1240 |  | 
|  | 1241 | if (store == NULL) | 
|  | 1242 | goto end; | 
|  | 1243 |  | 
|  | 1244 | if (CAfile != NULL || !noCAfile) { | 
|  | 1245 | lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); | 
|  | 1246 | if (lookup == NULL) | 
|  | 1247 | goto end; | 
|  | 1248 | if (CAfile) { | 
|  | 1249 | if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) { | 
|  | 1250 | BIO_printf(bio_err, "Error loading file %s\n", CAfile); | 
|  | 1251 | goto end; | 
|  | 1252 | } | 
|  | 1253 | } else { | 
|  | 1254 | X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); | 
|  | 1255 | } | 
|  | 1256 | } | 
|  | 1257 |  | 
|  | 1258 | if (CApath != NULL || !noCApath) { | 
|  | 1259 | lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); | 
|  | 1260 | if (lookup == NULL) | 
|  | 1261 | goto end; | 
|  | 1262 | if (CApath) { | 
|  | 1263 | if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) { | 
|  | 1264 | BIO_printf(bio_err, "Error loading directory %s\n", CApath); | 
|  | 1265 | goto end; | 
|  | 1266 | } | 
|  | 1267 | } else { | 
|  | 1268 | X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); | 
|  | 1269 | } | 
|  | 1270 | } | 
|  | 1271 |  | 
|  | 1272 | ERR_clear_error(); | 
|  | 1273 | return store; | 
|  | 1274 | end: | 
|  | 1275 | X509_STORE_free(store); | 
|  | 1276 | return NULL; | 
|  | 1277 | } | 
|  | 1278 |  | 
|  | 1279 | #ifndef OPENSSL_NO_ENGINE | 
|  | 1280 | /* Try to load an engine in a shareable library */ | 
|  | 1281 | static ENGINE *try_load_engine(const char *engine) | 
|  | 1282 | { | 
|  | 1283 | ENGINE *e = ENGINE_by_id("dynamic"); | 
|  | 1284 | if (e) { | 
|  | 1285 | if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0) | 
|  | 1286 | || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) { | 
|  | 1287 | ENGINE_free(e); | 
|  | 1288 | e = NULL; | 
|  | 1289 | } | 
|  | 1290 | } | 
|  | 1291 | return e; | 
|  | 1292 | } | 
|  | 1293 | #endif | 
|  | 1294 |  | 
|  | 1295 | ENGINE *setup_engine(const char *engine, int debug) | 
|  | 1296 | { | 
|  | 1297 | ENGINE *e = NULL; | 
|  | 1298 |  | 
|  | 1299 | #ifndef OPENSSL_NO_ENGINE | 
|  | 1300 | if (engine != NULL) { | 
|  | 1301 | if (strcmp(engine, "auto") == 0) { | 
|  | 1302 | BIO_printf(bio_err, "enabling auto ENGINE support\n"); | 
|  | 1303 | ENGINE_register_all_complete(); | 
|  | 1304 | return NULL; | 
|  | 1305 | } | 
|  | 1306 | if ((e = ENGINE_by_id(engine)) == NULL | 
|  | 1307 | && (e = try_load_engine(engine)) == NULL) { | 
|  | 1308 | BIO_printf(bio_err, "invalid engine \"%s\"\n", engine); | 
|  | 1309 | ERR_print_errors(bio_err); | 
|  | 1310 | return NULL; | 
|  | 1311 | } | 
|  | 1312 | if (debug) { | 
|  | 1313 | ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 0, bio_err, 0); | 
|  | 1314 | } | 
|  | 1315 | ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, ui_method, 0, 1); | 
|  | 1316 | if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { | 
|  | 1317 | BIO_printf(bio_err, "can't use that engine\n"); | 
|  | 1318 | ERR_print_errors(bio_err); | 
|  | 1319 | ENGINE_free(e); | 
|  | 1320 | return NULL; | 
|  | 1321 | } | 
|  | 1322 |  | 
|  | 1323 | BIO_printf(bio_err, "engine \"%s\" set.\n", ENGINE_get_id(e)); | 
|  | 1324 | } | 
|  | 1325 | #endif | 
|  | 1326 | return e; | 
|  | 1327 | } | 
|  | 1328 |  | 
|  | 1329 | void release_engine(ENGINE *e) | 
|  | 1330 | { | 
|  | 1331 | #ifndef OPENSSL_NO_ENGINE | 
|  | 1332 | if (e != NULL) | 
|  | 1333 | /* Free our "structural" reference. */ | 
|  | 1334 | ENGINE_free(e); | 
|  | 1335 | #endif | 
|  | 1336 | } | 
|  | 1337 |  | 
|  | 1338 | static unsigned long index_serial_hash(const OPENSSL_CSTRING *a) | 
|  | 1339 | { | 
|  | 1340 | const char *n; | 
|  | 1341 |  | 
|  | 1342 | n = a[DB_serial]; | 
|  | 1343 | while (*n == '0') | 
|  | 1344 | n++; | 
|  | 1345 | return OPENSSL_LH_strhash(n); | 
|  | 1346 | } | 
|  | 1347 |  | 
|  | 1348 | static int index_serial_cmp(const OPENSSL_CSTRING *a, | 
|  | 1349 | const OPENSSL_CSTRING *b) | 
|  | 1350 | { | 
|  | 1351 | const char *aa, *bb; | 
|  | 1352 |  | 
|  | 1353 | for (aa = a[DB_serial]; *aa == '0'; aa++) ; | 
|  | 1354 | for (bb = b[DB_serial]; *bb == '0'; bb++) ; | 
|  | 1355 | return strcmp(aa, bb); | 
|  | 1356 | } | 
|  | 1357 |  | 
|  | 1358 | static int index_name_qual(char **a) | 
|  | 1359 | { | 
|  | 1360 | return (a[0][0] == 'V'); | 
|  | 1361 | } | 
|  | 1362 |  | 
|  | 1363 | static unsigned long index_name_hash(const OPENSSL_CSTRING *a) | 
|  | 1364 | { | 
|  | 1365 | return OPENSSL_LH_strhash(a[DB_name]); | 
|  | 1366 | } | 
|  | 1367 |  | 
|  | 1368 | int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b) | 
|  | 1369 | { | 
|  | 1370 | return strcmp(a[DB_name], b[DB_name]); | 
|  | 1371 | } | 
|  | 1372 |  | 
|  | 1373 | static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING) | 
|  | 1374 | static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING) | 
|  | 1375 | static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING) | 
|  | 1376 | static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING) | 
|  | 1377 | #undef BSIZE | 
|  | 1378 | #define BSIZE 256 | 
|  | 1379 | BIGNUM *load_serial(const char *serialfile, int *exists, int create, | 
|  | 1380 | ASN1_INTEGER **retai) | 
|  | 1381 | { | 
|  | 1382 | BIO *in = NULL; | 
|  | 1383 | BIGNUM *ret = NULL; | 
|  | 1384 | char buf[1024]; | 
|  | 1385 | ASN1_INTEGER *ai = NULL; | 
|  | 1386 |  | 
|  | 1387 | ai = ASN1_INTEGER_new(); | 
|  | 1388 | if (ai == NULL) | 
|  | 1389 | goto err; | 
|  | 1390 |  | 
|  | 1391 | in = BIO_new_file(serialfile, "r"); | 
|  | 1392 | if (exists != NULL) | 
|  | 1393 | *exists = in != NULL; | 
|  | 1394 | if (in == NULL) { | 
|  | 1395 | if (!create) { | 
|  | 1396 | perror(serialfile); | 
|  | 1397 | goto err; | 
|  | 1398 | } | 
|  | 1399 | ERR_clear_error(); | 
|  | 1400 | ret = BN_new(); | 
|  | 1401 | if (ret == NULL) { | 
|  | 1402 | BIO_printf(bio_err, "Out of memory\n"); | 
|  | 1403 | } else if (!rand_serial(ret, ai)) { | 
|  | 1404 | BIO_printf(bio_err, "Error creating random number to store in %s\n", | 
|  | 1405 | serialfile); | 
|  | 1406 | BN_free(ret); | 
|  | 1407 | ret = NULL; | 
|  | 1408 | } | 
|  | 1409 | } else { | 
|  | 1410 | if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) { | 
|  | 1411 | BIO_printf(bio_err, "unable to load number from %s\n", | 
|  | 1412 | serialfile); | 
|  | 1413 | goto err; | 
|  | 1414 | } | 
|  | 1415 | ret = ASN1_INTEGER_to_BN(ai, NULL); | 
|  | 1416 | if (ret == NULL) { | 
|  | 1417 | BIO_printf(bio_err, | 
|  | 1418 | "error converting number from bin to BIGNUM\n"); | 
|  | 1419 | goto err; | 
|  | 1420 | } | 
|  | 1421 | } | 
|  | 1422 |  | 
|  | 1423 | if (ret && retai) { | 
|  | 1424 | *retai = ai; | 
|  | 1425 | ai = NULL; | 
|  | 1426 | } | 
|  | 1427 | err: | 
|  | 1428 | if (ret == NULL) | 
|  | 1429 | ERR_print_errors(bio_err); | 
|  | 1430 | BIO_free(in); | 
|  | 1431 | ASN1_INTEGER_free(ai); | 
|  | 1432 | return ret; | 
|  | 1433 | } | 
|  | 1434 |  | 
|  | 1435 | int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial, | 
|  | 1436 | ASN1_INTEGER **retai) | 
|  | 1437 | { | 
|  | 1438 | char buf[1][BSIZE]; | 
|  | 1439 | BIO *out = NULL; | 
|  | 1440 | int ret = 0; | 
|  | 1441 | ASN1_INTEGER *ai = NULL; | 
|  | 1442 | int j; | 
|  | 1443 |  | 
|  | 1444 | if (suffix == NULL) | 
|  | 1445 | j = strlen(serialfile); | 
|  | 1446 | else | 
|  | 1447 | j = strlen(serialfile) + strlen(suffix) + 1; | 
|  | 1448 | if (j >= BSIZE) { | 
|  | 1449 | BIO_printf(bio_err, "file name too long\n"); | 
|  | 1450 | goto err; | 
|  | 1451 | } | 
|  | 1452 |  | 
|  | 1453 | if (suffix == NULL) | 
|  | 1454 | OPENSSL_strlcpy(buf[0], serialfile, BSIZE); | 
|  | 1455 | else { | 
|  | 1456 | #ifndef OPENSSL_SYS_VMS | 
|  | 1457 | j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, suffix); | 
|  | 1458 | #else | 
|  | 1459 | j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, suffix); | 
|  | 1460 | #endif | 
|  | 1461 | } | 
|  | 1462 | out = BIO_new_file(buf[0], "w"); | 
|  | 1463 | if (out == NULL) { | 
|  | 1464 | ERR_print_errors(bio_err); | 
|  | 1465 | goto err; | 
|  | 1466 | } | 
|  | 1467 |  | 
|  | 1468 | if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) { | 
|  | 1469 | BIO_printf(bio_err, "error converting serial to ASN.1 format\n"); | 
|  | 1470 | goto err; | 
|  | 1471 | } | 
|  | 1472 | i2a_ASN1_INTEGER(out, ai); | 
|  | 1473 | BIO_puts(out, "\n"); | 
|  | 1474 | ret = 1; | 
|  | 1475 | if (retai) { | 
|  | 1476 | *retai = ai; | 
|  | 1477 | ai = NULL; | 
|  | 1478 | } | 
|  | 1479 | err: | 
|  | 1480 | BIO_free_all(out); | 
|  | 1481 | ASN1_INTEGER_free(ai); | 
|  | 1482 | return ret; | 
|  | 1483 | } | 
|  | 1484 |  | 
|  | 1485 | int rotate_serial(const char *serialfile, const char *new_suffix, | 
|  | 1486 | const char *old_suffix) | 
|  | 1487 | { | 
|  | 1488 | char buf[2][BSIZE]; | 
|  | 1489 | int i, j; | 
|  | 1490 |  | 
|  | 1491 | i = strlen(serialfile) + strlen(old_suffix); | 
|  | 1492 | j = strlen(serialfile) + strlen(new_suffix); | 
|  | 1493 | if (i > j) | 
|  | 1494 | j = i; | 
|  | 1495 | if (j + 1 >= BSIZE) { | 
|  | 1496 | BIO_printf(bio_err, "file name too long\n"); | 
|  | 1497 | goto err; | 
|  | 1498 | } | 
|  | 1499 | #ifndef OPENSSL_SYS_VMS | 
|  | 1500 | j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, new_suffix); | 
|  | 1501 | j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", serialfile, old_suffix); | 
|  | 1502 | #else | 
|  | 1503 | j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, new_suffix); | 
|  | 1504 | j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", serialfile, old_suffix); | 
|  | 1505 | #endif | 
|  | 1506 | if (rename(serialfile, buf[1]) < 0 && errno != ENOENT | 
|  | 1507 | #ifdef ENOTDIR | 
|  | 1508 | && errno != ENOTDIR | 
|  | 1509 | #endif | 
|  | 1510 | ) { | 
|  | 1511 | BIO_printf(bio_err, | 
|  | 1512 | "unable to rename %s to %s\n", serialfile, buf[1]); | 
|  | 1513 | perror("reason"); | 
|  | 1514 | goto err; | 
|  | 1515 | } | 
|  | 1516 | if (rename(buf[0], serialfile) < 0) { | 
|  | 1517 | BIO_printf(bio_err, | 
|  | 1518 | "unable to rename %s to %s\n", buf[0], serialfile); | 
|  | 1519 | perror("reason"); | 
|  | 1520 | rename(buf[1], serialfile); | 
|  | 1521 | goto err; | 
|  | 1522 | } | 
|  | 1523 | return 1; | 
|  | 1524 | err: | 
|  | 1525 | return 0; | 
|  | 1526 | } | 
|  | 1527 |  | 
|  | 1528 | int rand_serial(BIGNUM *b, ASN1_INTEGER *ai) | 
|  | 1529 | { | 
|  | 1530 | BIGNUM *btmp; | 
|  | 1531 | int ret = 0; | 
|  | 1532 |  | 
|  | 1533 | btmp = b == NULL ? BN_new() : b; | 
|  | 1534 | if (btmp == NULL) | 
|  | 1535 | return 0; | 
|  | 1536 |  | 
|  | 1537 | if (!BN_rand(btmp, SERIAL_RAND_BITS, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) | 
|  | 1538 | goto error; | 
|  | 1539 | if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) | 
|  | 1540 | goto error; | 
|  | 1541 |  | 
|  | 1542 | ret = 1; | 
|  | 1543 |  | 
|  | 1544 | error: | 
|  | 1545 |  | 
|  | 1546 | if (btmp != b) | 
|  | 1547 | BN_free(btmp); | 
|  | 1548 |  | 
|  | 1549 | return ret; | 
|  | 1550 | } | 
|  | 1551 |  | 
|  | 1552 | CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr) | 
|  | 1553 | { | 
|  | 1554 | CA_DB *retdb = NULL; | 
|  | 1555 | TXT_DB *tmpdb = NULL; | 
|  | 1556 | BIO *in; | 
|  | 1557 | CONF *dbattr_conf = NULL; | 
|  | 1558 | char buf[BSIZE]; | 
|  | 1559 | #ifndef OPENSSL_NO_POSIX_IO | 
|  | 1560 | FILE *dbfp; | 
|  | 1561 | struct stat dbst; | 
|  | 1562 | #endif | 
|  | 1563 |  | 
|  | 1564 | in = BIO_new_file(dbfile, "r"); | 
|  | 1565 | if (in == NULL) { | 
|  | 1566 | ERR_print_errors(bio_err); | 
|  | 1567 | goto err; | 
|  | 1568 | } | 
|  | 1569 |  | 
|  | 1570 | #ifndef OPENSSL_NO_POSIX_IO | 
|  | 1571 | BIO_get_fp(in, &dbfp); | 
|  | 1572 | if (fstat(fileno(dbfp), &dbst) == -1) { | 
|  | 1573 | SYSerr(SYS_F_FSTAT, errno); | 
|  | 1574 | ERR_add_error_data(3, "fstat('", dbfile, "')"); | 
|  | 1575 | ERR_print_errors(bio_err); | 
|  | 1576 | goto err; | 
|  | 1577 | } | 
|  | 1578 | #endif | 
|  | 1579 |  | 
|  | 1580 | if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL) | 
|  | 1581 | goto err; | 
|  | 1582 |  | 
|  | 1583 | #ifndef OPENSSL_SYS_VMS | 
|  | 1584 | BIO_snprintf(buf, sizeof(buf), "%s.attr", dbfile); | 
|  | 1585 | #else | 
|  | 1586 | BIO_snprintf(buf, sizeof(buf), "%s-attr", dbfile); | 
|  | 1587 | #endif | 
|  | 1588 | dbattr_conf = app_load_config_quiet(buf); | 
|  | 1589 |  | 
|  | 1590 | retdb = app_malloc(sizeof(*retdb), "new DB"); | 
|  | 1591 | retdb->db = tmpdb; | 
|  | 1592 | tmpdb = NULL; | 
|  | 1593 | if (db_attr) | 
|  | 1594 | retdb->attributes = *db_attr; | 
|  | 1595 | else { | 
|  | 1596 | retdb->attributes.unique_subject = 1; | 
|  | 1597 | } | 
|  | 1598 |  | 
|  | 1599 | if (dbattr_conf) { | 
|  | 1600 | char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject"); | 
|  | 1601 | if (p) { | 
|  | 1602 | retdb->attributes.unique_subject = parse_yesno(p, 1); | 
|  | 1603 | } | 
|  | 1604 | } | 
|  | 1605 |  | 
|  | 1606 | retdb->dbfname = OPENSSL_strdup(dbfile); | 
|  | 1607 | #ifndef OPENSSL_NO_POSIX_IO | 
|  | 1608 | retdb->dbst = dbst; | 
|  | 1609 | #endif | 
|  | 1610 |  | 
|  | 1611 | err: | 
|  | 1612 | NCONF_free(dbattr_conf); | 
|  | 1613 | TXT_DB_free(tmpdb); | 
|  | 1614 | BIO_free_all(in); | 
|  | 1615 | return retdb; | 
|  | 1616 | } | 
|  | 1617 |  | 
|  | 1618 | /* | 
|  | 1619 | * Returns > 0 on success, <= 0 on error | 
|  | 1620 | */ | 
|  | 1621 | int index_index(CA_DB *db) | 
|  | 1622 | { | 
|  | 1623 | if (!TXT_DB_create_index(db->db, DB_serial, NULL, | 
|  | 1624 | LHASH_HASH_FN(index_serial), | 
|  | 1625 | LHASH_COMP_FN(index_serial))) { | 
|  | 1626 | BIO_printf(bio_err, | 
|  | 1627 | "error creating serial number index:(%ld,%ld,%ld)\n", | 
|  | 1628 | db->db->error, db->db->arg1, db->db->arg2); | 
|  | 1629 | return 0; | 
|  | 1630 | } | 
|  | 1631 |  | 
|  | 1632 | if (db->attributes.unique_subject | 
|  | 1633 | && !TXT_DB_create_index(db->db, DB_name, index_name_qual, | 
|  | 1634 | LHASH_HASH_FN(index_name), | 
|  | 1635 | LHASH_COMP_FN(index_name))) { | 
|  | 1636 | BIO_printf(bio_err, "error creating name index:(%ld,%ld,%ld)\n", | 
|  | 1637 | db->db->error, db->db->arg1, db->db->arg2); | 
|  | 1638 | return 0; | 
|  | 1639 | } | 
|  | 1640 | return 1; | 
|  | 1641 | } | 
|  | 1642 |  | 
|  | 1643 | int save_index(const char *dbfile, const char *suffix, CA_DB *db) | 
|  | 1644 | { | 
|  | 1645 | char buf[3][BSIZE]; | 
|  | 1646 | BIO *out; | 
|  | 1647 | int j; | 
|  | 1648 |  | 
|  | 1649 | j = strlen(dbfile) + strlen(suffix); | 
|  | 1650 | if (j + 6 >= BSIZE) { | 
|  | 1651 | BIO_printf(bio_err, "file name too long\n"); | 
|  | 1652 | goto err; | 
|  | 1653 | } | 
|  | 1654 | #ifndef OPENSSL_SYS_VMS | 
|  | 1655 | j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr", dbfile); | 
|  | 1656 | j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.attr.%s", dbfile, suffix); | 
|  | 1657 | j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, suffix); | 
|  | 1658 | #else | 
|  | 1659 | j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr", dbfile); | 
|  | 1660 | j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-attr-%s", dbfile, suffix); | 
|  | 1661 | j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, suffix); | 
|  | 1662 | #endif | 
|  | 1663 | out = BIO_new_file(buf[0], "w"); | 
|  | 1664 | if (out == NULL) { | 
|  | 1665 | perror(dbfile); | 
|  | 1666 | BIO_printf(bio_err, "unable to open '%s'\n", dbfile); | 
|  | 1667 | goto err; | 
|  | 1668 | } | 
|  | 1669 | j = TXT_DB_write(out, db->db); | 
|  | 1670 | BIO_free(out); | 
|  | 1671 | if (j <= 0) | 
|  | 1672 | goto err; | 
|  | 1673 |  | 
|  | 1674 | out = BIO_new_file(buf[1], "w"); | 
|  | 1675 | if (out == NULL) { | 
|  | 1676 | perror(buf[2]); | 
|  | 1677 | BIO_printf(bio_err, "unable to open '%s'\n", buf[2]); | 
|  | 1678 | goto err; | 
|  | 1679 | } | 
|  | 1680 | BIO_printf(out, "unique_subject = %s\n", | 
|  | 1681 | db->attributes.unique_subject ? "yes" : "no"); | 
|  | 1682 | BIO_free(out); | 
|  | 1683 |  | 
|  | 1684 | return 1; | 
|  | 1685 | err: | 
|  | 1686 | return 0; | 
|  | 1687 | } | 
|  | 1688 |  | 
|  | 1689 | int rotate_index(const char *dbfile, const char *new_suffix, | 
|  | 1690 | const char *old_suffix) | 
|  | 1691 | { | 
|  | 1692 | char buf[5][BSIZE]; | 
|  | 1693 | int i, j; | 
|  | 1694 |  | 
|  | 1695 | i = strlen(dbfile) + strlen(old_suffix); | 
|  | 1696 | j = strlen(dbfile) + strlen(new_suffix); | 
|  | 1697 | if (i > j) | 
|  | 1698 | j = i; | 
|  | 1699 | if (j + 6 >= BSIZE) { | 
|  | 1700 | BIO_printf(bio_err, "file name too long\n"); | 
|  | 1701 | goto err; | 
|  | 1702 | } | 
|  | 1703 | #ifndef OPENSSL_SYS_VMS | 
|  | 1704 | j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s.attr", dbfile); | 
|  | 1705 | j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s.attr.%s", dbfile, old_suffix); | 
|  | 1706 | j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr.%s", dbfile, new_suffix); | 
|  | 1707 | j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", dbfile, old_suffix); | 
|  | 1708 | j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", dbfile, new_suffix); | 
|  | 1709 | #else | 
|  | 1710 | j = BIO_snprintf(buf[4], sizeof(buf[4]), "%s-attr", dbfile); | 
|  | 1711 | j = BIO_snprintf(buf[3], sizeof(buf[3]), "%s-attr-%s", dbfile, old_suffix); | 
|  | 1712 | j = BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr-%s", dbfile, new_suffix); | 
|  | 1713 | j = BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", dbfile, old_suffix); | 
|  | 1714 | j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, new_suffix); | 
|  | 1715 | #endif | 
|  | 1716 | if (rename(dbfile, buf[1]) < 0 && errno != ENOENT | 
|  | 1717 | #ifdef ENOTDIR | 
|  | 1718 | && errno != ENOTDIR | 
|  | 1719 | #endif | 
|  | 1720 | ) { | 
|  | 1721 | BIO_printf(bio_err, "unable to rename %s to %s\n", dbfile, buf[1]); | 
|  | 1722 | perror("reason"); | 
|  | 1723 | goto err; | 
|  | 1724 | } | 
|  | 1725 | if (rename(buf[0], dbfile) < 0) { | 
|  | 1726 | BIO_printf(bio_err, "unable to rename %s to %s\n", buf[0], dbfile); | 
|  | 1727 | perror("reason"); | 
|  | 1728 | rename(buf[1], dbfile); | 
|  | 1729 | goto err; | 
|  | 1730 | } | 
|  | 1731 | if (rename(buf[4], buf[3]) < 0 && errno != ENOENT | 
|  | 1732 | #ifdef ENOTDIR | 
|  | 1733 | && errno != ENOTDIR | 
|  | 1734 | #endif | 
|  | 1735 | ) { | 
|  | 1736 | BIO_printf(bio_err, "unable to rename %s to %s\n", buf[4], buf[3]); | 
|  | 1737 | perror("reason"); | 
|  | 1738 | rename(dbfile, buf[0]); | 
|  | 1739 | rename(buf[1], dbfile); | 
|  | 1740 | goto err; | 
|  | 1741 | } | 
|  | 1742 | if (rename(buf[2], buf[4]) < 0) { | 
|  | 1743 | BIO_printf(bio_err, "unable to rename %s to %s\n", buf[2], buf[4]); | 
|  | 1744 | perror("reason"); | 
|  | 1745 | rename(buf[3], buf[4]); | 
|  | 1746 | rename(dbfile, buf[0]); | 
|  | 1747 | rename(buf[1], dbfile); | 
|  | 1748 | goto err; | 
|  | 1749 | } | 
|  | 1750 | return 1; | 
|  | 1751 | err: | 
|  | 1752 | return 0; | 
|  | 1753 | } | 
|  | 1754 |  | 
|  | 1755 | void free_index(CA_DB *db) | 
|  | 1756 | { | 
|  | 1757 | if (db) { | 
|  | 1758 | TXT_DB_free(db->db); | 
|  | 1759 | OPENSSL_free(db->dbfname); | 
|  | 1760 | OPENSSL_free(db); | 
|  | 1761 | } | 
|  | 1762 | } | 
|  | 1763 |  | 
|  | 1764 | int parse_yesno(const char *str, int def) | 
|  | 1765 | { | 
|  | 1766 | if (str) { | 
|  | 1767 | switch (*str) { | 
|  | 1768 | case 'f':              /* false */ | 
|  | 1769 | case 'F':              /* FALSE */ | 
|  | 1770 | case 'n':              /* no */ | 
|  | 1771 | case 'N':              /* NO */ | 
|  | 1772 | case '0':              /* 0 */ | 
|  | 1773 | return 0; | 
|  | 1774 | case 't':              /* true */ | 
|  | 1775 | case 'T':              /* TRUE */ | 
|  | 1776 | case 'y':              /* yes */ | 
|  | 1777 | case 'Y':              /* YES */ | 
|  | 1778 | case '1':              /* 1 */ | 
|  | 1779 | return 1; | 
|  | 1780 | } | 
|  | 1781 | } | 
|  | 1782 | return def; | 
|  | 1783 | } | 
|  | 1784 |  | 
|  | 1785 | /* | 
|  | 1786 | * name is expected to be in the format /type0=value0/type1=value1/type2=... | 
|  | 1787 | * where characters may be escaped by \ | 
|  | 1788 | */ | 
|  | 1789 | X509_NAME *parse_name(const char *cp, long chtype, int canmulti) | 
|  | 1790 | { | 
|  | 1791 | int nextismulti = 0; | 
|  | 1792 | char *work; | 
|  | 1793 | X509_NAME *n; | 
|  | 1794 |  | 
|  | 1795 | if (*cp++ != '/') { | 
|  | 1796 | BIO_printf(bio_err, | 
|  | 1797 | "name is expected to be in the format " | 
|  | 1798 | "/type0=value0/type1=value1/type2=... where characters may " | 
|  | 1799 | "be escaped by \\. This name is not in that format: '%s'\n", | 
|  | 1800 | --cp); | 
|  | 1801 | return NULL; | 
|  | 1802 | } | 
|  | 1803 |  | 
|  | 1804 | n = X509_NAME_new(); | 
|  | 1805 | if (n == NULL) | 
|  | 1806 | return NULL; | 
|  | 1807 | work = OPENSSL_strdup(cp); | 
|  | 1808 | if (work == NULL) | 
|  | 1809 | goto err; | 
|  | 1810 |  | 
|  | 1811 | while (*cp) { | 
|  | 1812 | char *bp = work; | 
|  | 1813 | char *typestr = bp; | 
|  | 1814 | unsigned char *valstr; | 
|  | 1815 | int nid; | 
|  | 1816 | int ismulti = nextismulti; | 
|  | 1817 | nextismulti = 0; | 
|  | 1818 |  | 
|  | 1819 | /* Collect the type */ | 
|  | 1820 | while (*cp && *cp != '=') | 
|  | 1821 | *bp++ = *cp++; | 
|  | 1822 | if (*cp == '\0') { | 
|  | 1823 | BIO_printf(bio_err, | 
|  | 1824 | "%s: Hit end of string before finding the equals.\n", | 
|  | 1825 | opt_getprog()); | 
|  | 1826 | goto err; | 
|  | 1827 | } | 
|  | 1828 | *bp++ = '\0'; | 
|  | 1829 | ++cp; | 
|  | 1830 |  | 
|  | 1831 | /* Collect the value. */ | 
|  | 1832 | valstr = (unsigned char *)bp; | 
|  | 1833 | for (; *cp && *cp != '/'; *bp++ = *cp++) { | 
|  | 1834 | if (canmulti && *cp == '+') { | 
|  | 1835 | nextismulti = 1; | 
|  | 1836 | break; | 
|  | 1837 | } | 
|  | 1838 | if (*cp == '\\' && *++cp == '\0') { | 
|  | 1839 | BIO_printf(bio_err, | 
|  | 1840 | "%s: escape character at end of string\n", | 
|  | 1841 | opt_getprog()); | 
|  | 1842 | goto err; | 
|  | 1843 | } | 
|  | 1844 | } | 
|  | 1845 | *bp++ = '\0'; | 
|  | 1846 |  | 
|  | 1847 | /* If not at EOS (must be + or /), move forward. */ | 
|  | 1848 | if (*cp) | 
|  | 1849 | ++cp; | 
|  | 1850 |  | 
|  | 1851 | /* Parse */ | 
|  | 1852 | nid = OBJ_txt2nid(typestr); | 
|  | 1853 | if (nid == NID_undef) { | 
|  | 1854 | BIO_printf(bio_err, "%s: Skipping unknown attribute \"%s\"\n", | 
|  | 1855 | opt_getprog(), typestr); | 
|  | 1856 | continue; | 
|  | 1857 | } | 
|  | 1858 | if (*valstr == '\0') { | 
|  | 1859 | BIO_printf(bio_err, | 
|  | 1860 | "%s: No value provided for Subject Attribute %s, skipped\n", | 
|  | 1861 | opt_getprog(), typestr); | 
|  | 1862 | continue; | 
|  | 1863 | } | 
|  | 1864 | if (!X509_NAME_add_entry_by_NID(n, nid, chtype, | 
|  | 1865 | valstr, strlen((char *)valstr), | 
|  | 1866 | -1, ismulti ? -1 : 0)) | 
|  | 1867 | goto err; | 
|  | 1868 | } | 
|  | 1869 |  | 
|  | 1870 | OPENSSL_free(work); | 
|  | 1871 | return n; | 
|  | 1872 |  | 
|  | 1873 | err: | 
|  | 1874 | X509_NAME_free(n); | 
|  | 1875 | OPENSSL_free(work); | 
|  | 1876 | return NULL; | 
|  | 1877 | } | 
|  | 1878 |  | 
|  | 1879 | /* | 
|  | 1880 | * Read whole contents of a BIO into an allocated memory buffer and return | 
|  | 1881 | * it. | 
|  | 1882 | */ | 
|  | 1883 |  | 
|  | 1884 | int bio_to_mem(unsigned char **out, int maxlen, BIO *in) | 
|  | 1885 | { | 
|  | 1886 | BIO *mem; | 
|  | 1887 | int len, ret; | 
|  | 1888 | unsigned char tbuf[1024]; | 
|  | 1889 |  | 
|  | 1890 | mem = BIO_new(BIO_s_mem()); | 
|  | 1891 | if (mem == NULL) | 
|  | 1892 | return -1; | 
|  | 1893 | for (;;) { | 
|  | 1894 | if ((maxlen != -1) && maxlen < 1024) | 
|  | 1895 | len = maxlen; | 
|  | 1896 | else | 
|  | 1897 | len = 1024; | 
|  | 1898 | len = BIO_read(in, tbuf, len); | 
|  | 1899 | if (len < 0) { | 
|  | 1900 | BIO_free(mem); | 
|  | 1901 | return -1; | 
|  | 1902 | } | 
|  | 1903 | if (len == 0) | 
|  | 1904 | break; | 
|  | 1905 | if (BIO_write(mem, tbuf, len) != len) { | 
|  | 1906 | BIO_free(mem); | 
|  | 1907 | return -1; | 
|  | 1908 | } | 
|  | 1909 | maxlen -= len; | 
|  | 1910 |  | 
|  | 1911 | if (maxlen == 0) | 
|  | 1912 | break; | 
|  | 1913 | } | 
|  | 1914 | ret = BIO_get_mem_data(mem, (char **)out); | 
|  | 1915 | BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY); | 
|  | 1916 | BIO_free(mem); | 
|  | 1917 | return ret; | 
|  | 1918 | } | 
|  | 1919 |  | 
|  | 1920 | int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value) | 
|  | 1921 | { | 
|  | 1922 | int rv; | 
|  | 1923 | char *stmp, *vtmp = NULL; | 
|  | 1924 | stmp = OPENSSL_strdup(value); | 
|  | 1925 | if (!stmp) | 
|  | 1926 | return -1; | 
|  | 1927 | vtmp = strchr(stmp, ':'); | 
|  | 1928 | if (vtmp) { | 
|  | 1929 | *vtmp = 0; | 
|  | 1930 | vtmp++; | 
|  | 1931 | } | 
|  | 1932 | rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp); | 
|  | 1933 | OPENSSL_free(stmp); | 
|  | 1934 | return rv; | 
|  | 1935 | } | 
|  | 1936 |  | 
|  | 1937 | static void nodes_print(const char *name, STACK_OF(X509_POLICY_NODE) *nodes) | 
|  | 1938 | { | 
|  | 1939 | X509_POLICY_NODE *node; | 
|  | 1940 | int i; | 
|  | 1941 |  | 
|  | 1942 | BIO_printf(bio_err, "%s Policies:", name); | 
|  | 1943 | if (nodes) { | 
|  | 1944 | BIO_puts(bio_err, "\n"); | 
|  | 1945 | for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) { | 
|  | 1946 | node = sk_X509_POLICY_NODE_value(nodes, i); | 
|  | 1947 | X509_POLICY_NODE_print(bio_err, node, 2); | 
|  | 1948 | } | 
|  | 1949 | } else { | 
|  | 1950 | BIO_puts(bio_err, " <empty>\n"); | 
|  | 1951 | } | 
|  | 1952 | } | 
|  | 1953 |  | 
|  | 1954 | void policies_print(X509_STORE_CTX *ctx) | 
|  | 1955 | { | 
|  | 1956 | X509_POLICY_TREE *tree; | 
|  | 1957 | int explicit_policy; | 
|  | 1958 | tree = X509_STORE_CTX_get0_policy_tree(ctx); | 
|  | 1959 | explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx); | 
|  | 1960 |  | 
|  | 1961 | BIO_printf(bio_err, "Require explicit Policy: %s\n", | 
|  | 1962 | explicit_policy ? "True" : "False"); | 
|  | 1963 |  | 
|  | 1964 | nodes_print("Authority", X509_policy_tree_get0_policies(tree)); | 
|  | 1965 | nodes_print("User", X509_policy_tree_get0_user_policies(tree)); | 
|  | 1966 | } | 
|  | 1967 |  | 
|  | 1968 | /*- | 
|  | 1969 | * next_protos_parse parses a comma separated list of strings into a string | 
|  | 1970 | * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. | 
|  | 1971 | *   outlen: (output) set to the length of the resulting buffer on success. | 
|  | 1972 | *   err: (maybe NULL) on failure, an error message line is written to this BIO. | 
|  | 1973 | *   in: a NUL terminated string like "abc,def,ghi" | 
|  | 1974 | * | 
|  | 1975 | *   returns: a malloc'd buffer or NULL on failure. | 
|  | 1976 | */ | 
|  | 1977 | unsigned char *next_protos_parse(size_t *outlen, const char *in) | 
|  | 1978 | { | 
|  | 1979 | size_t len; | 
|  | 1980 | unsigned char *out; | 
|  | 1981 | size_t i, start = 0; | 
|  | 1982 | size_t skipped = 0; | 
|  | 1983 |  | 
|  | 1984 | len = strlen(in); | 
|  | 1985 | if (len == 0 || len >= 65535) | 
|  | 1986 | return NULL; | 
|  | 1987 |  | 
|  | 1988 | out = app_malloc(len + 1, "NPN buffer"); | 
|  | 1989 | for (i = 0; i <= len; ++i) { | 
|  | 1990 | if (i == len || in[i] == ',') { | 
|  | 1991 | /* | 
|  | 1992 | * Zero-length ALPN elements are invalid on the wire, we could be | 
|  | 1993 | * strict and reject the entire string, but just ignoring extra | 
|  | 1994 | * commas seems harmless and more friendly. | 
|  | 1995 | * | 
|  | 1996 | * Every comma we skip in this way puts the input buffer another | 
|  | 1997 | * byte ahead of the output buffer, so all stores into the output | 
|  | 1998 | * buffer need to be decremented by the number commas skipped. | 
|  | 1999 | */ | 
|  | 2000 | if (i == start) { | 
|  | 2001 | ++start; | 
|  | 2002 | ++skipped; | 
|  | 2003 | continue; | 
|  | 2004 | } | 
|  | 2005 | if (i - start > 255) { | 
|  | 2006 | OPENSSL_free(out); | 
|  | 2007 | return NULL; | 
|  | 2008 | } | 
|  | 2009 | out[start-skipped] = (unsigned char)(i - start); | 
|  | 2010 | start = i + 1; | 
|  | 2011 | } else { | 
|  | 2012 | out[i + 1 - skipped] = in[i]; | 
|  | 2013 | } | 
|  | 2014 | } | 
|  | 2015 |  | 
|  | 2016 | if (len <= skipped) { | 
|  | 2017 | OPENSSL_free(out); | 
|  | 2018 | return NULL; | 
|  | 2019 | } | 
|  | 2020 |  | 
|  | 2021 | *outlen = len + 1 - skipped; | 
|  | 2022 | return out; | 
|  | 2023 | } | 
|  | 2024 |  | 
|  | 2025 | void print_cert_checks(BIO *bio, X509 *x, | 
|  | 2026 | const char *checkhost, | 
|  | 2027 | const char *checkemail, const char *checkip) | 
|  | 2028 | { | 
|  | 2029 | if (x == NULL) | 
|  | 2030 | return; | 
|  | 2031 | if (checkhost) { | 
|  | 2032 | BIO_printf(bio, "Hostname %s does%s match certificate\n", | 
|  | 2033 | checkhost, | 
|  | 2034 | X509_check_host(x, checkhost, 0, 0, NULL) == 1 | 
|  | 2035 | ? "" : " NOT"); | 
|  | 2036 | } | 
|  | 2037 |  | 
|  | 2038 | if (checkemail) { | 
|  | 2039 | BIO_printf(bio, "Email %s does%s match certificate\n", | 
|  | 2040 | checkemail, X509_check_email(x, checkemail, 0, 0) | 
|  | 2041 | ? "" : " NOT"); | 
|  | 2042 | } | 
|  | 2043 |  | 
|  | 2044 | if (checkip) { | 
|  | 2045 | BIO_printf(bio, "IP %s does%s match certificate\n", | 
|  | 2046 | checkip, X509_check_ip_asc(x, checkip, 0) ? "" : " NOT"); | 
|  | 2047 | } | 
|  | 2048 | } | 
|  | 2049 |  | 
|  | 2050 | /* Get first http URL from a DIST_POINT structure */ | 
|  | 2051 |  | 
|  | 2052 | static const char *get_dp_url(DIST_POINT *dp) | 
|  | 2053 | { | 
|  | 2054 | GENERAL_NAMES *gens; | 
|  | 2055 | GENERAL_NAME *gen; | 
|  | 2056 | int i, gtype; | 
|  | 2057 | ASN1_STRING *uri; | 
|  | 2058 | if (!dp->distpoint || dp->distpoint->type != 0) | 
|  | 2059 | return NULL; | 
|  | 2060 | gens = dp->distpoint->name.fullname; | 
|  | 2061 | for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { | 
|  | 2062 | gen = sk_GENERAL_NAME_value(gens, i); | 
|  | 2063 | uri = GENERAL_NAME_get0_value(gen, >ype); | 
|  | 2064 | if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6) { | 
|  | 2065 | const char *uptr = (const char *)ASN1_STRING_get0_data(uri); | 
|  | 2066 | if (strncmp(uptr, "http://", 7) == 0) | 
|  | 2067 | return uptr; | 
|  | 2068 | } | 
|  | 2069 | } | 
|  | 2070 | return NULL; | 
|  | 2071 | } | 
|  | 2072 |  | 
|  | 2073 | /* | 
|  | 2074 | * Look through a CRLDP structure and attempt to find an http URL to | 
|  | 2075 | * downloads a CRL from. | 
|  | 2076 | */ | 
|  | 2077 |  | 
|  | 2078 | static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp) | 
|  | 2079 | { | 
|  | 2080 | int i; | 
|  | 2081 | const char *urlptr = NULL; | 
|  | 2082 | for (i = 0; i < sk_DIST_POINT_num(crldp); i++) { | 
|  | 2083 | DIST_POINT *dp = sk_DIST_POINT_value(crldp, i); | 
|  | 2084 | urlptr = get_dp_url(dp); | 
|  | 2085 | if (urlptr) | 
|  | 2086 | return load_crl(urlptr, FORMAT_HTTP); | 
|  | 2087 | } | 
|  | 2088 | return NULL; | 
|  | 2089 | } | 
|  | 2090 |  | 
|  | 2091 | /* | 
|  | 2092 | * Example of downloading CRLs from CRLDP: not usable for real world as it | 
|  | 2093 | * always downloads, doesn't support non-blocking I/O and doesn't cache | 
|  | 2094 | * anything. | 
|  | 2095 | */ | 
|  | 2096 |  | 
|  | 2097 | static STACK_OF(X509_CRL) *crls_http_cb(X509_STORE_CTX *ctx, X509_NAME *nm) | 
|  | 2098 | { | 
|  | 2099 | X509 *x; | 
|  | 2100 | STACK_OF(X509_CRL) *crls = NULL; | 
|  | 2101 | X509_CRL *crl; | 
|  | 2102 | STACK_OF(DIST_POINT) *crldp; | 
|  | 2103 |  | 
|  | 2104 | crls = sk_X509_CRL_new_null(); | 
|  | 2105 | if (!crls) | 
|  | 2106 | return NULL; | 
|  | 2107 | x = X509_STORE_CTX_get_current_cert(ctx); | 
|  | 2108 | crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL); | 
|  | 2109 | crl = load_crl_crldp(crldp); | 
|  | 2110 | sk_DIST_POINT_pop_free(crldp, DIST_POINT_free); | 
|  | 2111 | if (!crl) { | 
|  | 2112 | sk_X509_CRL_free(crls); | 
|  | 2113 | return NULL; | 
|  | 2114 | } | 
|  | 2115 | sk_X509_CRL_push(crls, crl); | 
|  | 2116 | /* Try to download delta CRL */ | 
|  | 2117 | crldp = X509_get_ext_d2i(x, NID_freshest_crl, NULL, NULL); | 
|  | 2118 | crl = load_crl_crldp(crldp); | 
|  | 2119 | sk_DIST_POINT_pop_free(crldp, DIST_POINT_free); | 
|  | 2120 | if (crl) | 
|  | 2121 | sk_X509_CRL_push(crls, crl); | 
|  | 2122 | return crls; | 
|  | 2123 | } | 
|  | 2124 |  | 
|  | 2125 | void store_setup_crl_download(X509_STORE *st) | 
|  | 2126 | { | 
|  | 2127 | X509_STORE_set_lookup_crls_cb(st, crls_http_cb); | 
|  | 2128 | } | 
|  | 2129 |  | 
|  | 2130 | /* | 
|  | 2131 | * Platform-specific sections | 
|  | 2132 | */ | 
|  | 2133 | #if defined(_WIN32) | 
|  | 2134 | # ifdef fileno | 
|  | 2135 | #  undef fileno | 
|  | 2136 | #  define fileno(a) (int)_fileno(a) | 
|  | 2137 | # endif | 
|  | 2138 |  | 
|  | 2139 | # include <windows.h> | 
|  | 2140 | # include <tchar.h> | 
|  | 2141 |  | 
|  | 2142 | static int WIN32_rename(const char *from, const char *to) | 
|  | 2143 | { | 
|  | 2144 | TCHAR *tfrom = NULL, *tto; | 
|  | 2145 | DWORD err; | 
|  | 2146 | int ret = 0; | 
|  | 2147 |  | 
|  | 2148 | if (sizeof(TCHAR) == 1) { | 
|  | 2149 | tfrom = (TCHAR *)from; | 
|  | 2150 | tto = (TCHAR *)to; | 
|  | 2151 | } else {                    /* UNICODE path */ | 
|  | 2152 |  | 
|  | 2153 | size_t i, flen = strlen(from) + 1, tlen = strlen(to) + 1; | 
|  | 2154 | tfrom = malloc(sizeof(*tfrom) * (flen + tlen)); | 
|  | 2155 | if (tfrom == NULL) | 
|  | 2156 | goto err; | 
|  | 2157 | tto = tfrom + flen; | 
|  | 2158 | # if !defined(_WIN32_WCE) || _WIN32_WCE>=101 | 
|  | 2159 | if (!MultiByteToWideChar(CP_ACP, 0, from, flen, (WCHAR *)tfrom, flen)) | 
|  | 2160 | # endif | 
|  | 2161 | for (i = 0; i < flen; i++) | 
|  | 2162 | tfrom[i] = (TCHAR)from[i]; | 
|  | 2163 | # if !defined(_WIN32_WCE) || _WIN32_WCE>=101 | 
|  | 2164 | if (!MultiByteToWideChar(CP_ACP, 0, to, tlen, (WCHAR *)tto, tlen)) | 
|  | 2165 | # endif | 
|  | 2166 | for (i = 0; i < tlen; i++) | 
|  | 2167 | tto[i] = (TCHAR)to[i]; | 
|  | 2168 | } | 
|  | 2169 |  | 
|  | 2170 | if (MoveFile(tfrom, tto)) | 
|  | 2171 | goto ok; | 
|  | 2172 | err = GetLastError(); | 
|  | 2173 | if (err == ERROR_ALREADY_EXISTS || err == ERROR_FILE_EXISTS) { | 
|  | 2174 | if (DeleteFile(tto) && MoveFile(tfrom, tto)) | 
|  | 2175 | goto ok; | 
|  | 2176 | err = GetLastError(); | 
|  | 2177 | } | 
|  | 2178 | if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) | 
|  | 2179 | errno = ENOENT; | 
|  | 2180 | else if (err == ERROR_ACCESS_DENIED) | 
|  | 2181 | errno = EACCES; | 
|  | 2182 | else | 
|  | 2183 | errno = EINVAL;         /* we could map more codes... */ | 
|  | 2184 | err: | 
|  | 2185 | ret = -1; | 
|  | 2186 | ok: | 
|  | 2187 | if (tfrom != NULL && tfrom != (TCHAR *)from) | 
|  | 2188 | free(tfrom); | 
|  | 2189 | return ret; | 
|  | 2190 | } | 
|  | 2191 | #endif | 
|  | 2192 |  | 
|  | 2193 | /* app_tminterval section */ | 
|  | 2194 | #if defined(_WIN32) | 
|  | 2195 | double app_tminterval(int stop, int usertime) | 
|  | 2196 | { | 
|  | 2197 | FILETIME now; | 
|  | 2198 | double ret = 0; | 
|  | 2199 | static ULARGE_INTEGER tmstart; | 
|  | 2200 | static int warning = 1; | 
|  | 2201 | # ifdef _WIN32_WINNT | 
|  | 2202 | static HANDLE proc = NULL; | 
|  | 2203 |  | 
|  | 2204 | if (proc == NULL) { | 
|  | 2205 | if (check_winnt()) | 
|  | 2206 | proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, | 
|  | 2207 | GetCurrentProcessId()); | 
|  | 2208 | if (proc == NULL) | 
|  | 2209 | proc = (HANDLE) - 1; | 
|  | 2210 | } | 
|  | 2211 |  | 
|  | 2212 | if (usertime && proc != (HANDLE) - 1) { | 
|  | 2213 | FILETIME junk; | 
|  | 2214 | GetProcessTimes(proc, &junk, &junk, &junk, &now); | 
|  | 2215 | } else | 
|  | 2216 | # endif | 
|  | 2217 | { | 
|  | 2218 | SYSTEMTIME systime; | 
|  | 2219 |  | 
|  | 2220 | if (usertime && warning) { | 
|  | 2221 | BIO_printf(bio_err, "To get meaningful results, run " | 
|  | 2222 | "this program on idle system.\n"); | 
|  | 2223 | warning = 0; | 
|  | 2224 | } | 
|  | 2225 | GetSystemTime(&systime); | 
|  | 2226 | SystemTimeToFileTime(&systime, &now); | 
|  | 2227 | } | 
|  | 2228 |  | 
|  | 2229 | if (stop == TM_START) { | 
|  | 2230 | tmstart.u.LowPart = now.dwLowDateTime; | 
|  | 2231 | tmstart.u.HighPart = now.dwHighDateTime; | 
|  | 2232 | } else { | 
|  | 2233 | ULARGE_INTEGER tmstop; | 
|  | 2234 |  | 
|  | 2235 | tmstop.u.LowPart = now.dwLowDateTime; | 
|  | 2236 | tmstop.u.HighPart = now.dwHighDateTime; | 
|  | 2237 |  | 
|  | 2238 | ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart) * 1e-7; | 
|  | 2239 | } | 
|  | 2240 |  | 
|  | 2241 | return ret; | 
|  | 2242 | } | 
|  | 2243 | #elif defined(OPENSSL_SYS_VXWORKS) | 
|  | 2244 | # include <time.h> | 
|  | 2245 |  | 
|  | 2246 | double app_tminterval(int stop, int usertime) | 
|  | 2247 | { | 
|  | 2248 | double ret = 0; | 
|  | 2249 | # ifdef CLOCK_REALTIME | 
|  | 2250 | static struct timespec tmstart; | 
|  | 2251 | struct timespec now; | 
|  | 2252 | # else | 
|  | 2253 | static unsigned long tmstart; | 
|  | 2254 | unsigned long now; | 
|  | 2255 | # endif | 
|  | 2256 | static int warning = 1; | 
|  | 2257 |  | 
|  | 2258 | if (usertime && warning) { | 
|  | 2259 | BIO_printf(bio_err, "To get meaningful results, run " | 
|  | 2260 | "this program on idle system.\n"); | 
|  | 2261 | warning = 0; | 
|  | 2262 | } | 
|  | 2263 | # ifdef CLOCK_REALTIME | 
|  | 2264 | clock_gettime(CLOCK_REALTIME, &now); | 
|  | 2265 | if (stop == TM_START) | 
|  | 2266 | tmstart = now; | 
|  | 2267 | else | 
|  | 2268 | ret = ((now.tv_sec + now.tv_nsec * 1e-9) | 
|  | 2269 | - (tmstart.tv_sec + tmstart.tv_nsec * 1e-9)); | 
|  | 2270 | # else | 
|  | 2271 | now = tickGet(); | 
|  | 2272 | if (stop == TM_START) | 
|  | 2273 | tmstart = now; | 
|  | 2274 | else | 
|  | 2275 | ret = (now - tmstart) / (double)sysClkRateGet(); | 
|  | 2276 | # endif | 
|  | 2277 | return ret; | 
|  | 2278 | } | 
|  | 2279 |  | 
|  | 2280 | #elif defined(OPENSSL_SYSTEM_VMS) | 
|  | 2281 | # include <time.h> | 
|  | 2282 | # include <times.h> | 
|  | 2283 |  | 
|  | 2284 | double app_tminterval(int stop, int usertime) | 
|  | 2285 | { | 
|  | 2286 | static clock_t tmstart; | 
|  | 2287 | double ret = 0; | 
|  | 2288 | clock_t now; | 
|  | 2289 | # ifdef __TMS | 
|  | 2290 | struct tms rus; | 
|  | 2291 |  | 
|  | 2292 | now = times(&rus); | 
|  | 2293 | if (usertime) | 
|  | 2294 | now = rus.tms_utime; | 
|  | 2295 | # else | 
|  | 2296 | if (usertime) | 
|  | 2297 | now = clock();          /* sum of user and kernel times */ | 
|  | 2298 | else { | 
|  | 2299 | struct timeval tv; | 
|  | 2300 | gettimeofday(&tv, NULL); | 
|  | 2301 | now = (clock_t)((unsigned long long)tv.tv_sec * CLK_TCK + | 
|  | 2302 | (unsigned long long)tv.tv_usec * (1000000 / CLK_TCK) | 
|  | 2303 | ); | 
|  | 2304 | } | 
|  | 2305 | # endif | 
|  | 2306 | if (stop == TM_START) | 
|  | 2307 | tmstart = now; | 
|  | 2308 | else | 
|  | 2309 | ret = (now - tmstart) / (double)(CLK_TCK); | 
|  | 2310 |  | 
|  | 2311 | return ret; | 
|  | 2312 | } | 
|  | 2313 |  | 
|  | 2314 | #elif defined(_SC_CLK_TCK)      /* by means of unistd.h */ | 
|  | 2315 | # include <sys/times.h> | 
|  | 2316 |  | 
|  | 2317 | double app_tminterval(int stop, int usertime) | 
|  | 2318 | { | 
|  | 2319 | double ret = 0; | 
|  | 2320 | struct tms rus; | 
|  | 2321 | clock_t now = times(&rus); | 
|  | 2322 | static clock_t tmstart; | 
|  | 2323 |  | 
|  | 2324 | if (usertime) | 
|  | 2325 | now = rus.tms_utime; | 
|  | 2326 |  | 
|  | 2327 | if (stop == TM_START) { | 
|  | 2328 | tmstart = now; | 
|  | 2329 | } else { | 
|  | 2330 | long int tck = sysconf(_SC_CLK_TCK); | 
|  | 2331 | ret = (now - tmstart) / (double)tck; | 
|  | 2332 | } | 
|  | 2333 |  | 
|  | 2334 | return ret; | 
|  | 2335 | } | 
|  | 2336 |  | 
|  | 2337 | #else | 
|  | 2338 | # include <sys/time.h> | 
|  | 2339 | # include <sys/resource.h> | 
|  | 2340 |  | 
|  | 2341 | double app_tminterval(int stop, int usertime) | 
|  | 2342 | { | 
|  | 2343 | double ret = 0; | 
|  | 2344 | struct rusage rus; | 
|  | 2345 | struct timeval now; | 
|  | 2346 | static struct timeval tmstart; | 
|  | 2347 |  | 
|  | 2348 | if (usertime) | 
|  | 2349 | getrusage(RUSAGE_SELF, &rus), now = rus.ru_utime; | 
|  | 2350 | else | 
|  | 2351 | gettimeofday(&now, NULL); | 
|  | 2352 |  | 
|  | 2353 | if (stop == TM_START) | 
|  | 2354 | tmstart = now; | 
|  | 2355 | else | 
|  | 2356 | ret = ((now.tv_sec + now.tv_usec * 1e-6) | 
|  | 2357 | - (tmstart.tv_sec + tmstart.tv_usec * 1e-6)); | 
|  | 2358 |  | 
|  | 2359 | return ret; | 
|  | 2360 | } | 
|  | 2361 | #endif | 
|  | 2362 |  | 
|  | 2363 | int app_access(const char* name, int flag) | 
|  | 2364 | { | 
|  | 2365 | #ifdef _WIN32 | 
|  | 2366 | return _access(name, flag); | 
|  | 2367 | #else | 
|  | 2368 | return access(name, flag); | 
|  | 2369 | #endif | 
|  | 2370 | } | 
|  | 2371 |  | 
|  | 2372 | /* app_isdir section */ | 
|  | 2373 | #ifdef _WIN32 | 
|  | 2374 | int app_isdir(const char *name) | 
|  | 2375 | { | 
|  | 2376 | DWORD attr; | 
|  | 2377 | # if defined(UNICODE) || defined(_UNICODE) | 
|  | 2378 | size_t i, len_0 = strlen(name) + 1; | 
|  | 2379 | WCHAR tempname[MAX_PATH]; | 
|  | 2380 |  | 
|  | 2381 | if (len_0 > MAX_PATH) | 
|  | 2382 | return -1; | 
|  | 2383 |  | 
|  | 2384 | #  if !defined(_WIN32_WCE) || _WIN32_WCE>=101 | 
|  | 2385 | if (!MultiByteToWideChar(CP_ACP, 0, name, len_0, tempname, MAX_PATH)) | 
|  | 2386 | #  endif | 
|  | 2387 | for (i = 0; i < len_0; i++) | 
|  | 2388 | tempname[i] = (WCHAR)name[i]; | 
|  | 2389 |  | 
|  | 2390 | attr = GetFileAttributes(tempname); | 
|  | 2391 | # else | 
|  | 2392 | attr = GetFileAttributes(name); | 
|  | 2393 | # endif | 
|  | 2394 | if (attr == INVALID_FILE_ATTRIBUTES) | 
|  | 2395 | return -1; | 
|  | 2396 | return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0); | 
|  | 2397 | } | 
|  | 2398 | #else | 
|  | 2399 | # include <sys/stat.h> | 
|  | 2400 | # ifndef S_ISDIR | 
|  | 2401 | #  if defined(_S_IFMT) && defined(_S_IFDIR) | 
|  | 2402 | #   define S_ISDIR(a)   (((a) & _S_IFMT) == _S_IFDIR) | 
|  | 2403 | #  else | 
|  | 2404 | #   define S_ISDIR(a)   (((a) & S_IFMT) == S_IFDIR) | 
|  | 2405 | #  endif | 
|  | 2406 | # endif | 
|  | 2407 |  | 
|  | 2408 | int app_isdir(const char *name) | 
|  | 2409 | { | 
|  | 2410 | # if defined(S_ISDIR) | 
|  | 2411 | struct stat st; | 
|  | 2412 |  | 
|  | 2413 | if (stat(name, &st) == 0) | 
|  | 2414 | return S_ISDIR(st.st_mode); | 
|  | 2415 | else | 
|  | 2416 | return -1; | 
|  | 2417 | # else | 
|  | 2418 | return -1; | 
|  | 2419 | # endif | 
|  | 2420 | } | 
|  | 2421 | #endif | 
|  | 2422 |  | 
|  | 2423 | /* raw_read|write section */ | 
|  | 2424 | #if defined(__VMS) | 
|  | 2425 | # include "vms_term_sock.h" | 
|  | 2426 | static int stdin_sock = -1; | 
|  | 2427 |  | 
|  | 2428 | static void close_stdin_sock(void) | 
|  | 2429 | { | 
|  | 2430 | TerminalSocket (TERM_SOCK_DELETE, &stdin_sock); | 
|  | 2431 | } | 
|  | 2432 |  | 
|  | 2433 | int fileno_stdin(void) | 
|  | 2434 | { | 
|  | 2435 | if (stdin_sock == -1) { | 
|  | 2436 | TerminalSocket(TERM_SOCK_CREATE, &stdin_sock); | 
|  | 2437 | atexit(close_stdin_sock); | 
|  | 2438 | } | 
|  | 2439 |  | 
|  | 2440 | return stdin_sock; | 
|  | 2441 | } | 
|  | 2442 | #else | 
|  | 2443 | int fileno_stdin(void) | 
|  | 2444 | { | 
|  | 2445 | return fileno(stdin); | 
|  | 2446 | } | 
|  | 2447 | #endif | 
|  | 2448 |  | 
|  | 2449 | int fileno_stdout(void) | 
|  | 2450 | { | 
|  | 2451 | return fileno(stdout); | 
|  | 2452 | } | 
|  | 2453 |  | 
|  | 2454 | #if defined(_WIN32) && defined(STD_INPUT_HANDLE) | 
|  | 2455 | int raw_read_stdin(void *buf, int siz) | 
|  | 2456 | { | 
|  | 2457 | DWORD n; | 
|  | 2458 | if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, siz, &n, NULL)) | 
|  | 2459 | return n; | 
|  | 2460 | else | 
|  | 2461 | return -1; | 
|  | 2462 | } | 
|  | 2463 | #elif defined(__VMS) | 
|  | 2464 | # include <sys/socket.h> | 
|  | 2465 |  | 
|  | 2466 | int raw_read_stdin(void *buf, int siz) | 
|  | 2467 | { | 
|  | 2468 | return recv(fileno_stdin(), buf, siz, 0); | 
|  | 2469 | } | 
|  | 2470 | #else | 
|  | 2471 | int raw_read_stdin(void *buf, int siz) | 
|  | 2472 | { | 
|  | 2473 | return read(fileno_stdin(), buf, siz); | 
|  | 2474 | } | 
|  | 2475 | #endif | 
|  | 2476 |  | 
|  | 2477 | #if defined(_WIN32) && defined(STD_OUTPUT_HANDLE) | 
|  | 2478 | int raw_write_stdout(const void *buf, int siz) | 
|  | 2479 | { | 
|  | 2480 | DWORD n; | 
|  | 2481 | if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, siz, &n, NULL)) | 
|  | 2482 | return n; | 
|  | 2483 | else | 
|  | 2484 | return -1; | 
|  | 2485 | } | 
|  | 2486 | #else | 
|  | 2487 | int raw_write_stdout(const void *buf, int siz) | 
|  | 2488 | { | 
|  | 2489 | return write(fileno_stdout(), buf, siz); | 
|  | 2490 | } | 
|  | 2491 | #endif | 
|  | 2492 |  | 
|  | 2493 | /* | 
|  | 2494 | * Centralized handling if input and output files with format specification | 
|  | 2495 | * The format is meant to show what the input and output is supposed to be, | 
|  | 2496 | * and is therefore a show of intent more than anything else.  However, it | 
|  | 2497 | * does impact behavior on some platform, such as differentiating between | 
|  | 2498 | * text and binary input/output on non-Unix platforms | 
|  | 2499 | */ | 
|  | 2500 | static int istext(int format) | 
|  | 2501 | { | 
|  | 2502 | return (format & B_FORMAT_TEXT) == B_FORMAT_TEXT; | 
|  | 2503 | } | 
|  | 2504 |  | 
|  | 2505 | BIO *dup_bio_in(int format) | 
|  | 2506 | { | 
|  | 2507 | return BIO_new_fp(stdin, | 
|  | 2508 | BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); | 
|  | 2509 | } | 
|  | 2510 |  | 
|  | 2511 | static BIO_METHOD *prefix_method = NULL; | 
|  | 2512 |  | 
|  | 2513 | BIO *dup_bio_out(int format) | 
|  | 2514 | { | 
|  | 2515 | BIO *b = BIO_new_fp(stdout, | 
|  | 2516 | BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); | 
|  | 2517 | void *prefix = NULL; | 
|  | 2518 |  | 
|  | 2519 | #ifdef OPENSSL_SYS_VMS | 
|  | 2520 | if (istext(format)) | 
|  | 2521 | b = BIO_push(BIO_new(BIO_f_linebuffer()), b); | 
|  | 2522 | #endif | 
|  | 2523 |  | 
|  | 2524 | if (istext(format) && (prefix = getenv("HARNESS_OSSL_PREFIX")) != NULL) { | 
|  | 2525 | if (prefix_method == NULL) | 
|  | 2526 | prefix_method = apps_bf_prefix(); | 
|  | 2527 | b = BIO_push(BIO_new(prefix_method), b); | 
|  | 2528 | BIO_ctrl(b, PREFIX_CTRL_SET_PREFIX, 0, prefix); | 
|  | 2529 | } | 
|  | 2530 |  | 
|  | 2531 | return b; | 
|  | 2532 | } | 
|  | 2533 |  | 
|  | 2534 | BIO *dup_bio_err(int format) | 
|  | 2535 | { | 
|  | 2536 | BIO *b = BIO_new_fp(stderr, | 
|  | 2537 | BIO_NOCLOSE | (istext(format) ? BIO_FP_TEXT : 0)); | 
|  | 2538 | #ifdef OPENSSL_SYS_VMS | 
|  | 2539 | if (istext(format)) | 
|  | 2540 | b = BIO_push(BIO_new(BIO_f_linebuffer()), b); | 
|  | 2541 | #endif | 
|  | 2542 | return b; | 
|  | 2543 | } | 
|  | 2544 |  | 
|  | 2545 | void destroy_prefix_method(void) | 
|  | 2546 | { | 
|  | 2547 | BIO_meth_free(prefix_method); | 
|  | 2548 | prefix_method = NULL; | 
|  | 2549 | } | 
|  | 2550 |  | 
|  | 2551 | void unbuffer(FILE *fp) | 
|  | 2552 | { | 
|  | 2553 | /* | 
|  | 2554 | * On VMS, setbuf() will only take 32-bit pointers, and a compilation | 
|  | 2555 | * with /POINTER_SIZE=64 will give off a MAYLOSEDATA2 warning here. | 
|  | 2556 | * However, we trust that the C RTL will never give us a FILE pointer | 
|  | 2557 | * above the first 4 GB of memory, so we simply turn off the warning | 
|  | 2558 | * temporarily. | 
|  | 2559 | */ | 
|  | 2560 | #if defined(OPENSSL_SYS_VMS) && defined(__DECC) | 
|  | 2561 | # pragma environment save | 
|  | 2562 | # pragma message disable maylosedata2 | 
|  | 2563 | #endif | 
|  | 2564 | setbuf(fp, NULL); | 
|  | 2565 | #if defined(OPENSSL_SYS_VMS) && defined(__DECC) | 
|  | 2566 | # pragma environment restore | 
|  | 2567 | #endif | 
|  | 2568 | } | 
|  | 2569 |  | 
|  | 2570 | static const char *modestr(char mode, int format) | 
|  | 2571 | { | 
|  | 2572 | OPENSSL_assert(mode == 'a' || mode == 'r' || mode == 'w'); | 
|  | 2573 |  | 
|  | 2574 | switch (mode) { | 
|  | 2575 | case 'a': | 
|  | 2576 | return istext(format) ? "a" : "ab"; | 
|  | 2577 | case 'r': | 
|  | 2578 | return istext(format) ? "r" : "rb"; | 
|  | 2579 | case 'w': | 
|  | 2580 | return istext(format) ? "w" : "wb"; | 
|  | 2581 | } | 
|  | 2582 | /* The assert above should make sure we never reach this point */ | 
|  | 2583 | return NULL; | 
|  | 2584 | } | 
|  | 2585 |  | 
|  | 2586 | static const char *modeverb(char mode) | 
|  | 2587 | { | 
|  | 2588 | switch (mode) { | 
|  | 2589 | case 'a': | 
|  | 2590 | return "appending"; | 
|  | 2591 | case 'r': | 
|  | 2592 | return "reading"; | 
|  | 2593 | case 'w': | 
|  | 2594 | return "writing"; | 
|  | 2595 | } | 
|  | 2596 | return "(doing something)"; | 
|  | 2597 | } | 
|  | 2598 |  | 
|  | 2599 | /* | 
|  | 2600 | * Open a file for writing, owner-read-only. | 
|  | 2601 | */ | 
|  | 2602 | BIO *bio_open_owner(const char *filename, int format, int private) | 
|  | 2603 | { | 
|  | 2604 | FILE *fp = NULL; | 
|  | 2605 | BIO *b = NULL; | 
|  | 2606 | int fd = -1, bflags, mode, textmode; | 
|  | 2607 |  | 
|  | 2608 | if (!private || filename == NULL || strcmp(filename, "-") == 0) | 
|  | 2609 | return bio_open_default(filename, 'w', format); | 
|  | 2610 |  | 
|  | 2611 | mode = O_WRONLY; | 
|  | 2612 | #ifdef O_CREAT | 
|  | 2613 | mode |= O_CREAT; | 
|  | 2614 | #endif | 
|  | 2615 | #ifdef O_TRUNC | 
|  | 2616 | mode |= O_TRUNC; | 
|  | 2617 | #endif | 
|  | 2618 | textmode = istext(format); | 
|  | 2619 | if (!textmode) { | 
|  | 2620 | #ifdef O_BINARY | 
|  | 2621 | mode |= O_BINARY; | 
|  | 2622 | #elif defined(_O_BINARY) | 
|  | 2623 | mode |= _O_BINARY; | 
|  | 2624 | #endif | 
|  | 2625 | } | 
|  | 2626 |  | 
|  | 2627 | #ifdef OPENSSL_SYS_VMS | 
|  | 2628 | /* VMS doesn't have O_BINARY, it just doesn't make sense.  But, | 
|  | 2629 | * it still needs to know that we're going binary, or fdopen() | 
|  | 2630 | * will fail with "invalid argument"...  so we tell VMS what the | 
|  | 2631 | * context is. | 
|  | 2632 | */ | 
|  | 2633 | if (!textmode) | 
|  | 2634 | fd = open(filename, mode, 0600, "ctx=bin"); | 
|  | 2635 | else | 
|  | 2636 | #endif | 
|  | 2637 | fd = open(filename, mode, 0600); | 
|  | 2638 | if (fd < 0) | 
|  | 2639 | goto err; | 
|  | 2640 | fp = fdopen(fd, modestr('w', format)); | 
|  | 2641 | if (fp == NULL) | 
|  | 2642 | goto err; | 
|  | 2643 | bflags = BIO_CLOSE; | 
|  | 2644 | if (textmode) | 
|  | 2645 | bflags |= BIO_FP_TEXT; | 
|  | 2646 | b = BIO_new_fp(fp, bflags); | 
|  | 2647 | if (b) | 
|  | 2648 | return b; | 
|  | 2649 |  | 
|  | 2650 | err: | 
|  | 2651 | BIO_printf(bio_err, "%s: Can't open \"%s\" for writing, %s\n", | 
|  | 2652 | opt_getprog(), filename, strerror(errno)); | 
|  | 2653 | ERR_print_errors(bio_err); | 
|  | 2654 | /* If we have fp, then fdopen took over fd, so don't close both. */ | 
|  | 2655 | if (fp) | 
|  | 2656 | fclose(fp); | 
|  | 2657 | else if (fd >= 0) | 
|  | 2658 | close(fd); | 
|  | 2659 | return NULL; | 
|  | 2660 | } | 
|  | 2661 |  | 
|  | 2662 | static BIO *bio_open_default_(const char *filename, char mode, int format, | 
|  | 2663 | int quiet) | 
|  | 2664 | { | 
|  | 2665 | BIO *ret; | 
|  | 2666 |  | 
|  | 2667 | if (filename == NULL || strcmp(filename, "-") == 0) { | 
|  | 2668 | ret = mode == 'r' ? dup_bio_in(format) : dup_bio_out(format); | 
|  | 2669 | if (quiet) { | 
|  | 2670 | ERR_clear_error(); | 
|  | 2671 | return ret; | 
|  | 2672 | } | 
|  | 2673 | if (ret != NULL) | 
|  | 2674 | return ret; | 
|  | 2675 | BIO_printf(bio_err, | 
|  | 2676 | "Can't open %s, %s\n", | 
|  | 2677 | mode == 'r' ? "stdin" : "stdout", strerror(errno)); | 
|  | 2678 | } else { | 
|  | 2679 | ret = BIO_new_file(filename, modestr(mode, format)); | 
|  | 2680 | if (quiet) { | 
|  | 2681 | ERR_clear_error(); | 
|  | 2682 | return ret; | 
|  | 2683 | } | 
|  | 2684 | if (ret != NULL) | 
|  | 2685 | return ret; | 
|  | 2686 | BIO_printf(bio_err, | 
|  | 2687 | "Can't open %s for %s, %s\n", | 
|  | 2688 | filename, modeverb(mode), strerror(errno)); | 
|  | 2689 | } | 
|  | 2690 | ERR_print_errors(bio_err); | 
|  | 2691 | return NULL; | 
|  | 2692 | } | 
|  | 2693 |  | 
|  | 2694 | BIO *bio_open_default(const char *filename, char mode, int format) | 
|  | 2695 | { | 
|  | 2696 | return bio_open_default_(filename, mode, format, 0); | 
|  | 2697 | } | 
|  | 2698 |  | 
|  | 2699 | BIO *bio_open_default_quiet(const char *filename, char mode, int format) | 
|  | 2700 | { | 
|  | 2701 | return bio_open_default_(filename, mode, format, 1); | 
|  | 2702 | } | 
|  | 2703 |  | 
|  | 2704 | void wait_for_async(SSL *s) | 
|  | 2705 | { | 
|  | 2706 | /* On Windows select only works for sockets, so we simply don't wait  */ | 
|  | 2707 | #ifndef OPENSSL_SYS_WINDOWS | 
|  | 2708 | int width = 0; | 
|  | 2709 | fd_set asyncfds; | 
|  | 2710 | OSSL_ASYNC_FD *fds; | 
|  | 2711 | size_t numfds; | 
|  | 2712 | size_t i; | 
|  | 2713 |  | 
|  | 2714 | if (!SSL_get_all_async_fds(s, NULL, &numfds)) | 
|  | 2715 | return; | 
|  | 2716 | if (numfds == 0) | 
|  | 2717 | return; | 
|  | 2718 | fds = app_malloc(sizeof(OSSL_ASYNC_FD) * numfds, "allocate async fds"); | 
|  | 2719 | if (!SSL_get_all_async_fds(s, fds, &numfds)) { | 
|  | 2720 | OPENSSL_free(fds); | 
|  | 2721 | return; | 
|  | 2722 | } | 
|  | 2723 |  | 
|  | 2724 | FD_ZERO(&asyncfds); | 
|  | 2725 | for (i = 0; i < numfds; i++) { | 
|  | 2726 | if (width <= (int)fds[i]) | 
|  | 2727 | width = (int)fds[i] + 1; | 
|  | 2728 | openssl_fdset((int)fds[i], &asyncfds); | 
|  | 2729 | } | 
|  | 2730 | select(width, (void *)&asyncfds, NULL, NULL, NULL); | 
|  | 2731 | OPENSSL_free(fds); | 
|  | 2732 | #endif | 
|  | 2733 | } | 
|  | 2734 |  | 
|  | 2735 | /* if OPENSSL_SYS_WINDOWS is defined then so is OPENSSL_SYS_MSDOS */ | 
|  | 2736 | #if defined(OPENSSL_SYS_MSDOS) | 
|  | 2737 | int has_stdin_waiting(void) | 
|  | 2738 | { | 
|  | 2739 | # if defined(OPENSSL_SYS_WINDOWS) | 
|  | 2740 | HANDLE inhand = GetStdHandle(STD_INPUT_HANDLE); | 
|  | 2741 | DWORD events = 0; | 
|  | 2742 | INPUT_RECORD inputrec; | 
|  | 2743 | DWORD insize = 1; | 
|  | 2744 | BOOL peeked; | 
|  | 2745 |  | 
|  | 2746 | if (inhand == INVALID_HANDLE_VALUE) { | 
|  | 2747 | return 0; | 
|  | 2748 | } | 
|  | 2749 |  | 
|  | 2750 | peeked = PeekConsoleInput(inhand, &inputrec, insize, &events); | 
|  | 2751 | if (!peeked) { | 
|  | 2752 | /* Probably redirected input? _kbhit() does not work in this case */ | 
|  | 2753 | if (!feof(stdin)) { | 
|  | 2754 | return 1; | 
|  | 2755 | } | 
|  | 2756 | return 0; | 
|  | 2757 | } | 
|  | 2758 | # endif | 
|  | 2759 | return _kbhit(); | 
|  | 2760 | } | 
|  | 2761 | #endif | 
|  | 2762 |  | 
|  | 2763 | /* Corrupt a signature by modifying final byte */ | 
|  | 2764 | void corrupt_signature(const ASN1_STRING *signature) | 
|  | 2765 | { | 
|  | 2766 | unsigned char *s = signature->data; | 
|  | 2767 | s[signature->length - 1] ^= 0x1; | 
|  | 2768 | } | 
|  | 2769 |  | 
|  | 2770 | int set_cert_times(X509 *x, const char *startdate, const char *enddate, | 
|  | 2771 | int days) | 
|  | 2772 | { | 
|  | 2773 | if (startdate == NULL || strcmp(startdate, "today") == 0) { | 
|  | 2774 | if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL) | 
|  | 2775 | return 0; | 
|  | 2776 | } else { | 
|  | 2777 | if (!ASN1_TIME_set_string_X509(X509_getm_notBefore(x), startdate)) | 
|  | 2778 | return 0; | 
|  | 2779 | } | 
|  | 2780 | if (enddate == NULL) { | 
|  | 2781 | if (X509_time_adj_ex(X509_getm_notAfter(x), days, 0, NULL) | 
|  | 2782 | == NULL) | 
|  | 2783 | return 0; | 
|  | 2784 | } else if (!ASN1_TIME_set_string_X509(X509_getm_notAfter(x), enddate)) { | 
|  | 2785 | return 0; | 
|  | 2786 | } | 
|  | 2787 | return 1; | 
|  | 2788 | } | 
|  | 2789 |  | 
|  | 2790 | void make_uppercase(char *string) | 
|  | 2791 | { | 
|  | 2792 | int i; | 
|  | 2793 |  | 
|  | 2794 | for (i = 0; string[i] != '\0'; i++) | 
|  | 2795 | string[i] = toupper((unsigned char)string[i]); | 
|  | 2796 | } |