1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: apps.c,v 1.62 2022/01/10 12:17:49 tb Exp $ */ 2f5b1c8a1SJohn Marino /* 3f5b1c8a1SJohn Marino * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 4f5b1c8a1SJohn Marino * 5f5b1c8a1SJohn Marino * Permission to use, copy, modify, and distribute this software for any 6f5b1c8a1SJohn Marino * purpose with or without fee is hereby granted, provided that the above 7f5b1c8a1SJohn Marino * copyright notice and this permission notice appear in all copies. 8f5b1c8a1SJohn Marino * 9f5b1c8a1SJohn Marino * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10f5b1c8a1SJohn Marino * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11f5b1c8a1SJohn Marino * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12f5b1c8a1SJohn Marino * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13f5b1c8a1SJohn Marino * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14f5b1c8a1SJohn Marino * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15f5b1c8a1SJohn Marino * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16f5b1c8a1SJohn Marino */ 17f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 18f5b1c8a1SJohn Marino * All rights reserved. 19f5b1c8a1SJohn Marino * 20f5b1c8a1SJohn Marino * This package is an SSL implementation written 21f5b1c8a1SJohn Marino * by Eric Young (eay@cryptsoft.com). 22f5b1c8a1SJohn Marino * The implementation was written so as to conform with Netscapes SSL. 23f5b1c8a1SJohn Marino * 24f5b1c8a1SJohn Marino * This library is free for commercial and non-commercial use as long as 25f5b1c8a1SJohn Marino * the following conditions are aheared to. The following conditions 26f5b1c8a1SJohn Marino * apply to all code found in this distribution, be it the RC4, RSA, 27f5b1c8a1SJohn Marino * lhash, DES, etc., code; not just the SSL code. The SSL documentation 28f5b1c8a1SJohn Marino * included with this distribution is covered by the same copyright terms 29f5b1c8a1SJohn Marino * except that the holder is Tim Hudson (tjh@cryptsoft.com). 30f5b1c8a1SJohn Marino * 31f5b1c8a1SJohn Marino * Copyright remains Eric Young's, and as such any Copyright notices in 32f5b1c8a1SJohn Marino * the code are not to be removed. 33f5b1c8a1SJohn Marino * If this package is used in a product, Eric Young should be given attribution 34f5b1c8a1SJohn Marino * as the author of the parts of the library used. 35f5b1c8a1SJohn Marino * This can be in the form of a textual message at program startup or 36f5b1c8a1SJohn Marino * in documentation (online or textual) provided with the package. 37f5b1c8a1SJohn Marino * 38f5b1c8a1SJohn Marino * Redistribution and use in source and binary forms, with or without 39f5b1c8a1SJohn Marino * modification, are permitted provided that the following conditions 40f5b1c8a1SJohn Marino * are met: 41f5b1c8a1SJohn Marino * 1. Redistributions of source code must retain the copyright 42f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer. 43f5b1c8a1SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright 44f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer in the 45f5b1c8a1SJohn Marino * documentation and/or other materials provided with the distribution. 46f5b1c8a1SJohn Marino * 3. All advertising materials mentioning features or use of this software 47f5b1c8a1SJohn Marino * must display the following acknowledgement: 48f5b1c8a1SJohn Marino * "This product includes cryptographic software written by 49f5b1c8a1SJohn Marino * Eric Young (eay@cryptsoft.com)" 50f5b1c8a1SJohn Marino * The word 'cryptographic' can be left out if the rouines from the library 51f5b1c8a1SJohn Marino * being used are not cryptographic related :-). 52f5b1c8a1SJohn Marino * 4. If you include any Windows specific code (or a derivative thereof) from 53f5b1c8a1SJohn Marino * the apps directory (application code) you must include an acknowledgement: 54f5b1c8a1SJohn Marino * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 55f5b1c8a1SJohn Marino * 56f5b1c8a1SJohn Marino * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 57f5b1c8a1SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 58f5b1c8a1SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 59f5b1c8a1SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 60f5b1c8a1SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 61f5b1c8a1SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 62f5b1c8a1SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 63f5b1c8a1SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 64f5b1c8a1SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 65f5b1c8a1SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 66f5b1c8a1SJohn Marino * SUCH DAMAGE. 67f5b1c8a1SJohn Marino * 68f5b1c8a1SJohn Marino * The licence and distribution terms for any publically available version or 69f5b1c8a1SJohn Marino * derivative of this code cannot be changed. i.e. this code cannot simply be 70f5b1c8a1SJohn Marino * copied and put under another distribution licence 71f5b1c8a1SJohn Marino * [including the GNU Public Licence.] 72f5b1c8a1SJohn Marino */ 73f5b1c8a1SJohn Marino /* ==================================================================== 74f5b1c8a1SJohn Marino * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. 75f5b1c8a1SJohn Marino * 76f5b1c8a1SJohn Marino * Redistribution and use in source and binary forms, with or without 77f5b1c8a1SJohn Marino * modification, are permitted provided that the following conditions 78f5b1c8a1SJohn Marino * are met: 79f5b1c8a1SJohn Marino * 80f5b1c8a1SJohn Marino * 1. Redistributions of source code must retain the above copyright 81f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer. 82f5b1c8a1SJohn Marino * 83f5b1c8a1SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright 84f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer in 85f5b1c8a1SJohn Marino * the documentation and/or other materials provided with the 86f5b1c8a1SJohn Marino * distribution. 87f5b1c8a1SJohn Marino * 88f5b1c8a1SJohn Marino * 3. All advertising materials mentioning features or use of this 89f5b1c8a1SJohn Marino * software must display the following acknowledgment: 90f5b1c8a1SJohn Marino * "This product includes software developed by the OpenSSL Project 91f5b1c8a1SJohn Marino * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 92f5b1c8a1SJohn Marino * 93f5b1c8a1SJohn Marino * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 94f5b1c8a1SJohn Marino * endorse or promote products derived from this software without 95f5b1c8a1SJohn Marino * prior written permission. For written permission, please contact 96f5b1c8a1SJohn Marino * openssl-core@openssl.org. 97f5b1c8a1SJohn Marino * 98f5b1c8a1SJohn Marino * 5. Products derived from this software may not be called "OpenSSL" 99f5b1c8a1SJohn Marino * nor may "OpenSSL" appear in their names without prior written 100f5b1c8a1SJohn Marino * permission of the OpenSSL Project. 101f5b1c8a1SJohn Marino * 102f5b1c8a1SJohn Marino * 6. Redistributions of any form whatsoever must retain the following 103f5b1c8a1SJohn Marino * acknowledgment: 104f5b1c8a1SJohn Marino * "This product includes software developed by the OpenSSL Project 105f5b1c8a1SJohn Marino * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 106f5b1c8a1SJohn Marino * 107f5b1c8a1SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 108f5b1c8a1SJohn Marino * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 109f5b1c8a1SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 110f5b1c8a1SJohn Marino * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 111f5b1c8a1SJohn Marino * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 112f5b1c8a1SJohn Marino * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 113f5b1c8a1SJohn Marino * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 114f5b1c8a1SJohn Marino * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 115f5b1c8a1SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 116f5b1c8a1SJohn Marino * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 117f5b1c8a1SJohn Marino * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 118f5b1c8a1SJohn Marino * OF THE POSSIBILITY OF SUCH DAMAGE. 119f5b1c8a1SJohn Marino * ==================================================================== 120f5b1c8a1SJohn Marino * 121f5b1c8a1SJohn Marino * This product includes cryptographic software written by Eric Young 122f5b1c8a1SJohn Marino * (eay@cryptsoft.com). This product includes software written by Tim 123f5b1c8a1SJohn Marino * Hudson (tjh@cryptsoft.com). 124f5b1c8a1SJohn Marino * 125f5b1c8a1SJohn Marino */ 126f5b1c8a1SJohn Marino 127f5b1c8a1SJohn Marino #include <sys/types.h> 128f5b1c8a1SJohn Marino #include <sys/stat.h> 129f5b1c8a1SJohn Marino 130f5b1c8a1SJohn Marino #include <ctype.h> 131f5b1c8a1SJohn Marino #include <errno.h> 132f5b1c8a1SJohn Marino #include <stdio.h> 133f5b1c8a1SJohn Marino #include <stdlib.h> 134f5b1c8a1SJohn Marino #include <limits.h> 135f5b1c8a1SJohn Marino #include <string.h> 136f5b1c8a1SJohn Marino #include <unistd.h> 137f5b1c8a1SJohn Marino 138f5b1c8a1SJohn Marino #include "apps.h" 139f5b1c8a1SJohn Marino 140f5b1c8a1SJohn Marino #include <openssl/bn.h> 141f5b1c8a1SJohn Marino #include <openssl/err.h> 142f5b1c8a1SJohn Marino #include <openssl/pem.h> 143f5b1c8a1SJohn Marino #include <openssl/pkcs12.h> 144*de0e0e4dSAntonio Huete Jimenez #include <openssl/rsa.h> 145f5b1c8a1SJohn Marino #include <openssl/safestack.h> 146*de0e0e4dSAntonio Huete Jimenez #include <openssl/ssl.h> 147f5b1c8a1SJohn Marino #include <openssl/x509.h> 148f5b1c8a1SJohn Marino #include <openssl/x509v3.h> 149f5b1c8a1SJohn Marino 150f5b1c8a1SJohn Marino typedef struct { 151f5b1c8a1SJohn Marino const char *name; 152f5b1c8a1SJohn Marino unsigned long flag; 153f5b1c8a1SJohn Marino unsigned long mask; 154f5b1c8a1SJohn Marino } NAME_EX_TBL; 155f5b1c8a1SJohn Marino 156f5b1c8a1SJohn Marino UI_METHOD *ui_method = NULL; 157f5b1c8a1SJohn Marino 158f5b1c8a1SJohn Marino static int set_table_opts(unsigned long *flags, const char *arg, 159f5b1c8a1SJohn Marino const NAME_EX_TBL *in_tbl); 160f5b1c8a1SJohn Marino static int set_multi_opts(unsigned long *flags, const char *arg, 161f5b1c8a1SJohn Marino const NAME_EX_TBL *in_tbl); 162f5b1c8a1SJohn Marino 163f5b1c8a1SJohn Marino int 164f5b1c8a1SJohn Marino str2fmt(char *s) 165f5b1c8a1SJohn Marino { 166f5b1c8a1SJohn Marino if (s == NULL) 167f5b1c8a1SJohn Marino return FORMAT_UNDEF; 168f5b1c8a1SJohn Marino if ((*s == 'D') || (*s == 'd')) 169f5b1c8a1SJohn Marino return (FORMAT_ASN1); 170f5b1c8a1SJohn Marino else if ((*s == 'T') || (*s == 't')) 171f5b1c8a1SJohn Marino return (FORMAT_TEXT); 172f5b1c8a1SJohn Marino else if ((*s == 'S') || (*s == 's')) 173f5b1c8a1SJohn Marino return (FORMAT_SMIME); 174f5b1c8a1SJohn Marino else if ((*s == 'M') || (*s == 'm')) 175f5b1c8a1SJohn Marino return (FORMAT_MSBLOB); 176f5b1c8a1SJohn Marino else if ((*s == '1') || 177f5b1c8a1SJohn Marino (strcmp(s, "PKCS12") == 0) || (strcmp(s, "pkcs12") == 0) || 178f5b1c8a1SJohn Marino (strcmp(s, "P12") == 0) || (strcmp(s, "p12") == 0)) 179f5b1c8a1SJohn Marino return (FORMAT_PKCS12); 180f5b1c8a1SJohn Marino else if ((*s == 'P') || (*s == 'p')) { 181f5b1c8a1SJohn Marino if (s[1] == 'V' || s[1] == 'v') 182f5b1c8a1SJohn Marino return FORMAT_PVK; 183f5b1c8a1SJohn Marino else 184f5b1c8a1SJohn Marino return (FORMAT_PEM); 185f5b1c8a1SJohn Marino } else 186f5b1c8a1SJohn Marino return (FORMAT_UNDEF); 187f5b1c8a1SJohn Marino } 188f5b1c8a1SJohn Marino 189f5b1c8a1SJohn Marino void 190f5b1c8a1SJohn Marino program_name(char *in, char *out, int size) 191f5b1c8a1SJohn Marino { 192f5b1c8a1SJohn Marino char *p; 193f5b1c8a1SJohn Marino 194f5b1c8a1SJohn Marino p = strrchr(in, '/'); 195f5b1c8a1SJohn Marino if (p != NULL) 196f5b1c8a1SJohn Marino p++; 197f5b1c8a1SJohn Marino else 198f5b1c8a1SJohn Marino p = in; 199f5b1c8a1SJohn Marino strlcpy(out, p, size); 200f5b1c8a1SJohn Marino } 201f5b1c8a1SJohn Marino 202f5b1c8a1SJohn Marino int 203f5b1c8a1SJohn Marino chopup_args(ARGS *arg, char *buf, int *argc, char **argv[]) 204f5b1c8a1SJohn Marino { 205f5b1c8a1SJohn Marino int num, i; 206f5b1c8a1SJohn Marino char *p; 207f5b1c8a1SJohn Marino 208f5b1c8a1SJohn Marino *argc = 0; 209f5b1c8a1SJohn Marino *argv = NULL; 210f5b1c8a1SJohn Marino 211f5b1c8a1SJohn Marino if (arg->count == 0) { 212f5b1c8a1SJohn Marino arg->count = 20; 213f5b1c8a1SJohn Marino arg->data = reallocarray(NULL, arg->count, sizeof(char *)); 214f5b1c8a1SJohn Marino if (arg->data == NULL) 215f5b1c8a1SJohn Marino return 0; 216f5b1c8a1SJohn Marino } 217f5b1c8a1SJohn Marino for (i = 0; i < arg->count; i++) 218f5b1c8a1SJohn Marino arg->data[i] = NULL; 219f5b1c8a1SJohn Marino 220f5b1c8a1SJohn Marino num = 0; 221f5b1c8a1SJohn Marino p = buf; 222f5b1c8a1SJohn Marino for (;;) { 223f5b1c8a1SJohn Marino /* first scan over white space */ 224f5b1c8a1SJohn Marino if (!*p) 225f5b1c8a1SJohn Marino break; 226f5b1c8a1SJohn Marino while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n'))) 227f5b1c8a1SJohn Marino p++; 228f5b1c8a1SJohn Marino if (!*p) 229f5b1c8a1SJohn Marino break; 230f5b1c8a1SJohn Marino 231f5b1c8a1SJohn Marino /* The start of something good :-) */ 232f5b1c8a1SJohn Marino if (num >= arg->count) { 233f5b1c8a1SJohn Marino char **tmp_p; 234f5b1c8a1SJohn Marino int tlen = arg->count + 20; 235f5b1c8a1SJohn Marino tmp_p = reallocarray(arg->data, tlen, sizeof(char *)); 236f5b1c8a1SJohn Marino if (tmp_p == NULL) 237f5b1c8a1SJohn Marino return 0; 238f5b1c8a1SJohn Marino arg->data = tmp_p; 239f5b1c8a1SJohn Marino arg->count = tlen; 240f5b1c8a1SJohn Marino /* initialize newly allocated data */ 241f5b1c8a1SJohn Marino for (i = num; i < arg->count; i++) 242f5b1c8a1SJohn Marino arg->data[i] = NULL; 243f5b1c8a1SJohn Marino } 244f5b1c8a1SJohn Marino arg->data[num++] = p; 245f5b1c8a1SJohn Marino 246f5b1c8a1SJohn Marino /* now look for the end of this */ 247f5b1c8a1SJohn Marino if ((*p == '\'') || (*p == '\"')) { /* scan for closing 248f5b1c8a1SJohn Marino * quote */ 249f5b1c8a1SJohn Marino i = *(p++); 250f5b1c8a1SJohn Marino arg->data[num - 1]++; /* jump over quote */ 251f5b1c8a1SJohn Marino while (*p && (*p != i)) 252f5b1c8a1SJohn Marino p++; 253f5b1c8a1SJohn Marino *p = '\0'; 254f5b1c8a1SJohn Marino } else { 255f5b1c8a1SJohn Marino while (*p && ((*p != ' ') && 256f5b1c8a1SJohn Marino (*p != '\t') && (*p != '\n'))) 257f5b1c8a1SJohn Marino p++; 258f5b1c8a1SJohn Marino 259f5b1c8a1SJohn Marino if (*p == '\0') 260f5b1c8a1SJohn Marino p--; 261f5b1c8a1SJohn Marino else 262f5b1c8a1SJohn Marino *p = '\0'; 263f5b1c8a1SJohn Marino } 264f5b1c8a1SJohn Marino p++; 265f5b1c8a1SJohn Marino } 266f5b1c8a1SJohn Marino *argc = num; 267f5b1c8a1SJohn Marino *argv = arg->data; 268f5b1c8a1SJohn Marino return (1); 269f5b1c8a1SJohn Marino } 270f5b1c8a1SJohn Marino 271f5b1c8a1SJohn Marino int 272f5b1c8a1SJohn Marino dump_cert_text(BIO *out, X509 *x) 273f5b1c8a1SJohn Marino { 274f5b1c8a1SJohn Marino char *p; 275f5b1c8a1SJohn Marino 276f5b1c8a1SJohn Marino p = X509_NAME_oneline(X509_get_subject_name(x), NULL, 0); 277f5b1c8a1SJohn Marino BIO_puts(out, "subject="); 278f5b1c8a1SJohn Marino BIO_puts(out, p); 279f5b1c8a1SJohn Marino free(p); 280f5b1c8a1SJohn Marino 281f5b1c8a1SJohn Marino p = X509_NAME_oneline(X509_get_issuer_name(x), NULL, 0); 282f5b1c8a1SJohn Marino BIO_puts(out, "\nissuer="); 283f5b1c8a1SJohn Marino BIO_puts(out, p); 284f5b1c8a1SJohn Marino BIO_puts(out, "\n"); 285f5b1c8a1SJohn Marino free(p); 286f5b1c8a1SJohn Marino 287f5b1c8a1SJohn Marino return 0; 288f5b1c8a1SJohn Marino } 289f5b1c8a1SJohn Marino 290f5b1c8a1SJohn Marino int 291f5b1c8a1SJohn Marino ui_open(UI *ui) 292f5b1c8a1SJohn Marino { 293f5b1c8a1SJohn Marino return UI_method_get_opener(UI_OpenSSL()) (ui); 294f5b1c8a1SJohn Marino } 295f5b1c8a1SJohn Marino 296f5b1c8a1SJohn Marino int 297f5b1c8a1SJohn Marino ui_read(UI *ui, UI_STRING *uis) 298f5b1c8a1SJohn Marino { 299f5b1c8a1SJohn Marino const char *password; 300f5b1c8a1SJohn Marino int string_type; 301f5b1c8a1SJohn Marino 302f5b1c8a1SJohn Marino if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD && 303f5b1c8a1SJohn Marino UI_get0_user_data(ui)) { 304f5b1c8a1SJohn Marino string_type = UI_get_string_type(uis); 305f5b1c8a1SJohn Marino if (string_type == UIT_PROMPT || string_type == UIT_VERIFY) { 306f5b1c8a1SJohn Marino password = 307f5b1c8a1SJohn Marino ((PW_CB_DATA *)UI_get0_user_data(ui))->password; 308f5b1c8a1SJohn Marino if (password && password[0] != '\0') { 309f5b1c8a1SJohn Marino UI_set_result(ui, uis, password); 310f5b1c8a1SJohn Marino return 1; 311f5b1c8a1SJohn Marino } 312f5b1c8a1SJohn Marino } 313f5b1c8a1SJohn Marino } 314f5b1c8a1SJohn Marino return UI_method_get_reader(UI_OpenSSL()) (ui, uis); 315f5b1c8a1SJohn Marino } 316f5b1c8a1SJohn Marino 317f5b1c8a1SJohn Marino int 318f5b1c8a1SJohn Marino ui_write(UI *ui, UI_STRING *uis) 319f5b1c8a1SJohn Marino { 320f5b1c8a1SJohn Marino const char *password; 321f5b1c8a1SJohn Marino int string_type; 322f5b1c8a1SJohn Marino 323f5b1c8a1SJohn Marino if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD && 324f5b1c8a1SJohn Marino UI_get0_user_data(ui)) { 325f5b1c8a1SJohn Marino string_type = UI_get_string_type(uis); 326f5b1c8a1SJohn Marino if (string_type == UIT_PROMPT || string_type == UIT_VERIFY) { 327f5b1c8a1SJohn Marino password = 328f5b1c8a1SJohn Marino ((PW_CB_DATA *)UI_get0_user_data(ui))->password; 329f5b1c8a1SJohn Marino if (password && password[0] != '\0') 330f5b1c8a1SJohn Marino return 1; 331f5b1c8a1SJohn Marino } 332f5b1c8a1SJohn Marino } 333f5b1c8a1SJohn Marino return UI_method_get_writer(UI_OpenSSL()) (ui, uis); 334f5b1c8a1SJohn Marino } 335f5b1c8a1SJohn Marino 336f5b1c8a1SJohn Marino int 337f5b1c8a1SJohn Marino ui_close(UI *ui) 338f5b1c8a1SJohn Marino { 339f5b1c8a1SJohn Marino return UI_method_get_closer(UI_OpenSSL()) (ui); 340f5b1c8a1SJohn Marino } 341f5b1c8a1SJohn Marino 342f5b1c8a1SJohn Marino int 343f5b1c8a1SJohn Marino password_callback(char *buf, int bufsiz, int verify, void *arg) 344f5b1c8a1SJohn Marino { 345f5b1c8a1SJohn Marino PW_CB_DATA *cb_tmp = arg; 346f5b1c8a1SJohn Marino UI *ui = NULL; 347f5b1c8a1SJohn Marino int res = 0; 348f5b1c8a1SJohn Marino const char *prompt_info = NULL; 349f5b1c8a1SJohn Marino const char *password = NULL; 350f5b1c8a1SJohn Marino PW_CB_DATA *cb_data = (PW_CB_DATA *) cb_tmp; 351f5b1c8a1SJohn Marino 352f5b1c8a1SJohn Marino if (cb_data) { 353f5b1c8a1SJohn Marino if (cb_data->password) 354f5b1c8a1SJohn Marino password = cb_data->password; 355f5b1c8a1SJohn Marino if (cb_data->prompt_info) 356f5b1c8a1SJohn Marino prompt_info = cb_data->prompt_info; 357f5b1c8a1SJohn Marino } 358f5b1c8a1SJohn Marino if (password) { 359f5b1c8a1SJohn Marino res = strlen(password); 360f5b1c8a1SJohn Marino if (res > bufsiz) 361f5b1c8a1SJohn Marino res = bufsiz; 362f5b1c8a1SJohn Marino memcpy(buf, password, res); 363f5b1c8a1SJohn Marino return res; 364f5b1c8a1SJohn Marino } 365f5b1c8a1SJohn Marino ui = UI_new_method(ui_method); 366f5b1c8a1SJohn Marino if (ui) { 367f5b1c8a1SJohn Marino int ok = 0; 368f5b1c8a1SJohn Marino char *buff = NULL; 369f5b1c8a1SJohn Marino int ui_flags = 0; 370f5b1c8a1SJohn Marino char *prompt = NULL; 371f5b1c8a1SJohn Marino 372f5b1c8a1SJohn Marino prompt = UI_construct_prompt(ui, "pass phrase", prompt_info); 373f5b1c8a1SJohn Marino 374f5b1c8a1SJohn Marino ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD; 375f5b1c8a1SJohn Marino UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); 376f5b1c8a1SJohn Marino 377f5b1c8a1SJohn Marino if (ok >= 0) 378f5b1c8a1SJohn Marino ok = UI_add_input_string(ui, prompt, ui_flags, buf, 379f5b1c8a1SJohn Marino PW_MIN_LENGTH, bufsiz - 1); 380f5b1c8a1SJohn Marino if (ok >= 0 && verify) { 381f5b1c8a1SJohn Marino buff = malloc(bufsiz); 382f5b1c8a1SJohn Marino ok = UI_add_verify_string(ui, prompt, ui_flags, buff, 383f5b1c8a1SJohn Marino PW_MIN_LENGTH, bufsiz - 1, buf); 384f5b1c8a1SJohn Marino } 385f5b1c8a1SJohn Marino if (ok >= 0) 386f5b1c8a1SJohn Marino do { 387f5b1c8a1SJohn Marino ok = UI_process(ui); 388f5b1c8a1SJohn Marino } while (ok < 0 && 389f5b1c8a1SJohn Marino UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); 390f5b1c8a1SJohn Marino 39172c33676SMaxim Ag freezero(buff, (unsigned int) bufsiz); 392f5b1c8a1SJohn Marino if (ok >= 0) 393f5b1c8a1SJohn Marino res = strlen(buf); 394f5b1c8a1SJohn Marino if (ok == -1) { 395f5b1c8a1SJohn Marino BIO_printf(bio_err, "User interface error\n"); 396f5b1c8a1SJohn Marino ERR_print_errors(bio_err); 397f5b1c8a1SJohn Marino explicit_bzero(buf, (unsigned int) bufsiz); 398f5b1c8a1SJohn Marino res = 0; 399f5b1c8a1SJohn Marino } 400f5b1c8a1SJohn Marino if (ok == -2) { 401f5b1c8a1SJohn Marino BIO_printf(bio_err, "aborted!\n"); 402f5b1c8a1SJohn Marino explicit_bzero(buf, (unsigned int) bufsiz); 403f5b1c8a1SJohn Marino res = 0; 404f5b1c8a1SJohn Marino } 405f5b1c8a1SJohn Marino UI_free(ui); 406f5b1c8a1SJohn Marino free(prompt); 407f5b1c8a1SJohn Marino } 408f5b1c8a1SJohn Marino return res; 409f5b1c8a1SJohn Marino } 410f5b1c8a1SJohn Marino 411f5b1c8a1SJohn Marino static char *app_get_pass(BIO *err, char *arg, int keepbio); 412f5b1c8a1SJohn Marino 413f5b1c8a1SJohn Marino int 414f5b1c8a1SJohn Marino app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2) 415f5b1c8a1SJohn Marino { 416f5b1c8a1SJohn Marino int same; 417f5b1c8a1SJohn Marino 418f5b1c8a1SJohn Marino if (!arg2 || !arg1 || strcmp(arg1, arg2)) 419f5b1c8a1SJohn Marino same = 0; 420f5b1c8a1SJohn Marino else 421f5b1c8a1SJohn Marino same = 1; 422f5b1c8a1SJohn Marino if (arg1) { 423f5b1c8a1SJohn Marino *pass1 = app_get_pass(err, arg1, same); 424f5b1c8a1SJohn Marino if (!*pass1) 425f5b1c8a1SJohn Marino return 0; 426f5b1c8a1SJohn Marino } else if (pass1) 427f5b1c8a1SJohn Marino *pass1 = NULL; 428f5b1c8a1SJohn Marino if (arg2) { 429f5b1c8a1SJohn Marino *pass2 = app_get_pass(err, arg2, same ? 2 : 0); 430f5b1c8a1SJohn Marino if (!*pass2) 431f5b1c8a1SJohn Marino return 0; 432f5b1c8a1SJohn Marino } else if (pass2) 433f5b1c8a1SJohn Marino *pass2 = NULL; 434f5b1c8a1SJohn Marino return 1; 435f5b1c8a1SJohn Marino } 436f5b1c8a1SJohn Marino 437f5b1c8a1SJohn Marino static char * 438f5b1c8a1SJohn Marino app_get_pass(BIO *err, char *arg, int keepbio) 439f5b1c8a1SJohn Marino { 440f5b1c8a1SJohn Marino char *tmp, tpass[APP_PASS_LEN]; 441f5b1c8a1SJohn Marino static BIO *pwdbio = NULL; 442f5b1c8a1SJohn Marino const char *errstr = NULL; 443f5b1c8a1SJohn Marino int i; 444f5b1c8a1SJohn Marino 445f5b1c8a1SJohn Marino if (!strncmp(arg, "pass:", 5)) 446f5b1c8a1SJohn Marino return strdup(arg + 5); 447f5b1c8a1SJohn Marino if (!strncmp(arg, "env:", 4)) { 448f5b1c8a1SJohn Marino tmp = getenv(arg + 4); 449f5b1c8a1SJohn Marino if (!tmp) { 450f5b1c8a1SJohn Marino BIO_printf(err, "Can't read environment variable %s\n", 451f5b1c8a1SJohn Marino arg + 4); 452f5b1c8a1SJohn Marino return NULL; 453f5b1c8a1SJohn Marino } 454f5b1c8a1SJohn Marino return strdup(tmp); 455f5b1c8a1SJohn Marino } 456f5b1c8a1SJohn Marino if (!keepbio || !pwdbio) { 457f5b1c8a1SJohn Marino if (!strncmp(arg, "file:", 5)) { 458f5b1c8a1SJohn Marino pwdbio = BIO_new_file(arg + 5, "r"); 459f5b1c8a1SJohn Marino if (!pwdbio) { 460f5b1c8a1SJohn Marino BIO_printf(err, "Can't open file %s\n", 461f5b1c8a1SJohn Marino arg + 5); 462f5b1c8a1SJohn Marino return NULL; 463f5b1c8a1SJohn Marino } 464f5b1c8a1SJohn Marino } else if (!strncmp(arg, "fd:", 3)) { 465f5b1c8a1SJohn Marino BIO *btmp; 466f5b1c8a1SJohn Marino i = strtonum(arg + 3, 0, INT_MAX, &errstr); 467f5b1c8a1SJohn Marino if (errstr) { 468f5b1c8a1SJohn Marino BIO_printf(err, 469f5b1c8a1SJohn Marino "Invalid file descriptor %s: %s\n", 470f5b1c8a1SJohn Marino arg, errstr); 471f5b1c8a1SJohn Marino return NULL; 472f5b1c8a1SJohn Marino } 473f5b1c8a1SJohn Marino pwdbio = BIO_new_fd(i, BIO_NOCLOSE); 474f5b1c8a1SJohn Marino if (!pwdbio) { 475f5b1c8a1SJohn Marino BIO_printf(err, 476f5b1c8a1SJohn Marino "Can't access file descriptor %s\n", 477f5b1c8a1SJohn Marino arg + 3); 478f5b1c8a1SJohn Marino return NULL; 479f5b1c8a1SJohn Marino } 480f5b1c8a1SJohn Marino /* 481f5b1c8a1SJohn Marino * Can't do BIO_gets on an fd BIO so add a buffering 482f5b1c8a1SJohn Marino * BIO 483f5b1c8a1SJohn Marino */ 484f5b1c8a1SJohn Marino btmp = BIO_new(BIO_f_buffer()); 485f5b1c8a1SJohn Marino pwdbio = BIO_push(btmp, pwdbio); 486f5b1c8a1SJohn Marino } else if (!strcmp(arg, "stdin")) { 487f5b1c8a1SJohn Marino pwdbio = BIO_new_fp(stdin, BIO_NOCLOSE); 488f5b1c8a1SJohn Marino if (!pwdbio) { 489f5b1c8a1SJohn Marino BIO_printf(err, "Can't open BIO for stdin\n"); 490f5b1c8a1SJohn Marino return NULL; 491f5b1c8a1SJohn Marino } 492f5b1c8a1SJohn Marino } else { 493f5b1c8a1SJohn Marino BIO_printf(err, "Invalid password argument \"%s\"\n", 494f5b1c8a1SJohn Marino arg); 495f5b1c8a1SJohn Marino return NULL; 496f5b1c8a1SJohn Marino } 497f5b1c8a1SJohn Marino } 498f5b1c8a1SJohn Marino i = BIO_gets(pwdbio, tpass, APP_PASS_LEN); 499f5b1c8a1SJohn Marino if (keepbio != 1) { 500f5b1c8a1SJohn Marino BIO_free_all(pwdbio); 501f5b1c8a1SJohn Marino pwdbio = NULL; 502f5b1c8a1SJohn Marino } 503f5b1c8a1SJohn Marino if (i <= 0) { 504f5b1c8a1SJohn Marino BIO_printf(err, "Error reading password from BIO\n"); 505f5b1c8a1SJohn Marino return NULL; 506f5b1c8a1SJohn Marino } 507f5b1c8a1SJohn Marino tmp = strchr(tpass, '\n'); 508f5b1c8a1SJohn Marino if (tmp) 509f5b1c8a1SJohn Marino *tmp = 0; 510f5b1c8a1SJohn Marino return strdup(tpass); 511f5b1c8a1SJohn Marino } 512f5b1c8a1SJohn Marino 513f5b1c8a1SJohn Marino int 514f5b1c8a1SJohn Marino add_oid_section(BIO *err, CONF *conf) 515f5b1c8a1SJohn Marino { 516f5b1c8a1SJohn Marino char *p; 517f5b1c8a1SJohn Marino STACK_OF(CONF_VALUE) *sktmp; 518f5b1c8a1SJohn Marino CONF_VALUE *cnf; 519f5b1c8a1SJohn Marino int i; 520f5b1c8a1SJohn Marino 521f5b1c8a1SJohn Marino if (!(p = NCONF_get_string(conf, NULL, "oid_section"))) { 522f5b1c8a1SJohn Marino ERR_clear_error(); 523f5b1c8a1SJohn Marino return 1; 524f5b1c8a1SJohn Marino } 525f5b1c8a1SJohn Marino if (!(sktmp = NCONF_get_section(conf, p))) { 526f5b1c8a1SJohn Marino BIO_printf(err, "problem loading oid section %s\n", p); 527f5b1c8a1SJohn Marino return 0; 528f5b1c8a1SJohn Marino } 529f5b1c8a1SJohn Marino for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { 530f5b1c8a1SJohn Marino cnf = sk_CONF_VALUE_value(sktmp, i); 531f5b1c8a1SJohn Marino if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) { 532f5b1c8a1SJohn Marino BIO_printf(err, "problem creating object %s=%s\n", 533f5b1c8a1SJohn Marino cnf->name, cnf->value); 534f5b1c8a1SJohn Marino return 0; 535f5b1c8a1SJohn Marino } 536f5b1c8a1SJohn Marino } 537f5b1c8a1SJohn Marino return 1; 538f5b1c8a1SJohn Marino } 539f5b1c8a1SJohn Marino 540f5b1c8a1SJohn Marino static int 541f5b1c8a1SJohn Marino load_pkcs12(BIO *err, BIO *in, const char *desc, pem_password_cb *pem_cb, 542f5b1c8a1SJohn Marino void *cb_data, EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca) 543f5b1c8a1SJohn Marino { 544f5b1c8a1SJohn Marino const char *pass; 545f5b1c8a1SJohn Marino char tpass[PEM_BUFSIZE]; 546f5b1c8a1SJohn Marino int len, ret = 0; 547f5b1c8a1SJohn Marino PKCS12 *p12; 548f5b1c8a1SJohn Marino 549f5b1c8a1SJohn Marino p12 = d2i_PKCS12_bio(in, NULL); 550f5b1c8a1SJohn Marino if (p12 == NULL) { 551f5b1c8a1SJohn Marino BIO_printf(err, "Error loading PKCS12 file for %s\n", desc); 552f5b1c8a1SJohn Marino goto die; 553f5b1c8a1SJohn Marino } 554f5b1c8a1SJohn Marino /* See if an empty password will do */ 555f5b1c8a1SJohn Marino if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0)) 556f5b1c8a1SJohn Marino pass = ""; 557f5b1c8a1SJohn Marino else { 558f5b1c8a1SJohn Marino if (!pem_cb) 559f5b1c8a1SJohn Marino pem_cb = password_callback; 560f5b1c8a1SJohn Marino len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data); 561f5b1c8a1SJohn Marino if (len < 0) { 562f5b1c8a1SJohn Marino BIO_printf(err, "Passpharse callback error for %s\n", 563f5b1c8a1SJohn Marino desc); 564f5b1c8a1SJohn Marino goto die; 565f5b1c8a1SJohn Marino } 566f5b1c8a1SJohn Marino if (len < PEM_BUFSIZE) 567f5b1c8a1SJohn Marino tpass[len] = 0; 568f5b1c8a1SJohn Marino if (!PKCS12_verify_mac(p12, tpass, len)) { 569f5b1c8a1SJohn Marino BIO_printf(err, 570f5b1c8a1SJohn Marino "Mac verify error (wrong password?) in PKCS12 file for %s\n", desc); 571f5b1c8a1SJohn Marino goto die; 572f5b1c8a1SJohn Marino } 573f5b1c8a1SJohn Marino pass = tpass; 574f5b1c8a1SJohn Marino } 575f5b1c8a1SJohn Marino ret = PKCS12_parse(p12, pass, pkey, cert, ca); 576f5b1c8a1SJohn Marino 577f5b1c8a1SJohn Marino die: 578f5b1c8a1SJohn Marino PKCS12_free(p12); 579f5b1c8a1SJohn Marino return ret; 580f5b1c8a1SJohn Marino } 581f5b1c8a1SJohn Marino 582f5b1c8a1SJohn Marino X509 * 583f5b1c8a1SJohn Marino load_cert(BIO *err, const char *file, int format, const char *pass, 584f5b1c8a1SJohn Marino const char *cert_descrip) 585f5b1c8a1SJohn Marino { 586f5b1c8a1SJohn Marino X509 *x = NULL; 587f5b1c8a1SJohn Marino BIO *cert; 588f5b1c8a1SJohn Marino 589f5b1c8a1SJohn Marino if ((cert = BIO_new(BIO_s_file())) == NULL) { 590f5b1c8a1SJohn Marino ERR_print_errors(err); 591f5b1c8a1SJohn Marino goto end; 592f5b1c8a1SJohn Marino } 593f5b1c8a1SJohn Marino if (file == NULL) { 594f5b1c8a1SJohn Marino setvbuf(stdin, NULL, _IONBF, 0); 595f5b1c8a1SJohn Marino BIO_set_fp(cert, stdin, BIO_NOCLOSE); 596f5b1c8a1SJohn Marino } else { 597f5b1c8a1SJohn Marino if (BIO_read_filename(cert, file) <= 0) { 598f5b1c8a1SJohn Marino BIO_printf(err, "Error opening %s %s\n", 599f5b1c8a1SJohn Marino cert_descrip, file); 600f5b1c8a1SJohn Marino ERR_print_errors(err); 601f5b1c8a1SJohn Marino goto end; 602f5b1c8a1SJohn Marino } 603f5b1c8a1SJohn Marino } 604f5b1c8a1SJohn Marino 605f5b1c8a1SJohn Marino if (format == FORMAT_ASN1) 606f5b1c8a1SJohn Marino x = d2i_X509_bio(cert, NULL); 607*de0e0e4dSAntonio Huete Jimenez else if (format == FORMAT_PEM) 608f5b1c8a1SJohn Marino x = PEM_read_bio_X509_AUX(cert, NULL, password_callback, NULL); 609f5b1c8a1SJohn Marino else if (format == FORMAT_PKCS12) { 610f5b1c8a1SJohn Marino if (!load_pkcs12(err, cert, cert_descrip, NULL, NULL, 611f5b1c8a1SJohn Marino NULL, &x, NULL)) 612f5b1c8a1SJohn Marino goto end; 613f5b1c8a1SJohn Marino } else { 614f5b1c8a1SJohn Marino BIO_printf(err, "bad input format specified for %s\n", 615f5b1c8a1SJohn Marino cert_descrip); 616f5b1c8a1SJohn Marino goto end; 617f5b1c8a1SJohn Marino } 618f5b1c8a1SJohn Marino 619f5b1c8a1SJohn Marino end: 620f5b1c8a1SJohn Marino if (x == NULL) { 621f5b1c8a1SJohn Marino BIO_printf(err, "unable to load certificate\n"); 622f5b1c8a1SJohn Marino ERR_print_errors(err); 623f5b1c8a1SJohn Marino } 624f5b1c8a1SJohn Marino BIO_free(cert); 625f5b1c8a1SJohn Marino return (x); 626f5b1c8a1SJohn Marino } 627f5b1c8a1SJohn Marino 628f5b1c8a1SJohn Marino EVP_PKEY * 629f5b1c8a1SJohn Marino load_key(BIO *err, const char *file, int format, int maybe_stdin, 630f5b1c8a1SJohn Marino const char *pass, const char *key_descrip) 631f5b1c8a1SJohn Marino { 632f5b1c8a1SJohn Marino BIO *key = NULL; 633f5b1c8a1SJohn Marino EVP_PKEY *pkey = NULL; 634f5b1c8a1SJohn Marino PW_CB_DATA cb_data; 635f5b1c8a1SJohn Marino 636f5b1c8a1SJohn Marino cb_data.password = pass; 637f5b1c8a1SJohn Marino cb_data.prompt_info = file; 638f5b1c8a1SJohn Marino 639f5b1c8a1SJohn Marino if (file == NULL && (!maybe_stdin)) { 640f5b1c8a1SJohn Marino BIO_printf(err, "no keyfile specified\n"); 641f5b1c8a1SJohn Marino goto end; 642f5b1c8a1SJohn Marino } 643f5b1c8a1SJohn Marino key = BIO_new(BIO_s_file()); 644f5b1c8a1SJohn Marino if (key == NULL) { 645f5b1c8a1SJohn Marino ERR_print_errors(err); 646f5b1c8a1SJohn Marino goto end; 647f5b1c8a1SJohn Marino } 648f5b1c8a1SJohn Marino if (file == NULL && maybe_stdin) { 649f5b1c8a1SJohn Marino setvbuf(stdin, NULL, _IONBF, 0); 650f5b1c8a1SJohn Marino BIO_set_fp(key, stdin, BIO_NOCLOSE); 651f5b1c8a1SJohn Marino } else if (BIO_read_filename(key, file) <= 0) { 652f5b1c8a1SJohn Marino BIO_printf(err, "Error opening %s %s\n", 653f5b1c8a1SJohn Marino key_descrip, file); 654f5b1c8a1SJohn Marino ERR_print_errors(err); 655f5b1c8a1SJohn Marino goto end; 656f5b1c8a1SJohn Marino } 657f5b1c8a1SJohn Marino if (format == FORMAT_ASN1) { 658f5b1c8a1SJohn Marino pkey = d2i_PrivateKey_bio(key, NULL); 659f5b1c8a1SJohn Marino } else if (format == FORMAT_PEM) { 660f5b1c8a1SJohn Marino pkey = PEM_read_bio_PrivateKey(key, NULL, password_callback, &cb_data); 661f5b1c8a1SJohn Marino } 662f5b1c8a1SJohn Marino else if (format == FORMAT_PKCS12) { 663f5b1c8a1SJohn Marino if (!load_pkcs12(err, key, key_descrip, password_callback, &cb_data, 664f5b1c8a1SJohn Marino &pkey, NULL, NULL)) 665f5b1c8a1SJohn Marino goto end; 666f5b1c8a1SJohn Marino } 667f5b1c8a1SJohn Marino #if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4) 668f5b1c8a1SJohn Marino else if (format == FORMAT_MSBLOB) 669f5b1c8a1SJohn Marino pkey = b2i_PrivateKey_bio(key); 670f5b1c8a1SJohn Marino else if (format == FORMAT_PVK) 671f5b1c8a1SJohn Marino pkey = b2i_PVK_bio(key, password_callback, 672f5b1c8a1SJohn Marino &cb_data); 673f5b1c8a1SJohn Marino #endif 674f5b1c8a1SJohn Marino else { 675f5b1c8a1SJohn Marino BIO_printf(err, "bad input format specified for key file\n"); 676f5b1c8a1SJohn Marino goto end; 677f5b1c8a1SJohn Marino } 678f5b1c8a1SJohn Marino end: 679f5b1c8a1SJohn Marino BIO_free(key); 680f5b1c8a1SJohn Marino if (pkey == NULL) { 681f5b1c8a1SJohn Marino BIO_printf(err, "unable to load %s\n", key_descrip); 682f5b1c8a1SJohn Marino ERR_print_errors(err); 683f5b1c8a1SJohn Marino } 684f5b1c8a1SJohn Marino return (pkey); 685f5b1c8a1SJohn Marino } 686f5b1c8a1SJohn Marino 687f5b1c8a1SJohn Marino EVP_PKEY * 688f5b1c8a1SJohn Marino load_pubkey(BIO *err, const char *file, int format, int maybe_stdin, 689f5b1c8a1SJohn Marino const char *pass, const char *key_descrip) 690f5b1c8a1SJohn Marino { 691f5b1c8a1SJohn Marino BIO *key = NULL; 692f5b1c8a1SJohn Marino EVP_PKEY *pkey = NULL; 693f5b1c8a1SJohn Marino PW_CB_DATA cb_data; 694f5b1c8a1SJohn Marino 695f5b1c8a1SJohn Marino cb_data.password = pass; 696f5b1c8a1SJohn Marino cb_data.prompt_info = file; 697f5b1c8a1SJohn Marino 698f5b1c8a1SJohn Marino if (file == NULL && !maybe_stdin) { 699f5b1c8a1SJohn Marino BIO_printf(err, "no keyfile specified\n"); 700f5b1c8a1SJohn Marino goto end; 701f5b1c8a1SJohn Marino } 702f5b1c8a1SJohn Marino key = BIO_new(BIO_s_file()); 703f5b1c8a1SJohn Marino if (key == NULL) { 704f5b1c8a1SJohn Marino ERR_print_errors(err); 705f5b1c8a1SJohn Marino goto end; 706f5b1c8a1SJohn Marino } 707f5b1c8a1SJohn Marino if (file == NULL && maybe_stdin) { 708f5b1c8a1SJohn Marino setvbuf(stdin, NULL, _IONBF, 0); 709f5b1c8a1SJohn Marino BIO_set_fp(key, stdin, BIO_NOCLOSE); 710f5b1c8a1SJohn Marino } else if (BIO_read_filename(key, file) <= 0) { 711f5b1c8a1SJohn Marino BIO_printf(err, "Error opening %s %s\n", key_descrip, file); 712f5b1c8a1SJohn Marino ERR_print_errors(err); 713f5b1c8a1SJohn Marino goto end; 714f5b1c8a1SJohn Marino } 715f5b1c8a1SJohn Marino if (format == FORMAT_ASN1) { 716f5b1c8a1SJohn Marino pkey = d2i_PUBKEY_bio(key, NULL); 717f5b1c8a1SJohn Marino } 718f5b1c8a1SJohn Marino else if (format == FORMAT_ASN1RSA) { 719f5b1c8a1SJohn Marino RSA *rsa; 720f5b1c8a1SJohn Marino rsa = d2i_RSAPublicKey_bio(key, NULL); 721f5b1c8a1SJohn Marino if (rsa) { 722f5b1c8a1SJohn Marino pkey = EVP_PKEY_new(); 723f5b1c8a1SJohn Marino if (pkey) 724f5b1c8a1SJohn Marino EVP_PKEY_set1_RSA(pkey, rsa); 725f5b1c8a1SJohn Marino RSA_free(rsa); 726f5b1c8a1SJohn Marino } else 727f5b1c8a1SJohn Marino pkey = NULL; 728f5b1c8a1SJohn Marino } else if (format == FORMAT_PEMRSA) { 729f5b1c8a1SJohn Marino RSA *rsa; 730f5b1c8a1SJohn Marino rsa = PEM_read_bio_RSAPublicKey(key, NULL, password_callback, &cb_data); 731f5b1c8a1SJohn Marino if (rsa) { 732f5b1c8a1SJohn Marino pkey = EVP_PKEY_new(); 733f5b1c8a1SJohn Marino if (pkey) 734f5b1c8a1SJohn Marino EVP_PKEY_set1_RSA(pkey, rsa); 735f5b1c8a1SJohn Marino RSA_free(rsa); 736f5b1c8a1SJohn Marino } else 737f5b1c8a1SJohn Marino pkey = NULL; 738f5b1c8a1SJohn Marino } 739f5b1c8a1SJohn Marino else if (format == FORMAT_PEM) { 740f5b1c8a1SJohn Marino pkey = PEM_read_bio_PUBKEY(key, NULL, password_callback, &cb_data); 741f5b1c8a1SJohn Marino } 742f5b1c8a1SJohn Marino #if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) 743f5b1c8a1SJohn Marino else if (format == FORMAT_MSBLOB) 744f5b1c8a1SJohn Marino pkey = b2i_PublicKey_bio(key); 745f5b1c8a1SJohn Marino #endif 746f5b1c8a1SJohn Marino else { 747f5b1c8a1SJohn Marino BIO_printf(err, "bad input format specified for key file\n"); 748f5b1c8a1SJohn Marino goto end; 749f5b1c8a1SJohn Marino } 750f5b1c8a1SJohn Marino 751f5b1c8a1SJohn Marino end: 752f5b1c8a1SJohn Marino BIO_free(key); 753f5b1c8a1SJohn Marino if (pkey == NULL) 754f5b1c8a1SJohn Marino BIO_printf(err, "unable to load %s\n", key_descrip); 755f5b1c8a1SJohn Marino return (pkey); 756f5b1c8a1SJohn Marino } 757f5b1c8a1SJohn Marino 758f5b1c8a1SJohn Marino static int 759f5b1c8a1SJohn Marino load_certs_crls(BIO *err, const char *file, int format, const char *pass, 760f5b1c8a1SJohn Marino const char *desc, STACK_OF(X509) **pcerts, 761f5b1c8a1SJohn Marino STACK_OF(X509_CRL) **pcrls) 762f5b1c8a1SJohn Marino { 763f5b1c8a1SJohn Marino int i; 764f5b1c8a1SJohn Marino BIO *bio; 765f5b1c8a1SJohn Marino STACK_OF(X509_INFO) *xis = NULL; 766f5b1c8a1SJohn Marino X509_INFO *xi; 767f5b1c8a1SJohn Marino PW_CB_DATA cb_data; 768f5b1c8a1SJohn Marino int rv = 0; 769f5b1c8a1SJohn Marino 770f5b1c8a1SJohn Marino cb_data.password = pass; 771f5b1c8a1SJohn Marino cb_data.prompt_info = file; 772f5b1c8a1SJohn Marino 773f5b1c8a1SJohn Marino if (format != FORMAT_PEM) { 774f5b1c8a1SJohn Marino BIO_printf(err, "bad input format specified for %s\n", desc); 775f5b1c8a1SJohn Marino return 0; 776f5b1c8a1SJohn Marino } 777f5b1c8a1SJohn Marino if (file == NULL) 778f5b1c8a1SJohn Marino bio = BIO_new_fp(stdin, BIO_NOCLOSE); 779f5b1c8a1SJohn Marino else 780f5b1c8a1SJohn Marino bio = BIO_new_file(file, "r"); 781f5b1c8a1SJohn Marino 782f5b1c8a1SJohn Marino if (bio == NULL) { 783f5b1c8a1SJohn Marino BIO_printf(err, "Error opening %s %s\n", 784f5b1c8a1SJohn Marino desc, file ? file : "stdin"); 785f5b1c8a1SJohn Marino ERR_print_errors(err); 786f5b1c8a1SJohn Marino return 0; 787f5b1c8a1SJohn Marino } 788f5b1c8a1SJohn Marino xis = PEM_X509_INFO_read_bio(bio, NULL, password_callback, &cb_data); 789f5b1c8a1SJohn Marino 790f5b1c8a1SJohn Marino BIO_free(bio); 791f5b1c8a1SJohn Marino 792f5b1c8a1SJohn Marino if (pcerts) { 793f5b1c8a1SJohn Marino *pcerts = sk_X509_new_null(); 794f5b1c8a1SJohn Marino if (!*pcerts) 795f5b1c8a1SJohn Marino goto end; 796f5b1c8a1SJohn Marino } 797f5b1c8a1SJohn Marino if (pcrls) { 798f5b1c8a1SJohn Marino *pcrls = sk_X509_CRL_new_null(); 799f5b1c8a1SJohn Marino if (!*pcrls) 800f5b1c8a1SJohn Marino goto end; 801f5b1c8a1SJohn Marino } 802f5b1c8a1SJohn Marino for (i = 0; i < sk_X509_INFO_num(xis); i++) { 803f5b1c8a1SJohn Marino xi = sk_X509_INFO_value(xis, i); 804f5b1c8a1SJohn Marino if (xi->x509 && pcerts) { 805f5b1c8a1SJohn Marino if (!sk_X509_push(*pcerts, xi->x509)) 806f5b1c8a1SJohn Marino goto end; 807f5b1c8a1SJohn Marino xi->x509 = NULL; 808f5b1c8a1SJohn Marino } 809f5b1c8a1SJohn Marino if (xi->crl && pcrls) { 810f5b1c8a1SJohn Marino if (!sk_X509_CRL_push(*pcrls, xi->crl)) 811f5b1c8a1SJohn Marino goto end; 812f5b1c8a1SJohn Marino xi->crl = NULL; 813f5b1c8a1SJohn Marino } 814f5b1c8a1SJohn Marino } 815f5b1c8a1SJohn Marino 816f5b1c8a1SJohn Marino if (pcerts && sk_X509_num(*pcerts) > 0) 817f5b1c8a1SJohn Marino rv = 1; 818f5b1c8a1SJohn Marino 819f5b1c8a1SJohn Marino if (pcrls && sk_X509_CRL_num(*pcrls) > 0) 820f5b1c8a1SJohn Marino rv = 1; 821f5b1c8a1SJohn Marino 822f5b1c8a1SJohn Marino end: 823f5b1c8a1SJohn Marino sk_X509_INFO_pop_free(xis, X509_INFO_free); 824f5b1c8a1SJohn Marino 825f5b1c8a1SJohn Marino if (rv == 0) { 826f5b1c8a1SJohn Marino if (pcerts) { 827f5b1c8a1SJohn Marino sk_X509_pop_free(*pcerts, X509_free); 828f5b1c8a1SJohn Marino *pcerts = NULL; 829f5b1c8a1SJohn Marino } 830f5b1c8a1SJohn Marino if (pcrls) { 831f5b1c8a1SJohn Marino sk_X509_CRL_pop_free(*pcrls, X509_CRL_free); 832f5b1c8a1SJohn Marino *pcrls = NULL; 833f5b1c8a1SJohn Marino } 834f5b1c8a1SJohn Marino BIO_printf(err, "unable to load %s\n", 835f5b1c8a1SJohn Marino pcerts ? "certificates" : "CRLs"); 836f5b1c8a1SJohn Marino ERR_print_errors(err); 837f5b1c8a1SJohn Marino } 838f5b1c8a1SJohn Marino return rv; 839f5b1c8a1SJohn Marino } 840f5b1c8a1SJohn Marino 841f5b1c8a1SJohn Marino STACK_OF(X509) * 842f5b1c8a1SJohn Marino load_certs(BIO *err, const char *file, int format, const char *pass, 843f5b1c8a1SJohn Marino const char *desc) 844f5b1c8a1SJohn Marino { 845f5b1c8a1SJohn Marino STACK_OF(X509) *certs; 846f5b1c8a1SJohn Marino 847f5b1c8a1SJohn Marino if (!load_certs_crls(err, file, format, pass, desc, &certs, NULL)) 848f5b1c8a1SJohn Marino return NULL; 849f5b1c8a1SJohn Marino return certs; 850f5b1c8a1SJohn Marino } 851f5b1c8a1SJohn Marino 852f5b1c8a1SJohn Marino STACK_OF(X509_CRL) * 853f5b1c8a1SJohn Marino load_crls(BIO *err, const char *file, int format, const char *pass, 854f5b1c8a1SJohn Marino const char *desc) 855f5b1c8a1SJohn Marino { 856f5b1c8a1SJohn Marino STACK_OF(X509_CRL) *crls; 857f5b1c8a1SJohn Marino 858f5b1c8a1SJohn Marino if (!load_certs_crls(err, file, format, pass, desc, NULL, &crls)) 859f5b1c8a1SJohn Marino return NULL; 860f5b1c8a1SJohn Marino return crls; 861f5b1c8a1SJohn Marino } 862f5b1c8a1SJohn Marino 863f5b1c8a1SJohn Marino #define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) 864f5b1c8a1SJohn Marino /* Return error for unknown extensions */ 865f5b1c8a1SJohn Marino #define X509V3_EXT_DEFAULT 0 866f5b1c8a1SJohn Marino /* Print error for unknown extensions */ 867f5b1c8a1SJohn Marino #define X509V3_EXT_ERROR_UNKNOWN (1L << 16) 868f5b1c8a1SJohn Marino /* ASN1 parse unknown extensions */ 869f5b1c8a1SJohn Marino #define X509V3_EXT_PARSE_UNKNOWN (2L << 16) 870f5b1c8a1SJohn Marino /* BIO_dump unknown extensions */ 871f5b1c8a1SJohn Marino #define X509V3_EXT_DUMP_UNKNOWN (3L << 16) 872f5b1c8a1SJohn Marino 873f5b1c8a1SJohn Marino #define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \ 874f5b1c8a1SJohn Marino X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION) 875f5b1c8a1SJohn Marino 876f5b1c8a1SJohn Marino int 877f5b1c8a1SJohn Marino set_cert_ex(unsigned long *flags, const char *arg) 878f5b1c8a1SJohn Marino { 879f5b1c8a1SJohn Marino static const NAME_EX_TBL cert_tbl[] = { 880f5b1c8a1SJohn Marino {"compatible", X509_FLAG_COMPAT, 0xffffffffl}, 881f5b1c8a1SJohn Marino {"ca_default", X509_FLAG_CA, 0xffffffffl}, 882f5b1c8a1SJohn Marino {"no_header", X509_FLAG_NO_HEADER, 0}, 883f5b1c8a1SJohn Marino {"no_version", X509_FLAG_NO_VERSION, 0}, 884f5b1c8a1SJohn Marino {"no_serial", X509_FLAG_NO_SERIAL, 0}, 885f5b1c8a1SJohn Marino {"no_signame", X509_FLAG_NO_SIGNAME, 0}, 886f5b1c8a1SJohn Marino {"no_validity", X509_FLAG_NO_VALIDITY, 0}, 887f5b1c8a1SJohn Marino {"no_subject", X509_FLAG_NO_SUBJECT, 0}, 888f5b1c8a1SJohn Marino {"no_issuer", X509_FLAG_NO_ISSUER, 0}, 889f5b1c8a1SJohn Marino {"no_pubkey", X509_FLAG_NO_PUBKEY, 0}, 890f5b1c8a1SJohn Marino {"no_extensions", X509_FLAG_NO_EXTENSIONS, 0}, 891f5b1c8a1SJohn Marino {"no_sigdump", X509_FLAG_NO_SIGDUMP, 0}, 892f5b1c8a1SJohn Marino {"no_aux", X509_FLAG_NO_AUX, 0}, 893f5b1c8a1SJohn Marino {"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0}, 894f5b1c8a1SJohn Marino {"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK}, 895f5b1c8a1SJohn Marino {"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, 896f5b1c8a1SJohn Marino {"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, 897f5b1c8a1SJohn Marino {"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, 898f5b1c8a1SJohn Marino {NULL, 0, 0} 899f5b1c8a1SJohn Marino }; 900f5b1c8a1SJohn Marino return set_multi_opts(flags, arg, cert_tbl); 901f5b1c8a1SJohn Marino } 902f5b1c8a1SJohn Marino 903f5b1c8a1SJohn Marino int 904f5b1c8a1SJohn Marino set_name_ex(unsigned long *flags, const char *arg) 905f5b1c8a1SJohn Marino { 906f5b1c8a1SJohn Marino static const NAME_EX_TBL ex_tbl[] = { 907f5b1c8a1SJohn Marino {"esc_2253", ASN1_STRFLGS_ESC_2253, 0}, 908f5b1c8a1SJohn Marino {"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0}, 909f5b1c8a1SJohn Marino {"esc_msb", ASN1_STRFLGS_ESC_MSB, 0}, 910f5b1c8a1SJohn Marino {"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0}, 911f5b1c8a1SJohn Marino {"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0}, 912f5b1c8a1SJohn Marino {"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0}, 913f5b1c8a1SJohn Marino {"show_type", ASN1_STRFLGS_SHOW_TYPE, 0}, 914f5b1c8a1SJohn Marino {"dump_all", ASN1_STRFLGS_DUMP_ALL, 0}, 915f5b1c8a1SJohn Marino {"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0}, 916f5b1c8a1SJohn Marino {"dump_der", ASN1_STRFLGS_DUMP_DER, 0}, 917f5b1c8a1SJohn Marino {"compat", XN_FLAG_COMPAT, 0xffffffffL}, 918f5b1c8a1SJohn Marino {"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK}, 919f5b1c8a1SJohn Marino {"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK}, 920f5b1c8a1SJohn Marino {"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK}, 921f5b1c8a1SJohn Marino {"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK}, 922f5b1c8a1SJohn Marino {"dn_rev", XN_FLAG_DN_REV, 0}, 923f5b1c8a1SJohn Marino {"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK}, 924f5b1c8a1SJohn Marino {"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK}, 925f5b1c8a1SJohn Marino {"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK}, 926f5b1c8a1SJohn Marino {"align", XN_FLAG_FN_ALIGN, 0}, 927f5b1c8a1SJohn Marino {"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK}, 928f5b1c8a1SJohn Marino {"space_eq", XN_FLAG_SPC_EQ, 0}, 929f5b1c8a1SJohn Marino {"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0}, 930f5b1c8a1SJohn Marino {"RFC2253", XN_FLAG_RFC2253, 0xffffffffL}, 931f5b1c8a1SJohn Marino {"oneline", XN_FLAG_ONELINE, 0xffffffffL}, 932f5b1c8a1SJohn Marino {"multiline", XN_FLAG_MULTILINE, 0xffffffffL}, 933f5b1c8a1SJohn Marino {"ca_default", XN_FLAG_MULTILINE, 0xffffffffL}, 934f5b1c8a1SJohn Marino {NULL, 0, 0} 935f5b1c8a1SJohn Marino }; 936f5b1c8a1SJohn Marino return set_multi_opts(flags, arg, ex_tbl); 937f5b1c8a1SJohn Marino } 938f5b1c8a1SJohn Marino 939f5b1c8a1SJohn Marino int 940f5b1c8a1SJohn Marino set_ext_copy(int *copy_type, const char *arg) 941f5b1c8a1SJohn Marino { 942f5b1c8a1SJohn Marino if (!strcasecmp(arg, "none")) 943f5b1c8a1SJohn Marino *copy_type = EXT_COPY_NONE; 944f5b1c8a1SJohn Marino else if (!strcasecmp(arg, "copy")) 945f5b1c8a1SJohn Marino *copy_type = EXT_COPY_ADD; 946f5b1c8a1SJohn Marino else if (!strcasecmp(arg, "copyall")) 947f5b1c8a1SJohn Marino *copy_type = EXT_COPY_ALL; 948f5b1c8a1SJohn Marino else 949f5b1c8a1SJohn Marino return 0; 950f5b1c8a1SJohn Marino return 1; 951f5b1c8a1SJohn Marino } 952f5b1c8a1SJohn Marino 953f5b1c8a1SJohn Marino int 954f5b1c8a1SJohn Marino copy_extensions(X509 *x, X509_REQ *req, int copy_type) 955f5b1c8a1SJohn Marino { 956f5b1c8a1SJohn Marino STACK_OF(X509_EXTENSION) *exts = NULL; 957f5b1c8a1SJohn Marino X509_EXTENSION *ext, *tmpext; 958f5b1c8a1SJohn Marino ASN1_OBJECT *obj; 959f5b1c8a1SJohn Marino int i, idx, ret = 0; 960f5b1c8a1SJohn Marino 961f5b1c8a1SJohn Marino if (!x || !req || (copy_type == EXT_COPY_NONE)) 962f5b1c8a1SJohn Marino return 1; 963f5b1c8a1SJohn Marino exts = X509_REQ_get_extensions(req); 964f5b1c8a1SJohn Marino 965f5b1c8a1SJohn Marino for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { 966f5b1c8a1SJohn Marino ext = sk_X509_EXTENSION_value(exts, i); 967f5b1c8a1SJohn Marino obj = X509_EXTENSION_get_object(ext); 968f5b1c8a1SJohn Marino idx = X509_get_ext_by_OBJ(x, obj, -1); 969f5b1c8a1SJohn Marino /* Does extension exist? */ 970f5b1c8a1SJohn Marino if (idx != -1) { 971f5b1c8a1SJohn Marino /* If normal copy don't override existing extension */ 972f5b1c8a1SJohn Marino if (copy_type == EXT_COPY_ADD) 973f5b1c8a1SJohn Marino continue; 974f5b1c8a1SJohn Marino /* Delete all extensions of same type */ 975f5b1c8a1SJohn Marino do { 976f5b1c8a1SJohn Marino tmpext = X509_get_ext(x, idx); 977f5b1c8a1SJohn Marino X509_delete_ext(x, idx); 978f5b1c8a1SJohn Marino X509_EXTENSION_free(tmpext); 979f5b1c8a1SJohn Marino idx = X509_get_ext_by_OBJ(x, obj, -1); 980f5b1c8a1SJohn Marino } while (idx != -1); 981f5b1c8a1SJohn Marino } 982f5b1c8a1SJohn Marino if (!X509_add_ext(x, ext, -1)) 983f5b1c8a1SJohn Marino goto end; 984f5b1c8a1SJohn Marino } 985f5b1c8a1SJohn Marino 986f5b1c8a1SJohn Marino ret = 1; 987f5b1c8a1SJohn Marino 988f5b1c8a1SJohn Marino end: 989f5b1c8a1SJohn Marino sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); 990f5b1c8a1SJohn Marino 991f5b1c8a1SJohn Marino return ret; 992f5b1c8a1SJohn Marino } 993f5b1c8a1SJohn Marino 994f5b1c8a1SJohn Marino static int 995f5b1c8a1SJohn Marino set_multi_opts(unsigned long *flags, const char *arg, 996f5b1c8a1SJohn Marino const NAME_EX_TBL *in_tbl) 997f5b1c8a1SJohn Marino { 998f5b1c8a1SJohn Marino STACK_OF(CONF_VALUE) *vals; 999f5b1c8a1SJohn Marino CONF_VALUE *val; 1000f5b1c8a1SJohn Marino int i, ret = 1; 1001f5b1c8a1SJohn Marino 1002f5b1c8a1SJohn Marino if (!arg) 1003f5b1c8a1SJohn Marino return 0; 1004f5b1c8a1SJohn Marino vals = X509V3_parse_list(arg); 1005f5b1c8a1SJohn Marino for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { 1006f5b1c8a1SJohn Marino val = sk_CONF_VALUE_value(vals, i); 1007f5b1c8a1SJohn Marino if (!set_table_opts(flags, val->name, in_tbl)) 1008f5b1c8a1SJohn Marino ret = 0; 1009f5b1c8a1SJohn Marino } 1010f5b1c8a1SJohn Marino sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); 1011f5b1c8a1SJohn Marino return ret; 1012f5b1c8a1SJohn Marino } 1013f5b1c8a1SJohn Marino 1014f5b1c8a1SJohn Marino static int 1015f5b1c8a1SJohn Marino set_table_opts(unsigned long *flags, const char *arg, 1016f5b1c8a1SJohn Marino const NAME_EX_TBL *in_tbl) 1017f5b1c8a1SJohn Marino { 1018f5b1c8a1SJohn Marino char c; 1019f5b1c8a1SJohn Marino const NAME_EX_TBL *ptbl; 1020f5b1c8a1SJohn Marino 1021f5b1c8a1SJohn Marino c = arg[0]; 1022f5b1c8a1SJohn Marino if (c == '-') { 1023f5b1c8a1SJohn Marino c = 0; 1024f5b1c8a1SJohn Marino arg++; 1025f5b1c8a1SJohn Marino } else if (c == '+') { 1026f5b1c8a1SJohn Marino c = 1; 1027f5b1c8a1SJohn Marino arg++; 1028f5b1c8a1SJohn Marino } else 1029f5b1c8a1SJohn Marino c = 1; 1030f5b1c8a1SJohn Marino 1031f5b1c8a1SJohn Marino for (ptbl = in_tbl; ptbl->name; ptbl++) { 1032f5b1c8a1SJohn Marino if (!strcasecmp(arg, ptbl->name)) { 1033f5b1c8a1SJohn Marino *flags &= ~ptbl->mask; 1034f5b1c8a1SJohn Marino if (c) 1035f5b1c8a1SJohn Marino *flags |= ptbl->flag; 1036f5b1c8a1SJohn Marino else 1037f5b1c8a1SJohn Marino *flags &= ~ptbl->flag; 1038f5b1c8a1SJohn Marino return 1; 1039f5b1c8a1SJohn Marino } 1040f5b1c8a1SJohn Marino } 1041f5b1c8a1SJohn Marino return 0; 1042f5b1c8a1SJohn Marino } 1043f5b1c8a1SJohn Marino 1044f5b1c8a1SJohn Marino void 1045f5b1c8a1SJohn Marino print_name(BIO *out, const char *title, X509_NAME *nm, unsigned long lflags) 1046f5b1c8a1SJohn Marino { 1047f5b1c8a1SJohn Marino char *buf; 1048f5b1c8a1SJohn Marino char mline = 0; 1049f5b1c8a1SJohn Marino int indent = 0; 1050f5b1c8a1SJohn Marino 1051f5b1c8a1SJohn Marino if (title) 1052f5b1c8a1SJohn Marino BIO_puts(out, title); 1053f5b1c8a1SJohn Marino if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { 1054f5b1c8a1SJohn Marino mline = 1; 1055f5b1c8a1SJohn Marino indent = 4; 1056f5b1c8a1SJohn Marino } 1057f5b1c8a1SJohn Marino if (lflags == XN_FLAG_COMPAT) { 1058f5b1c8a1SJohn Marino buf = X509_NAME_oneline(nm, 0, 0); 1059f5b1c8a1SJohn Marino BIO_puts(out, buf); 1060f5b1c8a1SJohn Marino BIO_puts(out, "\n"); 1061f5b1c8a1SJohn Marino free(buf); 1062f5b1c8a1SJohn Marino } else { 1063f5b1c8a1SJohn Marino if (mline) 1064f5b1c8a1SJohn Marino BIO_puts(out, "\n"); 1065f5b1c8a1SJohn Marino X509_NAME_print_ex(out, nm, indent, lflags); 1066f5b1c8a1SJohn Marino BIO_puts(out, "\n"); 1067f5b1c8a1SJohn Marino } 1068f5b1c8a1SJohn Marino } 1069f5b1c8a1SJohn Marino 1070f5b1c8a1SJohn Marino X509_STORE * 1071f5b1c8a1SJohn Marino setup_verify(BIO *bp, char *CAfile, char *CApath) 1072f5b1c8a1SJohn Marino { 1073f5b1c8a1SJohn Marino X509_STORE *store; 1074f5b1c8a1SJohn Marino X509_LOOKUP *lookup; 1075f5b1c8a1SJohn Marino 1076f5b1c8a1SJohn Marino if (!(store = X509_STORE_new())) 1077f5b1c8a1SJohn Marino goto end; 1078f5b1c8a1SJohn Marino lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); 1079f5b1c8a1SJohn Marino if (lookup == NULL) 1080f5b1c8a1SJohn Marino goto end; 1081f5b1c8a1SJohn Marino if (CAfile) { 1082f5b1c8a1SJohn Marino if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) { 1083f5b1c8a1SJohn Marino BIO_printf(bp, "Error loading file %s\n", CAfile); 1084f5b1c8a1SJohn Marino goto end; 1085f5b1c8a1SJohn Marino } 1086f5b1c8a1SJohn Marino } else 1087f5b1c8a1SJohn Marino X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); 1088f5b1c8a1SJohn Marino 1089f5b1c8a1SJohn Marino lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); 1090f5b1c8a1SJohn Marino if (lookup == NULL) 1091f5b1c8a1SJohn Marino goto end; 1092f5b1c8a1SJohn Marino if (CApath) { 1093f5b1c8a1SJohn Marino if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) { 1094f5b1c8a1SJohn Marino BIO_printf(bp, "Error loading directory %s\n", CApath); 1095f5b1c8a1SJohn Marino goto end; 1096f5b1c8a1SJohn Marino } 1097f5b1c8a1SJohn Marino } else 1098f5b1c8a1SJohn Marino X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); 1099f5b1c8a1SJohn Marino 1100f5b1c8a1SJohn Marino ERR_clear_error(); 1101f5b1c8a1SJohn Marino return store; 1102f5b1c8a1SJohn Marino 1103f5b1c8a1SJohn Marino end: 1104f5b1c8a1SJohn Marino X509_STORE_free(store); 1105f5b1c8a1SJohn Marino return NULL; 1106f5b1c8a1SJohn Marino } 1107f5b1c8a1SJohn Marino 1108f5b1c8a1SJohn Marino int 1109f5b1c8a1SJohn Marino load_config(BIO *err, CONF *cnf) 1110f5b1c8a1SJohn Marino { 1111f5b1c8a1SJohn Marino static int load_config_called = 0; 1112f5b1c8a1SJohn Marino 1113f5b1c8a1SJohn Marino if (load_config_called) 1114f5b1c8a1SJohn Marino return 1; 1115f5b1c8a1SJohn Marino load_config_called = 1; 1116f5b1c8a1SJohn Marino if (cnf == NULL) 1117f5b1c8a1SJohn Marino cnf = config; 1118f5b1c8a1SJohn Marino if (cnf == NULL) 1119f5b1c8a1SJohn Marino return 1; 1120f5b1c8a1SJohn Marino 1121f5b1c8a1SJohn Marino OPENSSL_load_builtin_modules(); 1122f5b1c8a1SJohn Marino 1123f5b1c8a1SJohn Marino if (CONF_modules_load(cnf, NULL, 0) <= 0) { 1124f5b1c8a1SJohn Marino BIO_printf(err, "Error configuring OpenSSL\n"); 1125f5b1c8a1SJohn Marino ERR_print_errors(err); 1126f5b1c8a1SJohn Marino return 0; 1127f5b1c8a1SJohn Marino } 1128f5b1c8a1SJohn Marino return 1; 1129f5b1c8a1SJohn Marino } 1130f5b1c8a1SJohn Marino 1131f5b1c8a1SJohn Marino char * 1132f5b1c8a1SJohn Marino make_config_name() 1133f5b1c8a1SJohn Marino { 1134f5b1c8a1SJohn Marino const char *t = X509_get_default_cert_area(); 1135f5b1c8a1SJohn Marino char *p; 1136f5b1c8a1SJohn Marino 1137f5b1c8a1SJohn Marino if (asprintf(&p, "%s/openssl.cnf", t) == -1) 1138f5b1c8a1SJohn Marino return NULL; 1139f5b1c8a1SJohn Marino return p; 1140f5b1c8a1SJohn Marino } 1141f5b1c8a1SJohn Marino 1142f5b1c8a1SJohn Marino static unsigned long 1143f5b1c8a1SJohn Marino index_serial_hash(const OPENSSL_CSTRING *a) 1144f5b1c8a1SJohn Marino { 1145f5b1c8a1SJohn Marino const char *n; 1146f5b1c8a1SJohn Marino 1147f5b1c8a1SJohn Marino n = a[DB_serial]; 1148f5b1c8a1SJohn Marino while (*n == '0') 1149f5b1c8a1SJohn Marino n++; 1150f5b1c8a1SJohn Marino return (lh_strhash(n)); 1151f5b1c8a1SJohn Marino } 1152f5b1c8a1SJohn Marino 1153f5b1c8a1SJohn Marino static int 1154f5b1c8a1SJohn Marino index_serial_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b) 1155f5b1c8a1SJohn Marino { 1156f5b1c8a1SJohn Marino const char *aa, *bb; 1157f5b1c8a1SJohn Marino 1158f5b1c8a1SJohn Marino for (aa = a[DB_serial]; *aa == '0'; aa++) 1159f5b1c8a1SJohn Marino ; 1160f5b1c8a1SJohn Marino for (bb = b[DB_serial]; *bb == '0'; bb++) 1161f5b1c8a1SJohn Marino ; 1162f5b1c8a1SJohn Marino return (strcmp(aa, bb)); 1163f5b1c8a1SJohn Marino } 1164f5b1c8a1SJohn Marino 1165f5b1c8a1SJohn Marino static int 1166f5b1c8a1SJohn Marino index_name_qual(char **a) 1167f5b1c8a1SJohn Marino { 1168f5b1c8a1SJohn Marino return (a[0][0] == 'V'); 1169f5b1c8a1SJohn Marino } 1170f5b1c8a1SJohn Marino 1171f5b1c8a1SJohn Marino static unsigned long 1172f5b1c8a1SJohn Marino index_name_hash(const OPENSSL_CSTRING *a) 1173f5b1c8a1SJohn Marino { 1174f5b1c8a1SJohn Marino return (lh_strhash(a[DB_name])); 1175f5b1c8a1SJohn Marino } 1176f5b1c8a1SJohn Marino 1177f5b1c8a1SJohn Marino int 1178f5b1c8a1SJohn Marino index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b) 1179f5b1c8a1SJohn Marino { 1180f5b1c8a1SJohn Marino return (strcmp(a[DB_name], b[DB_name])); 1181f5b1c8a1SJohn Marino } 1182f5b1c8a1SJohn Marino 1183f5b1c8a1SJohn Marino static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING) 1184f5b1c8a1SJohn Marino static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING) 1185f5b1c8a1SJohn Marino static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING) 1186f5b1c8a1SJohn Marino static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING) 1187f5b1c8a1SJohn Marino 1188f5b1c8a1SJohn Marino BIGNUM * 1189f5b1c8a1SJohn Marino load_serial(char *serialfile, int create, ASN1_INTEGER **retai) 1190f5b1c8a1SJohn Marino { 1191f5b1c8a1SJohn Marino BIO *in = NULL; 1192f5b1c8a1SJohn Marino BIGNUM *ret = NULL; 1193f5b1c8a1SJohn Marino char buf[1024]; 1194f5b1c8a1SJohn Marino ASN1_INTEGER *ai = NULL; 1195f5b1c8a1SJohn Marino 1196f5b1c8a1SJohn Marino ai = ASN1_INTEGER_new(); 1197f5b1c8a1SJohn Marino if (ai == NULL) 1198f5b1c8a1SJohn Marino goto err; 1199f5b1c8a1SJohn Marino 1200f5b1c8a1SJohn Marino if ((in = BIO_new(BIO_s_file())) == NULL) { 1201f5b1c8a1SJohn Marino ERR_print_errors(bio_err); 1202f5b1c8a1SJohn Marino goto err; 1203f5b1c8a1SJohn Marino } 1204f5b1c8a1SJohn Marino if (BIO_read_filename(in, serialfile) <= 0) { 1205f5b1c8a1SJohn Marino if (!create) { 1206f5b1c8a1SJohn Marino perror(serialfile); 1207f5b1c8a1SJohn Marino goto err; 1208f5b1c8a1SJohn Marino } else { 1209f5b1c8a1SJohn Marino ret = BN_new(); 1210f5b1c8a1SJohn Marino if (ret == NULL || !rand_serial(ret, ai)) 1211f5b1c8a1SJohn Marino BIO_printf(bio_err, "Out of memory\n"); 1212f5b1c8a1SJohn Marino } 1213f5b1c8a1SJohn Marino } else { 121472c33676SMaxim Ag if (!a2i_ASN1_INTEGER(in, ai, buf, sizeof buf)) { 1215f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to load number from %s\n", 1216f5b1c8a1SJohn Marino serialfile); 1217f5b1c8a1SJohn Marino goto err; 1218f5b1c8a1SJohn Marino } 1219f5b1c8a1SJohn Marino ret = ASN1_INTEGER_to_BN(ai, NULL); 1220f5b1c8a1SJohn Marino if (ret == NULL) { 1221f5b1c8a1SJohn Marino BIO_printf(bio_err, 1222f5b1c8a1SJohn Marino "error converting number from bin to BIGNUM\n"); 1223f5b1c8a1SJohn Marino goto err; 1224f5b1c8a1SJohn Marino } 1225f5b1c8a1SJohn Marino } 1226f5b1c8a1SJohn Marino 1227f5b1c8a1SJohn Marino if (ret && retai) { 1228f5b1c8a1SJohn Marino *retai = ai; 1229f5b1c8a1SJohn Marino ai = NULL; 1230f5b1c8a1SJohn Marino } 1231f5b1c8a1SJohn Marino 1232f5b1c8a1SJohn Marino err: 1233f5b1c8a1SJohn Marino BIO_free(in); 1234f5b1c8a1SJohn Marino ASN1_INTEGER_free(ai); 1235f5b1c8a1SJohn Marino return (ret); 1236f5b1c8a1SJohn Marino } 1237f5b1c8a1SJohn Marino 1238f5b1c8a1SJohn Marino int 1239f5b1c8a1SJohn Marino save_serial(char *serialfile, char *suffix, BIGNUM *serial, 1240f5b1c8a1SJohn Marino ASN1_INTEGER **retai) 1241f5b1c8a1SJohn Marino { 124272c33676SMaxim Ag char serialpath[PATH_MAX]; 1243f5b1c8a1SJohn Marino BIO *out = NULL; 1244f5b1c8a1SJohn Marino int ret = 0, n; 1245f5b1c8a1SJohn Marino ASN1_INTEGER *ai = NULL; 1246f5b1c8a1SJohn Marino 1247f5b1c8a1SJohn Marino if (suffix == NULL) 124872c33676SMaxim Ag n = strlcpy(serialpath, serialfile, sizeof serialpath); 1249f5b1c8a1SJohn Marino else 125072c33676SMaxim Ag n = snprintf(serialpath, sizeof serialpath, "%s.%s", 1251f5b1c8a1SJohn Marino serialfile, suffix); 1252cca6fc52SDaniel Fojt if (n < 0 || n >= sizeof(serialpath)) { 1253f5b1c8a1SJohn Marino BIO_printf(bio_err, "serial too long\n"); 1254f5b1c8a1SJohn Marino goto err; 1255f5b1c8a1SJohn Marino } 1256f5b1c8a1SJohn Marino out = BIO_new(BIO_s_file()); 1257f5b1c8a1SJohn Marino if (out == NULL) { 1258f5b1c8a1SJohn Marino ERR_print_errors(bio_err); 1259f5b1c8a1SJohn Marino goto err; 1260f5b1c8a1SJohn Marino } 126172c33676SMaxim Ag if (BIO_write_filename(out, serialpath) <= 0) { 1262f5b1c8a1SJohn Marino perror(serialfile); 1263f5b1c8a1SJohn Marino goto err; 1264f5b1c8a1SJohn Marino } 1265f5b1c8a1SJohn Marino if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) { 1266f5b1c8a1SJohn Marino BIO_printf(bio_err, 1267f5b1c8a1SJohn Marino "error converting serial to ASN.1 format\n"); 1268f5b1c8a1SJohn Marino goto err; 1269f5b1c8a1SJohn Marino } 1270f5b1c8a1SJohn Marino i2a_ASN1_INTEGER(out, ai); 1271f5b1c8a1SJohn Marino BIO_puts(out, "\n"); 1272f5b1c8a1SJohn Marino ret = 1; 1273f5b1c8a1SJohn Marino if (retai) { 1274f5b1c8a1SJohn Marino *retai = ai; 1275f5b1c8a1SJohn Marino ai = NULL; 1276f5b1c8a1SJohn Marino } 1277f5b1c8a1SJohn Marino 1278f5b1c8a1SJohn Marino err: 1279f5b1c8a1SJohn Marino BIO_free_all(out); 1280f5b1c8a1SJohn Marino ASN1_INTEGER_free(ai); 1281f5b1c8a1SJohn Marino return (ret); 1282f5b1c8a1SJohn Marino } 1283f5b1c8a1SJohn Marino 1284f5b1c8a1SJohn Marino int 1285f5b1c8a1SJohn Marino rotate_serial(char *serialfile, char *new_suffix, char *old_suffix) 1286f5b1c8a1SJohn Marino { 128772c33676SMaxim Ag char opath[PATH_MAX], npath[PATH_MAX]; 1288f5b1c8a1SJohn Marino 128972c33676SMaxim Ag if (snprintf(npath, sizeof npath, "%s.%s", serialfile, 129072c33676SMaxim Ag new_suffix) >= sizeof npath) { 1291f5b1c8a1SJohn Marino BIO_printf(bio_err, "file name too long\n"); 1292f5b1c8a1SJohn Marino goto err; 1293f5b1c8a1SJohn Marino } 1294f5b1c8a1SJohn Marino 129572c33676SMaxim Ag if (snprintf(opath, sizeof opath, "%s.%s", serialfile, 129672c33676SMaxim Ag old_suffix) >= sizeof opath) { 129772c33676SMaxim Ag BIO_printf(bio_err, "file name too long\n"); 129872c33676SMaxim Ag goto err; 129972c33676SMaxim Ag } 1300f5b1c8a1SJohn Marino 1301cca6fc52SDaniel Fojt if (rename(serialfile, opath) == -1 && 1302f5b1c8a1SJohn Marino errno != ENOENT && errno != ENOTDIR) { 1303f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to rename %s to %s\n", 130472c33676SMaxim Ag serialfile, opath); 1305f5b1c8a1SJohn Marino perror("reason"); 1306f5b1c8a1SJohn Marino goto err; 1307f5b1c8a1SJohn Marino } 1308f5b1c8a1SJohn Marino 1309f5b1c8a1SJohn Marino 1310cca6fc52SDaniel Fojt if (rename(npath, serialfile) == -1) { 1311f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to rename %s to %s\n", 131272c33676SMaxim Ag npath, serialfile); 1313f5b1c8a1SJohn Marino perror("reason"); 1314cca6fc52SDaniel Fojt if (rename(opath, serialfile) == -1) { 1315f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to rename %s to %s\n", 131672c33676SMaxim Ag opath, serialfile); 1317f5b1c8a1SJohn Marino perror("reason"); 1318f5b1c8a1SJohn Marino } 1319f5b1c8a1SJohn Marino goto err; 1320f5b1c8a1SJohn Marino } 1321f5b1c8a1SJohn Marino return 1; 1322f5b1c8a1SJohn Marino 1323f5b1c8a1SJohn Marino err: 1324f5b1c8a1SJohn Marino return 0; 1325f5b1c8a1SJohn Marino } 1326f5b1c8a1SJohn Marino 1327f5b1c8a1SJohn Marino int 1328f5b1c8a1SJohn Marino rand_serial(BIGNUM *b, ASN1_INTEGER *ai) 1329f5b1c8a1SJohn Marino { 1330f5b1c8a1SJohn Marino BIGNUM *btmp; 1331f5b1c8a1SJohn Marino int ret = 0; 1332f5b1c8a1SJohn Marino 1333f5b1c8a1SJohn Marino if (b) 1334f5b1c8a1SJohn Marino btmp = b; 1335f5b1c8a1SJohn Marino else 1336f5b1c8a1SJohn Marino btmp = BN_new(); 1337f5b1c8a1SJohn Marino 1338f5b1c8a1SJohn Marino if (!btmp) 1339f5b1c8a1SJohn Marino return 0; 1340f5b1c8a1SJohn Marino 1341f5b1c8a1SJohn Marino if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) 1342f5b1c8a1SJohn Marino goto error; 1343f5b1c8a1SJohn Marino if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) 1344f5b1c8a1SJohn Marino goto error; 1345f5b1c8a1SJohn Marino 1346f5b1c8a1SJohn Marino ret = 1; 1347f5b1c8a1SJohn Marino 1348f5b1c8a1SJohn Marino error: 134972c33676SMaxim Ag if (b != btmp) 1350f5b1c8a1SJohn Marino BN_free(btmp); 1351f5b1c8a1SJohn Marino 1352f5b1c8a1SJohn Marino return ret; 1353f5b1c8a1SJohn Marino } 1354f5b1c8a1SJohn Marino 1355f5b1c8a1SJohn Marino CA_DB * 1356f5b1c8a1SJohn Marino load_index(char *dbfile, DB_ATTR *db_attr) 1357f5b1c8a1SJohn Marino { 1358f5b1c8a1SJohn Marino CA_DB *retdb = NULL; 1359f5b1c8a1SJohn Marino TXT_DB *tmpdb = NULL; 1360f5b1c8a1SJohn Marino BIO *in = BIO_new(BIO_s_file()); 1361f5b1c8a1SJohn Marino CONF *dbattr_conf = NULL; 136272c33676SMaxim Ag char attrpath[PATH_MAX]; 1363f5b1c8a1SJohn Marino long errorline = -1; 1364f5b1c8a1SJohn Marino 1365f5b1c8a1SJohn Marino if (in == NULL) { 1366f5b1c8a1SJohn Marino ERR_print_errors(bio_err); 1367f5b1c8a1SJohn Marino goto err; 1368f5b1c8a1SJohn Marino } 1369f5b1c8a1SJohn Marino if (BIO_read_filename(in, dbfile) <= 0) { 1370f5b1c8a1SJohn Marino perror(dbfile); 1371f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to open '%s'\n", dbfile); 1372f5b1c8a1SJohn Marino goto err; 1373f5b1c8a1SJohn Marino } 1374f5b1c8a1SJohn Marino if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL) 1375f5b1c8a1SJohn Marino goto err; 1376f5b1c8a1SJohn Marino 137772c33676SMaxim Ag if (snprintf(attrpath, sizeof attrpath, "%s.attr", dbfile) 137872c33676SMaxim Ag >= sizeof attrpath) { 137972c33676SMaxim Ag BIO_printf(bio_err, "attr filename too long\n"); 138072c33676SMaxim Ag goto err; 138172c33676SMaxim Ag } 138272c33676SMaxim Ag 1383f5b1c8a1SJohn Marino dbattr_conf = NCONF_new(NULL); 138472c33676SMaxim Ag if (NCONF_load(dbattr_conf, attrpath, &errorline) <= 0) { 1385f5b1c8a1SJohn Marino if (errorline > 0) { 1386f5b1c8a1SJohn Marino BIO_printf(bio_err, 1387f5b1c8a1SJohn Marino "error on line %ld of db attribute file '%s'\n", 138872c33676SMaxim Ag errorline, attrpath); 1389f5b1c8a1SJohn Marino goto err; 1390f5b1c8a1SJohn Marino } else { 1391f5b1c8a1SJohn Marino NCONF_free(dbattr_conf); 1392f5b1c8a1SJohn Marino dbattr_conf = NULL; 1393f5b1c8a1SJohn Marino } 1394f5b1c8a1SJohn Marino } 1395f5b1c8a1SJohn Marino if ((retdb = malloc(sizeof(CA_DB))) == NULL) { 1396f5b1c8a1SJohn Marino fprintf(stderr, "Out of memory\n"); 1397f5b1c8a1SJohn Marino goto err; 1398f5b1c8a1SJohn Marino } 1399f5b1c8a1SJohn Marino retdb->db = tmpdb; 1400f5b1c8a1SJohn Marino tmpdb = NULL; 1401f5b1c8a1SJohn Marino if (db_attr) 1402f5b1c8a1SJohn Marino retdb->attributes = *db_attr; 1403f5b1c8a1SJohn Marino else { 1404f5b1c8a1SJohn Marino retdb->attributes.unique_subject = 1; 1405f5b1c8a1SJohn Marino } 1406f5b1c8a1SJohn Marino 1407f5b1c8a1SJohn Marino if (dbattr_conf) { 1408f5b1c8a1SJohn Marino char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject"); 1409f5b1c8a1SJohn Marino if (p) { 1410f5b1c8a1SJohn Marino retdb->attributes.unique_subject = parse_yesno(p, 1); 1411f5b1c8a1SJohn Marino } 1412f5b1c8a1SJohn Marino } 1413f5b1c8a1SJohn Marino 1414f5b1c8a1SJohn Marino err: 1415f5b1c8a1SJohn Marino NCONF_free(dbattr_conf); 1416f5b1c8a1SJohn Marino TXT_DB_free(tmpdb); 1417f5b1c8a1SJohn Marino BIO_free_all(in); 1418f5b1c8a1SJohn Marino return retdb; 1419f5b1c8a1SJohn Marino } 1420f5b1c8a1SJohn Marino 1421f5b1c8a1SJohn Marino int 1422f5b1c8a1SJohn Marino index_index(CA_DB *db) 1423f5b1c8a1SJohn Marino { 1424f5b1c8a1SJohn Marino if (!TXT_DB_create_index(db->db, DB_serial, NULL, 1425f5b1c8a1SJohn Marino LHASH_HASH_FN(index_serial), LHASH_COMP_FN(index_serial))) { 1426f5b1c8a1SJohn Marino BIO_printf(bio_err, 1427f5b1c8a1SJohn Marino "error creating serial number index:(%ld,%ld,%ld)\n", 1428f5b1c8a1SJohn Marino db->db->error, db->db->arg1, db->db->arg2); 1429f5b1c8a1SJohn Marino return 0; 1430f5b1c8a1SJohn Marino } 1431f5b1c8a1SJohn Marino if (db->attributes.unique_subject && 1432f5b1c8a1SJohn Marino !TXT_DB_create_index(db->db, DB_name, index_name_qual, 1433f5b1c8a1SJohn Marino LHASH_HASH_FN(index_name), LHASH_COMP_FN(index_name))) { 1434f5b1c8a1SJohn Marino BIO_printf(bio_err, "error creating name index:(%ld,%ld,%ld)\n", 1435f5b1c8a1SJohn Marino db->db->error, db->db->arg1, db->db->arg2); 1436f5b1c8a1SJohn Marino return 0; 1437f5b1c8a1SJohn Marino } 1438f5b1c8a1SJohn Marino return 1; 1439f5b1c8a1SJohn Marino } 1440f5b1c8a1SJohn Marino 1441f5b1c8a1SJohn Marino int 144272c33676SMaxim Ag save_index(const char *file, const char *suffix, CA_DB *db) 1443f5b1c8a1SJohn Marino { 144472c33676SMaxim Ag char attrpath[PATH_MAX], dbfile[PATH_MAX]; 1445f5b1c8a1SJohn Marino BIO *out = BIO_new(BIO_s_file()); 1446f5b1c8a1SJohn Marino int j; 1447f5b1c8a1SJohn Marino 1448f5b1c8a1SJohn Marino if (out == NULL) { 1449f5b1c8a1SJohn Marino ERR_print_errors(bio_err); 1450f5b1c8a1SJohn Marino goto err; 1451f5b1c8a1SJohn Marino } 145272c33676SMaxim Ag if (snprintf(attrpath, sizeof attrpath, "%s.attr.%s", 145372c33676SMaxim Ag file, suffix) >= sizeof attrpath) { 1454f5b1c8a1SJohn Marino BIO_printf(bio_err, "file name too long\n"); 1455f5b1c8a1SJohn Marino goto err; 1456f5b1c8a1SJohn Marino } 145772c33676SMaxim Ag if (snprintf(dbfile, sizeof dbfile, "%s.%s", 145872c33676SMaxim Ag file, suffix) >= sizeof dbfile) { 145972c33676SMaxim Ag BIO_printf(bio_err, "file name too long\n"); 146072c33676SMaxim Ag goto err; 146172c33676SMaxim Ag } 1462f5b1c8a1SJohn Marino 146372c33676SMaxim Ag if (BIO_write_filename(out, dbfile) <= 0) { 1464f5b1c8a1SJohn Marino perror(dbfile); 1465f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to open '%s'\n", dbfile); 1466f5b1c8a1SJohn Marino goto err; 1467f5b1c8a1SJohn Marino } 1468f5b1c8a1SJohn Marino j = TXT_DB_write(out, db->db); 1469f5b1c8a1SJohn Marino if (j <= 0) 1470f5b1c8a1SJohn Marino goto err; 1471f5b1c8a1SJohn Marino 1472f5b1c8a1SJohn Marino BIO_free(out); 1473f5b1c8a1SJohn Marino 1474f5b1c8a1SJohn Marino out = BIO_new(BIO_s_file()); 1475f5b1c8a1SJohn Marino 147672c33676SMaxim Ag if (BIO_write_filename(out, attrpath) <= 0) { 147772c33676SMaxim Ag perror(attrpath); 147872c33676SMaxim Ag BIO_printf(bio_err, "unable to open '%s'\n", attrpath); 1479f5b1c8a1SJohn Marino goto err; 1480f5b1c8a1SJohn Marino } 1481f5b1c8a1SJohn Marino BIO_printf(out, "unique_subject = %s\n", 1482f5b1c8a1SJohn Marino db->attributes.unique_subject ? "yes" : "no"); 1483f5b1c8a1SJohn Marino BIO_free(out); 1484f5b1c8a1SJohn Marino 1485f5b1c8a1SJohn Marino return 1; 1486f5b1c8a1SJohn Marino 1487f5b1c8a1SJohn Marino err: 1488f5b1c8a1SJohn Marino return 0; 1489f5b1c8a1SJohn Marino } 1490f5b1c8a1SJohn Marino 1491f5b1c8a1SJohn Marino int 1492f5b1c8a1SJohn Marino rotate_index(const char *dbfile, const char *new_suffix, const char *old_suffix) 1493f5b1c8a1SJohn Marino { 149472c33676SMaxim Ag char attrpath[PATH_MAX], nattrpath[PATH_MAX], oattrpath[PATH_MAX]; 149572c33676SMaxim Ag char dbpath[PATH_MAX], odbpath[PATH_MAX]; 1496f5b1c8a1SJohn Marino 149772c33676SMaxim Ag if (snprintf(attrpath, sizeof attrpath, "%s.attr", 149872c33676SMaxim Ag dbfile) >= sizeof attrpath) { 1499f5b1c8a1SJohn Marino BIO_printf(bio_err, "file name too long\n"); 1500f5b1c8a1SJohn Marino goto err; 1501f5b1c8a1SJohn Marino } 150272c33676SMaxim Ag if (snprintf(nattrpath, sizeof nattrpath, "%s.attr.%s", 150372c33676SMaxim Ag dbfile, new_suffix) >= sizeof nattrpath) { 150472c33676SMaxim Ag BIO_printf(bio_err, "file name too long\n"); 150572c33676SMaxim Ag goto err; 150672c33676SMaxim Ag } 150772c33676SMaxim Ag if (snprintf(oattrpath, sizeof oattrpath, "%s.attr.%s", 150872c33676SMaxim Ag dbfile, old_suffix) >= sizeof oattrpath) { 150972c33676SMaxim Ag BIO_printf(bio_err, "file name too long\n"); 151072c33676SMaxim Ag goto err; 151172c33676SMaxim Ag } 151272c33676SMaxim Ag if (snprintf(dbpath, sizeof dbpath, "%s.%s", 151372c33676SMaxim Ag dbfile, new_suffix) >= sizeof dbpath) { 151472c33676SMaxim Ag BIO_printf(bio_err, "file name too long\n"); 151572c33676SMaxim Ag goto err; 151672c33676SMaxim Ag } 151772c33676SMaxim Ag if (snprintf(odbpath, sizeof odbpath, "%s.%s", 151872c33676SMaxim Ag dbfile, old_suffix) >= sizeof odbpath) { 151972c33676SMaxim Ag BIO_printf(bio_err, "file name too long\n"); 152072c33676SMaxim Ag goto err; 152172c33676SMaxim Ag } 1522f5b1c8a1SJohn Marino 1523cca6fc52SDaniel Fojt if (rename(dbfile, odbpath) == -1 && errno != ENOENT && errno != ENOTDIR) { 1524f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to rename %s to %s\n", 152572c33676SMaxim Ag dbfile, odbpath); 1526f5b1c8a1SJohn Marino perror("reason"); 1527f5b1c8a1SJohn Marino goto err; 1528f5b1c8a1SJohn Marino } 1529f5b1c8a1SJohn Marino 1530cca6fc52SDaniel Fojt if (rename(dbpath, dbfile) == -1) { 1531f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to rename %s to %s\n", 153272c33676SMaxim Ag dbpath, dbfile); 1533f5b1c8a1SJohn Marino perror("reason"); 1534cca6fc52SDaniel Fojt if (rename(odbpath, dbfile) == -1) { 1535f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to rename %s to %s\n", 153672c33676SMaxim Ag odbpath, dbfile); 1537f5b1c8a1SJohn Marino perror("reason"); 1538f5b1c8a1SJohn Marino } 1539f5b1c8a1SJohn Marino goto err; 1540f5b1c8a1SJohn Marino } 1541f5b1c8a1SJohn Marino 1542cca6fc52SDaniel Fojt if (rename(attrpath, oattrpath) == -1 && errno != ENOENT && errno != ENOTDIR) { 1543f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to rename %s to %s\n", 154472c33676SMaxim Ag attrpath, oattrpath); 1545f5b1c8a1SJohn Marino perror("reason"); 1546cca6fc52SDaniel Fojt if (rename(dbfile, dbpath) == -1) { 1547f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to rename %s to %s\n", 154872c33676SMaxim Ag dbfile, dbpath); 1549f5b1c8a1SJohn Marino perror("reason"); 1550f5b1c8a1SJohn Marino } 1551cca6fc52SDaniel Fojt if (rename(odbpath, dbfile) == -1) { 1552f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to rename %s to %s\n", 155372c33676SMaxim Ag odbpath, dbfile); 1554f5b1c8a1SJohn Marino perror("reason"); 1555f5b1c8a1SJohn Marino } 1556f5b1c8a1SJohn Marino goto err; 1557f5b1c8a1SJohn Marino } 1558f5b1c8a1SJohn Marino 1559cca6fc52SDaniel Fojt if (rename(nattrpath, attrpath) == -1) { 1560f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to rename %s to %s\n", 156172c33676SMaxim Ag nattrpath, attrpath); 1562f5b1c8a1SJohn Marino perror("reason"); 1563cca6fc52SDaniel Fojt if (rename(oattrpath, attrpath) == -1) { 1564f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to rename %s to %s\n", 156572c33676SMaxim Ag oattrpath, attrpath); 1566f5b1c8a1SJohn Marino perror("reason"); 1567f5b1c8a1SJohn Marino } 1568cca6fc52SDaniel Fojt if (rename(dbfile, dbpath) == -1) { 1569f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to rename %s to %s\n", 157072c33676SMaxim Ag dbfile, dbpath); 1571f5b1c8a1SJohn Marino perror("reason"); 1572f5b1c8a1SJohn Marino } 1573cca6fc52SDaniel Fojt if (rename(odbpath, dbfile) == -1) { 1574f5b1c8a1SJohn Marino BIO_printf(bio_err, "unable to rename %s to %s\n", 157572c33676SMaxim Ag odbpath, dbfile); 1576f5b1c8a1SJohn Marino perror("reason"); 1577f5b1c8a1SJohn Marino } 1578f5b1c8a1SJohn Marino goto err; 1579f5b1c8a1SJohn Marino } 1580f5b1c8a1SJohn Marino return 1; 1581f5b1c8a1SJohn Marino 1582f5b1c8a1SJohn Marino err: 1583f5b1c8a1SJohn Marino return 0; 1584f5b1c8a1SJohn Marino } 1585f5b1c8a1SJohn Marino 1586f5b1c8a1SJohn Marino void 1587f5b1c8a1SJohn Marino free_index(CA_DB *db) 1588f5b1c8a1SJohn Marino { 1589f5b1c8a1SJohn Marino if (db) { 1590f5b1c8a1SJohn Marino TXT_DB_free(db->db); 1591f5b1c8a1SJohn Marino free(db); 1592f5b1c8a1SJohn Marino } 1593f5b1c8a1SJohn Marino } 1594f5b1c8a1SJohn Marino 1595f5b1c8a1SJohn Marino int 1596f5b1c8a1SJohn Marino parse_yesno(const char *str, int def) 1597f5b1c8a1SJohn Marino { 1598f5b1c8a1SJohn Marino int ret = def; 1599f5b1c8a1SJohn Marino 1600f5b1c8a1SJohn Marino if (str) { 1601f5b1c8a1SJohn Marino switch (*str) { 1602f5b1c8a1SJohn Marino case 'f': /* false */ 1603f5b1c8a1SJohn Marino case 'F': /* FALSE */ 1604f5b1c8a1SJohn Marino case 'n': /* no */ 1605f5b1c8a1SJohn Marino case 'N': /* NO */ 1606f5b1c8a1SJohn Marino case '0': /* 0 */ 1607f5b1c8a1SJohn Marino ret = 0; 1608f5b1c8a1SJohn Marino break; 1609f5b1c8a1SJohn Marino case 't': /* true */ 1610f5b1c8a1SJohn Marino case 'T': /* TRUE */ 1611f5b1c8a1SJohn Marino case 'y': /* yes */ 1612f5b1c8a1SJohn Marino case 'Y': /* YES */ 1613f5b1c8a1SJohn Marino case '1': /* 1 */ 1614f5b1c8a1SJohn Marino ret = 1; 1615f5b1c8a1SJohn Marino break; 1616f5b1c8a1SJohn Marino default: 1617f5b1c8a1SJohn Marino ret = def; 1618f5b1c8a1SJohn Marino break; 1619f5b1c8a1SJohn Marino } 1620f5b1c8a1SJohn Marino } 1621f5b1c8a1SJohn Marino return ret; 1622f5b1c8a1SJohn Marino } 1623f5b1c8a1SJohn Marino 1624f5b1c8a1SJohn Marino /* 1625f5b1c8a1SJohn Marino * subject is expected to be in the format /type0=value0/type1=value1/type2=... 1626f5b1c8a1SJohn Marino * where characters may be escaped by \ 1627f5b1c8a1SJohn Marino */ 1628f5b1c8a1SJohn Marino X509_NAME * 1629f5b1c8a1SJohn Marino parse_name(char *subject, long chtype, int multirdn) 1630f5b1c8a1SJohn Marino { 1631f5b1c8a1SJohn Marino X509_NAME *name = NULL; 1632f5b1c8a1SJohn Marino size_t buflen, max_ne; 1633f5b1c8a1SJohn Marino char **ne_types, **ne_values; 1634f5b1c8a1SJohn Marino char *buf, *bp, *sp; 1635f5b1c8a1SJohn Marino int i, nid, ne_num = 0; 1636f5b1c8a1SJohn Marino int *mval; 1637f5b1c8a1SJohn Marino 1638f5b1c8a1SJohn Marino /* 1639f5b1c8a1SJohn Marino * Buffer to copy the types and values into. Due to escaping the 1640f5b1c8a1SJohn Marino * copy can only become shorter. 1641f5b1c8a1SJohn Marino */ 1642f5b1c8a1SJohn Marino buflen = strlen(subject) + 1; 1643f5b1c8a1SJohn Marino buf = malloc(buflen); 1644f5b1c8a1SJohn Marino 1645f5b1c8a1SJohn Marino /* Maximum number of name elements. */ 1646f5b1c8a1SJohn Marino max_ne = buflen / 2 + 1; 1647f5b1c8a1SJohn Marino ne_types = reallocarray(NULL, max_ne, sizeof(char *)); 1648f5b1c8a1SJohn Marino ne_values = reallocarray(NULL, max_ne, sizeof(char *)); 1649f5b1c8a1SJohn Marino mval = reallocarray(NULL, max_ne, sizeof(int)); 1650f5b1c8a1SJohn Marino 1651f5b1c8a1SJohn Marino if (buf == NULL || ne_types == NULL || ne_values == NULL || 1652f5b1c8a1SJohn Marino mval == NULL) { 1653f5b1c8a1SJohn Marino BIO_printf(bio_err, "malloc error\n"); 1654f5b1c8a1SJohn Marino goto error; 1655f5b1c8a1SJohn Marino } 1656f5b1c8a1SJohn Marino 1657f5b1c8a1SJohn Marino bp = buf; 1658f5b1c8a1SJohn Marino sp = subject; 1659f5b1c8a1SJohn Marino 1660f5b1c8a1SJohn Marino if (*subject != '/') { 1661f5b1c8a1SJohn Marino BIO_printf(bio_err, "Subject does not start with '/'.\n"); 1662f5b1c8a1SJohn Marino goto error; 1663f5b1c8a1SJohn Marino } 1664f5b1c8a1SJohn Marino 1665f5b1c8a1SJohn Marino /* Skip leading '/'. */ 1666f5b1c8a1SJohn Marino sp++; 1667f5b1c8a1SJohn Marino 1668f5b1c8a1SJohn Marino /* No multivalued RDN by default. */ 1669f5b1c8a1SJohn Marino mval[ne_num] = 0; 1670f5b1c8a1SJohn Marino 1671f5b1c8a1SJohn Marino while (*sp) { 1672f5b1c8a1SJohn Marino /* Collect type. */ 1673f5b1c8a1SJohn Marino ne_types[ne_num] = bp; 1674f5b1c8a1SJohn Marino while (*sp) { 1675f5b1c8a1SJohn Marino /* is there anything to escape in the type...? */ 1676f5b1c8a1SJohn Marino if (*sp == '\\') { 1677f5b1c8a1SJohn Marino if (*++sp) 1678f5b1c8a1SJohn Marino *bp++ = *sp++; 1679f5b1c8a1SJohn Marino else { 1680f5b1c8a1SJohn Marino BIO_printf(bio_err, "escape character " 1681f5b1c8a1SJohn Marino "at end of string\n"); 1682f5b1c8a1SJohn Marino goto error; 1683f5b1c8a1SJohn Marino } 1684f5b1c8a1SJohn Marino } else if (*sp == '=') { 1685f5b1c8a1SJohn Marino sp++; 1686f5b1c8a1SJohn Marino *bp++ = '\0'; 1687f5b1c8a1SJohn Marino break; 1688f5b1c8a1SJohn Marino } else 1689f5b1c8a1SJohn Marino *bp++ = *sp++; 1690f5b1c8a1SJohn Marino } 1691f5b1c8a1SJohn Marino if (!*sp) { 1692f5b1c8a1SJohn Marino BIO_printf(bio_err, "end of string encountered while " 1693f5b1c8a1SJohn Marino "processing type of subject name element #%d\n", 1694f5b1c8a1SJohn Marino ne_num); 1695f5b1c8a1SJohn Marino goto error; 1696f5b1c8a1SJohn Marino } 1697f5b1c8a1SJohn Marino ne_values[ne_num] = bp; 1698f5b1c8a1SJohn Marino while (*sp) { 1699f5b1c8a1SJohn Marino if (*sp == '\\') { 1700f5b1c8a1SJohn Marino if (*++sp) 1701f5b1c8a1SJohn Marino *bp++ = *sp++; 1702f5b1c8a1SJohn Marino else { 1703f5b1c8a1SJohn Marino BIO_printf(bio_err, "escape character " 1704f5b1c8a1SJohn Marino "at end of string\n"); 1705f5b1c8a1SJohn Marino goto error; 1706f5b1c8a1SJohn Marino } 1707f5b1c8a1SJohn Marino } else if (*sp == '/') { 1708f5b1c8a1SJohn Marino sp++; 1709f5b1c8a1SJohn Marino /* no multivalued RDN by default */ 1710f5b1c8a1SJohn Marino mval[ne_num + 1] = 0; 1711f5b1c8a1SJohn Marino break; 1712f5b1c8a1SJohn Marino } else if (*sp == '+' && multirdn) { 1713f5b1c8a1SJohn Marino /* a not escaped + signals a multivalued RDN */ 1714f5b1c8a1SJohn Marino sp++; 1715f5b1c8a1SJohn Marino mval[ne_num + 1] = -1; 1716f5b1c8a1SJohn Marino break; 1717f5b1c8a1SJohn Marino } else 1718f5b1c8a1SJohn Marino *bp++ = *sp++; 1719f5b1c8a1SJohn Marino } 1720f5b1c8a1SJohn Marino *bp++ = '\0'; 1721f5b1c8a1SJohn Marino ne_num++; 1722f5b1c8a1SJohn Marino } 1723f5b1c8a1SJohn Marino 1724f5b1c8a1SJohn Marino if ((name = X509_NAME_new()) == NULL) 1725f5b1c8a1SJohn Marino goto error; 1726f5b1c8a1SJohn Marino 1727f5b1c8a1SJohn Marino for (i = 0; i < ne_num; i++) { 1728f5b1c8a1SJohn Marino if ((nid = OBJ_txt2nid(ne_types[i])) == NID_undef) { 1729f5b1c8a1SJohn Marino BIO_printf(bio_err, 1730f5b1c8a1SJohn Marino "Subject Attribute %s has no known NID, skipped\n", 1731f5b1c8a1SJohn Marino ne_types[i]); 1732f5b1c8a1SJohn Marino continue; 1733f5b1c8a1SJohn Marino } 1734f5b1c8a1SJohn Marino if (!*ne_values[i]) { 1735f5b1c8a1SJohn Marino BIO_printf(bio_err, "No value provided for Subject " 1736f5b1c8a1SJohn Marino "Attribute %s, skipped\n", ne_types[i]); 1737f5b1c8a1SJohn Marino continue; 1738f5b1c8a1SJohn Marino } 1739f5b1c8a1SJohn Marino if (!X509_NAME_add_entry_by_NID(name, nid, chtype, 1740f5b1c8a1SJohn Marino (unsigned char *) ne_values[i], -1, -1, mval[i])) 1741f5b1c8a1SJohn Marino goto error; 1742f5b1c8a1SJohn Marino } 1743f5b1c8a1SJohn Marino goto done; 1744f5b1c8a1SJohn Marino 1745f5b1c8a1SJohn Marino error: 1746f5b1c8a1SJohn Marino X509_NAME_free(name); 1747f5b1c8a1SJohn Marino name = NULL; 1748f5b1c8a1SJohn Marino 1749f5b1c8a1SJohn Marino done: 1750f5b1c8a1SJohn Marino free(ne_values); 1751f5b1c8a1SJohn Marino free(ne_types); 1752f5b1c8a1SJohn Marino free(mval); 1753f5b1c8a1SJohn Marino free(buf); 1754f5b1c8a1SJohn Marino 1755f5b1c8a1SJohn Marino return name; 1756f5b1c8a1SJohn Marino } 1757f5b1c8a1SJohn Marino 1758f5b1c8a1SJohn Marino int 1759f5b1c8a1SJohn Marino args_verify(char ***pargs, int *pargc, int *badarg, BIO *err, 1760f5b1c8a1SJohn Marino X509_VERIFY_PARAM **pm) 1761f5b1c8a1SJohn Marino { 1762f5b1c8a1SJohn Marino ASN1_OBJECT *otmp = NULL; 1763f5b1c8a1SJohn Marino unsigned long flags = 0; 1764f5b1c8a1SJohn Marino int i; 1765f5b1c8a1SJohn Marino int purpose = 0, depth = -1; 1766f5b1c8a1SJohn Marino char **oldargs = *pargs; 1767f5b1c8a1SJohn Marino char *arg = **pargs, *argn = (*pargs)[1]; 1768f5b1c8a1SJohn Marino time_t at_time = 0; 1769f5b1c8a1SJohn Marino const char *errstr = NULL; 1770f5b1c8a1SJohn Marino 1771f5b1c8a1SJohn Marino if (!strcmp(arg, "-policy")) { 1772f5b1c8a1SJohn Marino if (!argn) 1773f5b1c8a1SJohn Marino *badarg = 1; 1774f5b1c8a1SJohn Marino else { 1775f5b1c8a1SJohn Marino otmp = OBJ_txt2obj(argn, 0); 1776f5b1c8a1SJohn Marino if (!otmp) { 1777f5b1c8a1SJohn Marino BIO_printf(err, "Invalid Policy \"%s\"\n", 1778f5b1c8a1SJohn Marino argn); 1779f5b1c8a1SJohn Marino *badarg = 1; 1780f5b1c8a1SJohn Marino } 1781f5b1c8a1SJohn Marino } 1782f5b1c8a1SJohn Marino (*pargs)++; 1783f5b1c8a1SJohn Marino } else if (strcmp(arg, "-purpose") == 0) { 1784f5b1c8a1SJohn Marino X509_PURPOSE *xptmp; 1785f5b1c8a1SJohn Marino if (!argn) 1786f5b1c8a1SJohn Marino *badarg = 1; 1787f5b1c8a1SJohn Marino else { 1788f5b1c8a1SJohn Marino i = X509_PURPOSE_get_by_sname(argn); 1789f5b1c8a1SJohn Marino if (i < 0) { 1790f5b1c8a1SJohn Marino BIO_printf(err, "unrecognized purpose\n"); 1791f5b1c8a1SJohn Marino *badarg = 1; 1792f5b1c8a1SJohn Marino } else { 1793f5b1c8a1SJohn Marino xptmp = X509_PURPOSE_get0(i); 1794f5b1c8a1SJohn Marino purpose = X509_PURPOSE_get_id(xptmp); 1795f5b1c8a1SJohn Marino } 1796f5b1c8a1SJohn Marino } 1797f5b1c8a1SJohn Marino (*pargs)++; 1798f5b1c8a1SJohn Marino } else if (strcmp(arg, "-verify_depth") == 0) { 1799f5b1c8a1SJohn Marino if (!argn) 1800f5b1c8a1SJohn Marino *badarg = 1; 1801f5b1c8a1SJohn Marino else { 1802f5b1c8a1SJohn Marino depth = strtonum(argn, 1, INT_MAX, &errstr); 1803f5b1c8a1SJohn Marino if (errstr) { 1804f5b1c8a1SJohn Marino BIO_printf(err, "invalid depth %s: %s\n", 1805f5b1c8a1SJohn Marino argn, errstr); 1806f5b1c8a1SJohn Marino *badarg = 1; 1807f5b1c8a1SJohn Marino } 1808f5b1c8a1SJohn Marino } 1809f5b1c8a1SJohn Marino (*pargs)++; 1810f5b1c8a1SJohn Marino } else if (strcmp(arg, "-attime") == 0) { 1811f5b1c8a1SJohn Marino if (!argn) 1812f5b1c8a1SJohn Marino *badarg = 1; 1813f5b1c8a1SJohn Marino else { 1814f5b1c8a1SJohn Marino long long timestamp; 1815f5b1c8a1SJohn Marino /* 1816f5b1c8a1SJohn Marino * interpret the -attime argument as seconds since 1817f5b1c8a1SJohn Marino * Epoch 1818f5b1c8a1SJohn Marino */ 1819f5b1c8a1SJohn Marino if (sscanf(argn, "%lli", ×tamp) != 1) { 1820f5b1c8a1SJohn Marino BIO_printf(bio_err, 1821f5b1c8a1SJohn Marino "Error parsing timestamp %s\n", 1822f5b1c8a1SJohn Marino argn); 1823f5b1c8a1SJohn Marino *badarg = 1; 1824f5b1c8a1SJohn Marino } 1825f5b1c8a1SJohn Marino /* XXX 2038 truncation */ 1826f5b1c8a1SJohn Marino at_time = (time_t) timestamp; 1827f5b1c8a1SJohn Marino } 1828f5b1c8a1SJohn Marino (*pargs)++; 1829f5b1c8a1SJohn Marino } else if (!strcmp(arg, "-ignore_critical")) 1830f5b1c8a1SJohn Marino flags |= X509_V_FLAG_IGNORE_CRITICAL; 1831f5b1c8a1SJohn Marino else if (!strcmp(arg, "-issuer_checks")) 1832f5b1c8a1SJohn Marino flags |= X509_V_FLAG_CB_ISSUER_CHECK; 1833f5b1c8a1SJohn Marino else if (!strcmp(arg, "-crl_check")) 1834f5b1c8a1SJohn Marino flags |= X509_V_FLAG_CRL_CHECK; 1835f5b1c8a1SJohn Marino else if (!strcmp(arg, "-crl_check_all")) 1836f5b1c8a1SJohn Marino flags |= X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL; 1837f5b1c8a1SJohn Marino else if (!strcmp(arg, "-policy_check")) 1838f5b1c8a1SJohn Marino flags |= X509_V_FLAG_POLICY_CHECK; 1839f5b1c8a1SJohn Marino else if (!strcmp(arg, "-explicit_policy")) 1840f5b1c8a1SJohn Marino flags |= X509_V_FLAG_EXPLICIT_POLICY; 1841*de0e0e4dSAntonio Huete Jimenez else if (!strcmp(arg, "-legacy_verify")) 1842*de0e0e4dSAntonio Huete Jimenez flags |= X509_V_FLAG_LEGACY_VERIFY; 1843f5b1c8a1SJohn Marino else if (!strcmp(arg, "-inhibit_any")) 1844f5b1c8a1SJohn Marino flags |= X509_V_FLAG_INHIBIT_ANY; 1845f5b1c8a1SJohn Marino else if (!strcmp(arg, "-inhibit_map")) 1846f5b1c8a1SJohn Marino flags |= X509_V_FLAG_INHIBIT_MAP; 1847f5b1c8a1SJohn Marino else if (!strcmp(arg, "-x509_strict")) 1848f5b1c8a1SJohn Marino flags |= X509_V_FLAG_X509_STRICT; 1849f5b1c8a1SJohn Marino else if (!strcmp(arg, "-extended_crl")) 1850f5b1c8a1SJohn Marino flags |= X509_V_FLAG_EXTENDED_CRL_SUPPORT; 1851f5b1c8a1SJohn Marino else if (!strcmp(arg, "-use_deltas")) 1852f5b1c8a1SJohn Marino flags |= X509_V_FLAG_USE_DELTAS; 1853f5b1c8a1SJohn Marino else if (!strcmp(arg, "-policy_print")) 1854f5b1c8a1SJohn Marino flags |= X509_V_FLAG_NOTIFY_POLICY; 1855f5b1c8a1SJohn Marino else if (!strcmp(arg, "-check_ss_sig")) 1856f5b1c8a1SJohn Marino flags |= X509_V_FLAG_CHECK_SS_SIGNATURE; 1857f5b1c8a1SJohn Marino else 1858f5b1c8a1SJohn Marino return 0; 1859f5b1c8a1SJohn Marino 1860f5b1c8a1SJohn Marino if (*badarg) { 1861f5b1c8a1SJohn Marino X509_VERIFY_PARAM_free(*pm); 1862f5b1c8a1SJohn Marino *pm = NULL; 1863f5b1c8a1SJohn Marino goto end; 1864f5b1c8a1SJohn Marino } 1865f5b1c8a1SJohn Marino if (!*pm && !(*pm = X509_VERIFY_PARAM_new())) { 1866f5b1c8a1SJohn Marino *badarg = 1; 1867f5b1c8a1SJohn Marino goto end; 1868f5b1c8a1SJohn Marino } 1869f5b1c8a1SJohn Marino if (otmp) { 1870f5b1c8a1SJohn Marino X509_VERIFY_PARAM_add0_policy(*pm, otmp); 1871f5b1c8a1SJohn Marino otmp = NULL; 1872f5b1c8a1SJohn Marino } 1873f5b1c8a1SJohn Marino if (flags) 1874f5b1c8a1SJohn Marino X509_VERIFY_PARAM_set_flags(*pm, flags); 1875f5b1c8a1SJohn Marino 1876f5b1c8a1SJohn Marino if (purpose) 1877f5b1c8a1SJohn Marino X509_VERIFY_PARAM_set_purpose(*pm, purpose); 1878f5b1c8a1SJohn Marino 1879f5b1c8a1SJohn Marino if (depth >= 0) 1880f5b1c8a1SJohn Marino X509_VERIFY_PARAM_set_depth(*pm, depth); 1881f5b1c8a1SJohn Marino 1882f5b1c8a1SJohn Marino if (at_time) 1883f5b1c8a1SJohn Marino X509_VERIFY_PARAM_set_time(*pm, at_time); 1884f5b1c8a1SJohn Marino 1885f5b1c8a1SJohn Marino end: 1886f5b1c8a1SJohn Marino (*pargs)++; 1887f5b1c8a1SJohn Marino 1888f5b1c8a1SJohn Marino if (pargc) 1889f5b1c8a1SJohn Marino *pargc -= *pargs - oldargs; 1890f5b1c8a1SJohn Marino 1891f5b1c8a1SJohn Marino ASN1_OBJECT_free(otmp); 1892f5b1c8a1SJohn Marino return 1; 1893f5b1c8a1SJohn Marino } 1894f5b1c8a1SJohn Marino 1895f5b1c8a1SJohn Marino /* Read whole contents of a BIO into an allocated memory buffer and 1896f5b1c8a1SJohn Marino * return it. 1897f5b1c8a1SJohn Marino */ 1898f5b1c8a1SJohn Marino 1899f5b1c8a1SJohn Marino int 1900f5b1c8a1SJohn Marino bio_to_mem(unsigned char **out, int maxlen, BIO *in) 1901f5b1c8a1SJohn Marino { 1902f5b1c8a1SJohn Marino BIO *mem; 1903f5b1c8a1SJohn Marino int len, ret; 1904f5b1c8a1SJohn Marino unsigned char tbuf[1024]; 1905f5b1c8a1SJohn Marino 1906f5b1c8a1SJohn Marino mem = BIO_new(BIO_s_mem()); 1907f5b1c8a1SJohn Marino if (!mem) 1908f5b1c8a1SJohn Marino return -1; 1909f5b1c8a1SJohn Marino for (;;) { 1910f5b1c8a1SJohn Marino if ((maxlen != -1) && maxlen < 1024) 1911f5b1c8a1SJohn Marino len = maxlen; 1912f5b1c8a1SJohn Marino else 1913f5b1c8a1SJohn Marino len = 1024; 1914f5b1c8a1SJohn Marino len = BIO_read(in, tbuf, len); 1915f5b1c8a1SJohn Marino if (len <= 0) 1916f5b1c8a1SJohn Marino break; 1917f5b1c8a1SJohn Marino if (BIO_write(mem, tbuf, len) != len) { 1918f5b1c8a1SJohn Marino BIO_free(mem); 1919f5b1c8a1SJohn Marino return -1; 1920f5b1c8a1SJohn Marino } 1921f5b1c8a1SJohn Marino maxlen -= len; 1922f5b1c8a1SJohn Marino 1923f5b1c8a1SJohn Marino if (maxlen == 0) 1924f5b1c8a1SJohn Marino break; 1925f5b1c8a1SJohn Marino } 1926f5b1c8a1SJohn Marino ret = BIO_get_mem_data(mem, (char **) out); 1927f5b1c8a1SJohn Marino BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY); 1928f5b1c8a1SJohn Marino BIO_free(mem); 1929f5b1c8a1SJohn Marino return ret; 1930f5b1c8a1SJohn Marino } 1931f5b1c8a1SJohn Marino 1932f5b1c8a1SJohn Marino int 1933f5b1c8a1SJohn Marino pkey_ctrl_string(EVP_PKEY_CTX *ctx, char *value) 1934f5b1c8a1SJohn Marino { 1935f5b1c8a1SJohn Marino int rv; 1936f5b1c8a1SJohn Marino char *stmp, *vtmp = NULL; 1937f5b1c8a1SJohn Marino 1938f5b1c8a1SJohn Marino if (value == NULL) 1939f5b1c8a1SJohn Marino return -1; 1940f5b1c8a1SJohn Marino stmp = strdup(value); 1941f5b1c8a1SJohn Marino if (!stmp) 1942f5b1c8a1SJohn Marino return -1; 1943f5b1c8a1SJohn Marino vtmp = strchr(stmp, ':'); 1944f5b1c8a1SJohn Marino if (vtmp) { 1945f5b1c8a1SJohn Marino *vtmp = 0; 1946f5b1c8a1SJohn Marino vtmp++; 1947f5b1c8a1SJohn Marino } 1948f5b1c8a1SJohn Marino rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp); 1949f5b1c8a1SJohn Marino free(stmp); 1950f5b1c8a1SJohn Marino 1951f5b1c8a1SJohn Marino return rv; 1952f5b1c8a1SJohn Marino } 1953f5b1c8a1SJohn Marino 1954f5b1c8a1SJohn Marino static void 1955f5b1c8a1SJohn Marino nodes_print(BIO *out, const char *name, STACK_OF(X509_POLICY_NODE) *nodes) 1956f5b1c8a1SJohn Marino { 1957f5b1c8a1SJohn Marino X509_POLICY_NODE *node; 1958f5b1c8a1SJohn Marino int i; 1959f5b1c8a1SJohn Marino 1960f5b1c8a1SJohn Marino BIO_printf(out, "%s Policies:", name); 1961f5b1c8a1SJohn Marino if (nodes) { 1962f5b1c8a1SJohn Marino BIO_puts(out, "\n"); 1963f5b1c8a1SJohn Marino for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) { 1964f5b1c8a1SJohn Marino node = sk_X509_POLICY_NODE_value(nodes, i); 1965f5b1c8a1SJohn Marino X509_POLICY_NODE_print(out, node, 2); 1966f5b1c8a1SJohn Marino } 1967f5b1c8a1SJohn Marino } else 1968f5b1c8a1SJohn Marino BIO_puts(out, " <empty>\n"); 1969f5b1c8a1SJohn Marino } 1970f5b1c8a1SJohn Marino 1971f5b1c8a1SJohn Marino void 1972f5b1c8a1SJohn Marino policies_print(BIO *out, X509_STORE_CTX *ctx) 1973f5b1c8a1SJohn Marino { 1974f5b1c8a1SJohn Marino X509_POLICY_TREE *tree; 1975f5b1c8a1SJohn Marino int explicit_policy; 1976f5b1c8a1SJohn Marino int free_out = 0; 1977f5b1c8a1SJohn Marino 1978f5b1c8a1SJohn Marino if (out == NULL) { 1979f5b1c8a1SJohn Marino out = BIO_new_fp(stderr, BIO_NOCLOSE); 1980f5b1c8a1SJohn Marino free_out = 1; 1981f5b1c8a1SJohn Marino } 1982f5b1c8a1SJohn Marino tree = X509_STORE_CTX_get0_policy_tree(ctx); 1983f5b1c8a1SJohn Marino explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx); 1984f5b1c8a1SJohn Marino 1985f5b1c8a1SJohn Marino BIO_printf(out, "Require explicit Policy: %s\n", 1986f5b1c8a1SJohn Marino explicit_policy ? "True" : "False"); 1987f5b1c8a1SJohn Marino 1988f5b1c8a1SJohn Marino nodes_print(out, "Authority", X509_policy_tree_get0_policies(tree)); 1989f5b1c8a1SJohn Marino nodes_print(out, "User", X509_policy_tree_get0_user_policies(tree)); 199072c33676SMaxim Ag 1991f5b1c8a1SJohn Marino if (free_out) 1992f5b1c8a1SJohn Marino BIO_free(out); 1993f5b1c8a1SJohn Marino } 1994f5b1c8a1SJohn Marino 199572c33676SMaxim Ag /* 199672c33676SMaxim Ag * next_protos_parse parses a comma separated list of strings into a string 1997f5b1c8a1SJohn Marino * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. 1998f5b1c8a1SJohn Marino * outlen: (output) set to the length of the resulting buffer on success. 1999f5b1c8a1SJohn Marino * err: (maybe NULL) on failure, an error message line is written to this BIO. 2000f5b1c8a1SJohn Marino * in: a NUL termianted string like "abc,def,ghi" 2001f5b1c8a1SJohn Marino * 2002f5b1c8a1SJohn Marino * returns: a malloced buffer or NULL on failure. 2003f5b1c8a1SJohn Marino */ 2004f5b1c8a1SJohn Marino unsigned char * 2005f5b1c8a1SJohn Marino next_protos_parse(unsigned short *outlen, const char *in) 2006f5b1c8a1SJohn Marino { 2007f5b1c8a1SJohn Marino size_t len; 2008f5b1c8a1SJohn Marino unsigned char *out; 2009f5b1c8a1SJohn Marino size_t i, start = 0; 2010f5b1c8a1SJohn Marino 2011f5b1c8a1SJohn Marino len = strlen(in); 2012f5b1c8a1SJohn Marino if (len >= 65535) 2013f5b1c8a1SJohn Marino return NULL; 2014f5b1c8a1SJohn Marino 2015f5b1c8a1SJohn Marino out = malloc(strlen(in) + 1); 2016f5b1c8a1SJohn Marino if (!out) 2017f5b1c8a1SJohn Marino return NULL; 2018f5b1c8a1SJohn Marino 2019f5b1c8a1SJohn Marino for (i = 0; i <= len; ++i) { 2020f5b1c8a1SJohn Marino if (i == len || in[i] == ',') { 2021f5b1c8a1SJohn Marino if (i - start > 255) { 2022f5b1c8a1SJohn Marino free(out); 2023f5b1c8a1SJohn Marino return NULL; 2024f5b1c8a1SJohn Marino } 2025f5b1c8a1SJohn Marino out[start] = i - start; 2026f5b1c8a1SJohn Marino start = i + 1; 2027f5b1c8a1SJohn Marino } else 2028f5b1c8a1SJohn Marino out[i + 1] = in[i]; 2029f5b1c8a1SJohn Marino } 2030f5b1c8a1SJohn Marino 2031f5b1c8a1SJohn Marino *outlen = len + 1; 2032f5b1c8a1SJohn Marino return out; 2033f5b1c8a1SJohn Marino } 2034f5b1c8a1SJohn Marino 2035f5b1c8a1SJohn Marino int 2036f5b1c8a1SJohn Marino app_isdir(const char *name) 2037f5b1c8a1SJohn Marino { 2038f5b1c8a1SJohn Marino struct stat st; 2039f5b1c8a1SJohn Marino 2040f5b1c8a1SJohn Marino if (stat(name, &st) == 0) 2041f5b1c8a1SJohn Marino return S_ISDIR(st.st_mode); 2042f5b1c8a1SJohn Marino return -1; 2043f5b1c8a1SJohn Marino } 2044f5b1c8a1SJohn Marino 2045f5b1c8a1SJohn Marino #define OPTION_WIDTH 18 2046f5b1c8a1SJohn Marino 2047f5b1c8a1SJohn Marino void 2048cca6fc52SDaniel Fojt options_usage(const struct option *opts) 2049f5b1c8a1SJohn Marino { 2050f5b1c8a1SJohn Marino const char *p, *q; 2051f5b1c8a1SJohn Marino char optstr[32]; 2052f5b1c8a1SJohn Marino int i; 2053f5b1c8a1SJohn Marino 2054f5b1c8a1SJohn Marino for (i = 0; opts[i].name != NULL; i++) { 2055f5b1c8a1SJohn Marino if (opts[i].desc == NULL) 2056f5b1c8a1SJohn Marino continue; 2057f5b1c8a1SJohn Marino 2058f5b1c8a1SJohn Marino snprintf(optstr, sizeof(optstr), "-%s %s", opts[i].name, 2059f5b1c8a1SJohn Marino (opts[i].argname != NULL) ? opts[i].argname : ""); 2060f5b1c8a1SJohn Marino fprintf(stderr, " %-*s", OPTION_WIDTH, optstr); 2061f5b1c8a1SJohn Marino if (strlen(optstr) > OPTION_WIDTH) 2062f5b1c8a1SJohn Marino fprintf(stderr, "\n %-*s", OPTION_WIDTH, ""); 2063f5b1c8a1SJohn Marino 2064f5b1c8a1SJohn Marino p = opts[i].desc; 2065f5b1c8a1SJohn Marino while ((q = strchr(p, '\n')) != NULL) { 2066f5b1c8a1SJohn Marino fprintf(stderr, " %.*s", (int)(q - p), p); 2067f5b1c8a1SJohn Marino fprintf(stderr, "\n %-*s", OPTION_WIDTH, ""); 2068f5b1c8a1SJohn Marino p = q + 1; 2069f5b1c8a1SJohn Marino } 2070f5b1c8a1SJohn Marino fprintf(stderr, " %s\n", p); 2071f5b1c8a1SJohn Marino } 2072f5b1c8a1SJohn Marino } 2073f5b1c8a1SJohn Marino 2074f5b1c8a1SJohn Marino int 2075cca6fc52SDaniel Fojt options_parse(int argc, char **argv, const struct option *opts, char **unnamed, 2076f5b1c8a1SJohn Marino int *argsused) 2077f5b1c8a1SJohn Marino { 2078f5b1c8a1SJohn Marino const char *errstr; 2079cca6fc52SDaniel Fojt const struct option *opt; 2080f5b1c8a1SJohn Marino long long val; 2081f5b1c8a1SJohn Marino char *arg, *p; 2082f5b1c8a1SJohn Marino int fmt, used; 2083f5b1c8a1SJohn Marino int ord = 0; 2084f5b1c8a1SJohn Marino int i, j; 2085f5b1c8a1SJohn Marino 2086f5b1c8a1SJohn Marino if (unnamed != NULL) 2087f5b1c8a1SJohn Marino *unnamed = NULL; 2088f5b1c8a1SJohn Marino 2089f5b1c8a1SJohn Marino for (i = 1; i < argc; i++) { 2090f5b1c8a1SJohn Marino p = arg = argv[i]; 2091f5b1c8a1SJohn Marino 2092f5b1c8a1SJohn Marino /* Single unnamed argument (without leading hyphen). */ 2093f5b1c8a1SJohn Marino if (*p++ != '-') { 2094f5b1c8a1SJohn Marino if (argsused != NULL) 2095f5b1c8a1SJohn Marino goto done; 2096f5b1c8a1SJohn Marino if (unnamed == NULL) 2097f5b1c8a1SJohn Marino goto unknown; 2098f5b1c8a1SJohn Marino if (*unnamed != NULL) 2099f5b1c8a1SJohn Marino goto toomany; 2100f5b1c8a1SJohn Marino *unnamed = arg; 2101f5b1c8a1SJohn Marino continue; 2102f5b1c8a1SJohn Marino } 2103f5b1c8a1SJohn Marino 2104f5b1c8a1SJohn Marino /* End of named options (single hyphen). */ 2105f5b1c8a1SJohn Marino if (*p == '\0') { 2106f5b1c8a1SJohn Marino if (++i >= argc) 2107f5b1c8a1SJohn Marino goto done; 2108f5b1c8a1SJohn Marino if (argsused != NULL) 2109f5b1c8a1SJohn Marino goto done; 2110f5b1c8a1SJohn Marino if (unnamed != NULL && i == argc - 1) { 2111f5b1c8a1SJohn Marino if (*unnamed != NULL) 2112f5b1c8a1SJohn Marino goto toomany; 2113f5b1c8a1SJohn Marino *unnamed = argv[i]; 2114f5b1c8a1SJohn Marino continue; 2115f5b1c8a1SJohn Marino } 2116f5b1c8a1SJohn Marino goto unknown; 2117f5b1c8a1SJohn Marino } 2118f5b1c8a1SJohn Marino 2119f5b1c8a1SJohn Marino /* See if there is a matching option... */ 2120f5b1c8a1SJohn Marino for (j = 0; opts[j].name != NULL; j++) { 2121f5b1c8a1SJohn Marino if (strcmp(p, opts[j].name) == 0) 2122f5b1c8a1SJohn Marino break; 2123f5b1c8a1SJohn Marino } 2124f5b1c8a1SJohn Marino opt = &opts[j]; 2125f5b1c8a1SJohn Marino if (opt->name == NULL && opt->type == 0) 2126f5b1c8a1SJohn Marino goto unknown; 2127f5b1c8a1SJohn Marino 2128f5b1c8a1SJohn Marino if (opt->type == OPTION_ARG || 2129f5b1c8a1SJohn Marino opt->type == OPTION_ARG_FORMAT || 2130f5b1c8a1SJohn Marino opt->type == OPTION_ARG_FUNC || 2131f5b1c8a1SJohn Marino opt->type == OPTION_ARG_INT || 213272c33676SMaxim Ag opt->type == OPTION_ARG_LONG || 213372c33676SMaxim Ag opt->type == OPTION_ARG_TIME) { 2134f5b1c8a1SJohn Marino if (++i >= argc) { 2135f5b1c8a1SJohn Marino fprintf(stderr, "missing %s argument for -%s\n", 2136f5b1c8a1SJohn Marino opt->argname, opt->name); 2137f5b1c8a1SJohn Marino return (1); 2138f5b1c8a1SJohn Marino } 2139f5b1c8a1SJohn Marino } 2140f5b1c8a1SJohn Marino 2141f5b1c8a1SJohn Marino switch (opt->type) { 2142f5b1c8a1SJohn Marino case OPTION_ARG: 2143f5b1c8a1SJohn Marino *opt->opt.arg = argv[i]; 2144f5b1c8a1SJohn Marino break; 2145f5b1c8a1SJohn Marino 2146f5b1c8a1SJohn Marino case OPTION_ARGV_FUNC: 2147f5b1c8a1SJohn Marino if (opt->opt.argvfunc(argc - i, &argv[i], &used) != 0) 2148f5b1c8a1SJohn Marino return (1); 2149f5b1c8a1SJohn Marino i += used - 1; 2150f5b1c8a1SJohn Marino break; 2151f5b1c8a1SJohn Marino 2152f5b1c8a1SJohn Marino case OPTION_ARG_FORMAT: 2153f5b1c8a1SJohn Marino fmt = str2fmt(argv[i]); 2154f5b1c8a1SJohn Marino if (fmt == FORMAT_UNDEF) { 2155f5b1c8a1SJohn Marino fprintf(stderr, "unknown %s '%s' for -%s\n", 2156f5b1c8a1SJohn Marino opt->argname, argv[i], opt->name); 2157f5b1c8a1SJohn Marino return (1); 2158f5b1c8a1SJohn Marino } 2159f5b1c8a1SJohn Marino *opt->opt.value = fmt; 2160f5b1c8a1SJohn Marino break; 2161f5b1c8a1SJohn Marino 2162f5b1c8a1SJohn Marino case OPTION_ARG_FUNC: 2163f5b1c8a1SJohn Marino if (opt->opt.argfunc(argv[i]) != 0) 2164f5b1c8a1SJohn Marino return (1); 2165f5b1c8a1SJohn Marino break; 2166f5b1c8a1SJohn Marino 2167f5b1c8a1SJohn Marino case OPTION_ARG_INT: 2168f5b1c8a1SJohn Marino val = strtonum(argv[i], 0, INT_MAX, &errstr); 2169f5b1c8a1SJohn Marino if (errstr != NULL) { 2170f5b1c8a1SJohn Marino fprintf(stderr, "%s %s argument for -%s\n", 2171f5b1c8a1SJohn Marino errstr, opt->argname, opt->name); 2172f5b1c8a1SJohn Marino return (1); 2173f5b1c8a1SJohn Marino } 2174f5b1c8a1SJohn Marino *opt->opt.value = (int)val; 2175f5b1c8a1SJohn Marino break; 2176f5b1c8a1SJohn Marino 2177f5b1c8a1SJohn Marino case OPTION_ARG_LONG: 2178f5b1c8a1SJohn Marino val = strtonum(argv[i], 0, LONG_MAX, &errstr); 2179f5b1c8a1SJohn Marino if (errstr != NULL) { 2180f5b1c8a1SJohn Marino fprintf(stderr, "%s %s argument for -%s\n", 2181f5b1c8a1SJohn Marino errstr, opt->argname, opt->name); 2182f5b1c8a1SJohn Marino return (1); 2183f5b1c8a1SJohn Marino } 2184f5b1c8a1SJohn Marino *opt->opt.lvalue = (long)val; 2185f5b1c8a1SJohn Marino break; 2186f5b1c8a1SJohn Marino 218772c33676SMaxim Ag case OPTION_ARG_TIME: 218872c33676SMaxim Ag val = strtonum(argv[i], 0, LLONG_MAX, &errstr); 218972c33676SMaxim Ag if (errstr != NULL) { 219072c33676SMaxim Ag fprintf(stderr, "%s %s argument for -%s\n", 219172c33676SMaxim Ag errstr, opt->argname, opt->name); 219272c33676SMaxim Ag return (1); 219372c33676SMaxim Ag } 219472c33676SMaxim Ag *opt->opt.tvalue = val; 219572c33676SMaxim Ag break; 219672c33676SMaxim Ag 2197f5b1c8a1SJohn Marino case OPTION_DISCARD: 2198f5b1c8a1SJohn Marino break; 2199f5b1c8a1SJohn Marino 2200f5b1c8a1SJohn Marino case OPTION_FUNC: 2201f5b1c8a1SJohn Marino if (opt->opt.func() != 0) 2202f5b1c8a1SJohn Marino return (1); 2203f5b1c8a1SJohn Marino break; 2204f5b1c8a1SJohn Marino 2205f5b1c8a1SJohn Marino case OPTION_FLAG: 2206f5b1c8a1SJohn Marino *opt->opt.flag = 1; 2207f5b1c8a1SJohn Marino break; 2208f5b1c8a1SJohn Marino 2209f5b1c8a1SJohn Marino case OPTION_FLAG_ORD: 2210f5b1c8a1SJohn Marino *opt->opt.flag = ++ord; 2211f5b1c8a1SJohn Marino break; 2212f5b1c8a1SJohn Marino 2213f5b1c8a1SJohn Marino case OPTION_VALUE: 2214f5b1c8a1SJohn Marino *opt->opt.value = opt->value; 2215f5b1c8a1SJohn Marino break; 2216f5b1c8a1SJohn Marino 2217f5b1c8a1SJohn Marino case OPTION_VALUE_AND: 2218f5b1c8a1SJohn Marino *opt->opt.value &= opt->value; 2219f5b1c8a1SJohn Marino break; 2220f5b1c8a1SJohn Marino 2221f5b1c8a1SJohn Marino case OPTION_VALUE_OR: 2222f5b1c8a1SJohn Marino *opt->opt.value |= opt->value; 2223f5b1c8a1SJohn Marino break; 2224f5b1c8a1SJohn Marino 22258edacedfSDaniel Fojt case OPTION_UL_VALUE_OR: 22268edacedfSDaniel Fojt *opt->opt.ulvalue |= opt->ulvalue; 22278edacedfSDaniel Fojt break; 22288edacedfSDaniel Fojt 2229*de0e0e4dSAntonio Huete Jimenez case OPTION_ORDER: 2230*de0e0e4dSAntonio Huete Jimenez *opt->opt.order = ++(*opt->order); 2231*de0e0e4dSAntonio Huete Jimenez break; 2232*de0e0e4dSAntonio Huete Jimenez 2233f5b1c8a1SJohn Marino default: 2234f5b1c8a1SJohn Marino fprintf(stderr, "option %s - unknown type %i\n", 2235f5b1c8a1SJohn Marino opt->name, opt->type); 2236f5b1c8a1SJohn Marino return (1); 2237f5b1c8a1SJohn Marino } 2238f5b1c8a1SJohn Marino } 2239f5b1c8a1SJohn Marino 2240f5b1c8a1SJohn Marino done: 2241f5b1c8a1SJohn Marino if (argsused != NULL) 2242f5b1c8a1SJohn Marino *argsused = i; 2243f5b1c8a1SJohn Marino 2244f5b1c8a1SJohn Marino return (0); 2245f5b1c8a1SJohn Marino 2246f5b1c8a1SJohn Marino toomany: 2247f5b1c8a1SJohn Marino fprintf(stderr, "too many arguments\n"); 2248f5b1c8a1SJohn Marino return (1); 2249f5b1c8a1SJohn Marino 2250f5b1c8a1SJohn Marino unknown: 2251f5b1c8a1SJohn Marino fprintf(stderr, "unknown option '%s'\n", arg); 2252f5b1c8a1SJohn Marino return (1); 2253f5b1c8a1SJohn Marino } 225472c33676SMaxim Ag 225572c33676SMaxim Ag void 225672c33676SMaxim Ag show_cipher(const OBJ_NAME *name, void *arg) 225772c33676SMaxim Ag { 225872c33676SMaxim Ag int *n = arg; 225972c33676SMaxim Ag 226072c33676SMaxim Ag if (!islower((unsigned char)*name->name)) 226172c33676SMaxim Ag return; 226272c33676SMaxim Ag 226372c33676SMaxim Ag fprintf(stderr, " -%-24s%s", name->name, (++*n % 3 != 0 ? "" : "\n")); 226472c33676SMaxim Ag } 226572c33676SMaxim Ag 2266*de0e0e4dSAntonio Huete Jimenez int 2267*de0e0e4dSAntonio Huete Jimenez pkey_check(BIO *out, EVP_PKEY *pkey, int (check_fn)(EVP_PKEY_CTX *), 2268*de0e0e4dSAntonio Huete Jimenez const char *desc) 2269*de0e0e4dSAntonio Huete Jimenez { 2270*de0e0e4dSAntonio Huete Jimenez EVP_PKEY_CTX *ctx; 2271*de0e0e4dSAntonio Huete Jimenez 2272*de0e0e4dSAntonio Huete Jimenez if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { 2273*de0e0e4dSAntonio Huete Jimenez ERR_print_errors(bio_err); 2274*de0e0e4dSAntonio Huete Jimenez return 0; 2275*de0e0e4dSAntonio Huete Jimenez } 2276*de0e0e4dSAntonio Huete Jimenez 2277*de0e0e4dSAntonio Huete Jimenez if (check_fn(ctx) == 1) { 2278*de0e0e4dSAntonio Huete Jimenez BIO_printf(out, "%s valid\n", desc); 2279*de0e0e4dSAntonio Huete Jimenez } else { 2280*de0e0e4dSAntonio Huete Jimenez unsigned long err; 2281*de0e0e4dSAntonio Huete Jimenez 2282*de0e0e4dSAntonio Huete Jimenez BIO_printf(out, "%s invalid\n", desc); 2283*de0e0e4dSAntonio Huete Jimenez 2284*de0e0e4dSAntonio Huete Jimenez while ((err = ERR_get_error()) != 0) 2285*de0e0e4dSAntonio Huete Jimenez BIO_printf(out, "Detailed error: %s\n", 2286*de0e0e4dSAntonio Huete Jimenez ERR_reason_error_string(err)); 2287*de0e0e4dSAntonio Huete Jimenez } 2288*de0e0e4dSAntonio Huete Jimenez 2289*de0e0e4dSAntonio Huete Jimenez EVP_PKEY_CTX_free(ctx); 2290*de0e0e4dSAntonio Huete Jimenez 2291*de0e0e4dSAntonio Huete Jimenez return 1; 2292*de0e0e4dSAntonio Huete Jimenez } 2293