155714Skris/* apps/apps.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 855714Skris * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1555714Skris * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 2255714Skris * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4055714Skris * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 5255714Skris * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 58109998Smarkm/* ==================================================================== 59109998Smarkm * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. 60109998Smarkm * 61109998Smarkm * Redistribution and use in source and binary forms, with or without 62109998Smarkm * modification, are permitted provided that the following conditions 63109998Smarkm * are met: 64109998Smarkm * 65109998Smarkm * 1. Redistributions of source code must retain the above copyright 66109998Smarkm * notice, this list of conditions and the following disclaimer. 67109998Smarkm * 68109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 69109998Smarkm * notice, this list of conditions and the following disclaimer in 70109998Smarkm * the documentation and/or other materials provided with the 71109998Smarkm * distribution. 72109998Smarkm * 73109998Smarkm * 3. All advertising materials mentioning features or use of this 74109998Smarkm * software must display the following acknowledgment: 75109998Smarkm * "This product includes software developed by the OpenSSL Project 76109998Smarkm * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 77109998Smarkm * 78109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 79109998Smarkm * endorse or promote products derived from this software without 80109998Smarkm * prior written permission. For written permission, please contact 81109998Smarkm * openssl-core@openssl.org. 82109998Smarkm * 83109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 84109998Smarkm * nor may "OpenSSL" appear in their names without prior written 85109998Smarkm * permission of the OpenSSL Project. 86109998Smarkm * 87109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 88109998Smarkm * acknowledgment: 89109998Smarkm * "This product includes software developed by the OpenSSL Project 90109998Smarkm * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 91109998Smarkm * 92109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 93109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 94109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 95109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 96109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 97109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 98109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 99109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 100109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 101109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 102109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 103109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 104109998Smarkm * ==================================================================== 105109998Smarkm * 106109998Smarkm * This product includes cryptographic software written by Eric Young 107109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 108109998Smarkm * Hudson (tjh@cryptsoft.com). 109109998Smarkm * 110109998Smarkm */ 11155714Skris 112238405Sjkim#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) 113238405Sjkim#define _POSIX_C_SOURCE 2 /* On VMS, you need to define this to get 114238405Sjkim the declaration of fileno(). The value 115238405Sjkim 2 is to make sure no function defined 116238405Sjkim in POSIX-2 is left undefined. */ 117238405Sjkim#endif 11855714Skris#include <stdio.h> 11955714Skris#include <stdlib.h> 12055714Skris#include <string.h> 121238405Sjkim#if !defined(OPENSSL_SYSNAME_WIN32) && !defined(NETWARE_CLIB) 122238405Sjkim#include <strings.h> 123238405Sjkim#endif 12455714Skris#include <sys/types.h> 125109998Smarkm#include <ctype.h> 126238405Sjkim#include <errno.h> 127194206Ssimon#include <assert.h> 12868651Skris#include <openssl/err.h> 12968651Skris#include <openssl/x509.h> 130109998Smarkm#include <openssl/x509v3.h> 13168651Skris#include <openssl/pem.h> 13268651Skris#include <openssl/pkcs12.h> 133109998Smarkm#include <openssl/ui.h> 13468651Skris#include <openssl/safestack.h> 135111147Snectar#ifndef OPENSSL_NO_ENGINE 136109998Smarkm#include <openssl/engine.h> 137111147Snectar#endif 138160814Ssimon#ifndef OPENSSL_NO_RSA 139160814Ssimon#include <openssl/rsa.h> 140160814Ssimon#endif 141160814Ssimon#include <openssl/bn.h> 142194206Ssimon#ifndef OPENSSL_NO_JPAKE 143194206Ssimon#include <openssl/jpake.h> 144194206Ssimon#endif 14555714Skris 146109998Smarkm#define NON_MAIN 147109998Smarkm#include "apps.h" 148109998Smarkm#undef NON_MAIN 149109998Smarkm 150238405Sjkim#ifdef _WIN32 151238405Sjkimstatic int WIN32_rename(const char *from, const char *to); 152238405Sjkim#define rename(from,to) WIN32_rename((from),(to)) 153238405Sjkim#endif 154238405Sjkim 155109998Smarkmtypedef struct { 156160814Ssimon const char *name; 157109998Smarkm unsigned long flag; 158109998Smarkm unsigned long mask; 159109998Smarkm} NAME_EX_TBL; 160109998Smarkm 161109998Smarkmstatic UI_METHOD *ui_method = NULL; 162109998Smarkm 163109998Smarkmstatic int set_table_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl); 164109998Smarkmstatic int set_multi_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl); 165109998Smarkm 166109998Smarkm#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA) 167109998Smarkm/* Looks like this stuff is worth moving into separate function */ 168109998Smarkmstatic EVP_PKEY * 169109998Smarkmload_netscape_key(BIO *err, BIO *key, const char *file, 170109998Smarkm const char *key_descrip, int format); 171109998Smarkm#endif 172109998Smarkm 17355714Skrisint app_init(long mesgwin); 17455714Skris#ifdef undef /* never finished - probably never will be :-) */ 17555714Skrisint args_from_file(char *file, int *argc, char **argv[]) 17655714Skris { 17755714Skris FILE *fp; 17855714Skris int num,i; 17955714Skris unsigned int len; 18055714Skris static char *buf=NULL; 18155714Skris static char **arg=NULL; 18255714Skris char *p; 18355714Skris 18455714Skris fp=fopen(file,"r"); 18555714Skris if (fp == NULL) 18655714Skris return(0); 18755714Skris 188238405Sjkim if (fseek(fp,0,SEEK_END)==0) 189238405Sjkim len=ftell(fp), rewind(fp); 190238405Sjkim else len=-1; 191238405Sjkim if (len<=0) 192238405Sjkim { 193238405Sjkim fclose(fp); 194238405Sjkim return(0); 195238405Sjkim } 196238405Sjkim 19755714Skris *argc=0; 19855714Skris *argv=NULL; 19955714Skris 20068651Skris if (buf != NULL) OPENSSL_free(buf); 20168651Skris buf=(char *)OPENSSL_malloc(len+1); 20255714Skris if (buf == NULL) return(0); 20355714Skris 20455714Skris len=fread(buf,1,len,fp); 20555714Skris if (len <= 1) return(0); 20655714Skris buf[len]='\0'; 20755714Skris 20855714Skris i=0; 20955714Skris for (p=buf; *p; p++) 21055714Skris if (*p == '\n') i++; 21168651Skris if (arg != NULL) OPENSSL_free(arg); 21268651Skris arg=(char **)OPENSSL_malloc(sizeof(char *)*(i*2)); 21355714Skris 21455714Skris *argv=arg; 21555714Skris num=0; 21655714Skris p=buf; 21755714Skris for (;;) 21855714Skris { 21955714Skris if (!*p) break; 22055714Skris if (*p == '#') /* comment line */ 22155714Skris { 22255714Skris while (*p && (*p != '\n')) p++; 22355714Skris continue; 22455714Skris } 22555714Skris /* else we have a line */ 22655714Skris *(arg++)=p; 22755714Skris num++; 22855714Skris while (*p && ((*p != ' ') && (*p != '\t') && (*p != '\n'))) 22955714Skris p++; 23055714Skris if (!*p) break; 23155714Skris if (*p == '\n') 23255714Skris { 23355714Skris *(p++)='\0'; 23455714Skris continue; 23555714Skris } 23655714Skris /* else it is a tab or space */ 23755714Skris p++; 23855714Skris while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n'))) 23955714Skris p++; 24055714Skris if (!*p) break; 24155714Skris if (*p == '\n') 24255714Skris { 24355714Skris p++; 24455714Skris continue; 24555714Skris } 24655714Skris *(arg++)=p++; 24755714Skris num++; 24855714Skris while (*p && (*p != '\n')) p++; 24955714Skris if (!*p) break; 25055714Skris /* else *p == '\n' */ 25155714Skris *(p++)='\0'; 25255714Skris } 25355714Skris *argc=num; 25455714Skris return(1); 25555714Skris } 25655714Skris#endif 25755714Skris 25855714Skrisint str2fmt(char *s) 25955714Skris { 260238405Sjkim if (s == NULL) 261238405Sjkim return FORMAT_UNDEF; 26255714Skris if ((*s == 'D') || (*s == 'd')) 26355714Skris return(FORMAT_ASN1); 26455714Skris else if ((*s == 'T') || (*s == 't')) 26555714Skris return(FORMAT_TEXT); 266238405Sjkim else if ((*s == 'N') || (*s == 'n')) 267238405Sjkim return(FORMAT_NETSCAPE); 268238405Sjkim else if ((*s == 'S') || (*s == 's')) 269238405Sjkim return(FORMAT_SMIME); 270238405Sjkim else if ((*s == 'M') || (*s == 'm')) 271238405Sjkim return(FORMAT_MSBLOB); 27268651Skris else if ((*s == '1') 27368651Skris || (strcmp(s,"PKCS12") == 0) || (strcmp(s,"pkcs12") == 0) 27468651Skris || (strcmp(s,"P12") == 0) || (strcmp(s,"p12") == 0)) 27568651Skris return(FORMAT_PKCS12); 276109998Smarkm else if ((*s == 'E') || (*s == 'e')) 277109998Smarkm return(FORMAT_ENGINE); 278238405Sjkim else if ((*s == 'P') || (*s == 'p')) 279238405Sjkim { 280238405Sjkim if (s[1] == 'V' || s[1] == 'v') 281238405Sjkim return FORMAT_PVK; 282238405Sjkim else 283238405Sjkim return(FORMAT_PEM); 284238405Sjkim } 28555714Skris else 28655714Skris return(FORMAT_UNDEF); 28755714Skris } 28855714Skris 289160814Ssimon#if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) || defined(OPENSSL_SYS_NETWARE) 29055714Skrisvoid program_name(char *in, char *out, int size) 29155714Skris { 29255714Skris int i,n; 29355714Skris char *p=NULL; 29455714Skris 29555714Skris n=strlen(in); 29655714Skris /* find the last '/', '\' or ':' */ 29755714Skris for (i=n-1; i>0; i--) 29855714Skris { 29955714Skris if ((in[i] == '/') || (in[i] == '\\') || (in[i] == ':')) 30055714Skris { 30155714Skris p= &(in[i+1]); 30255714Skris break; 30355714Skris } 30455714Skris } 30555714Skris if (p == NULL) 30655714Skris p=in; 30755714Skris n=strlen(p); 308160814Ssimon 309160814Ssimon#if defined(OPENSSL_SYS_NETWARE) 310160814Ssimon /* strip off trailing .nlm if present. */ 311160814Ssimon if ((n > 4) && (p[n-4] == '.') && 312160814Ssimon ((p[n-3] == 'n') || (p[n-3] == 'N')) && 313160814Ssimon ((p[n-2] == 'l') || (p[n-2] == 'L')) && 314160814Ssimon ((p[n-1] == 'm') || (p[n-1] == 'M'))) 315160814Ssimon n-=4; 316160814Ssimon#else 31755714Skris /* strip off trailing .exe if present. */ 31855714Skris if ((n > 4) && (p[n-4] == '.') && 31955714Skris ((p[n-3] == 'e') || (p[n-3] == 'E')) && 32055714Skris ((p[n-2] == 'x') || (p[n-2] == 'X')) && 32155714Skris ((p[n-1] == 'e') || (p[n-1] == 'E'))) 32255714Skris n-=4; 323160814Ssimon#endif 324160814Ssimon 32555714Skris if (n > size-1) 32655714Skris n=size-1; 32755714Skris 32855714Skris for (i=0; i<n; i++) 32955714Skris { 33055714Skris if ((p[i] >= 'A') && (p[i] <= 'Z')) 33155714Skris out[i]=p[i]-'A'+'a'; 33255714Skris else 33355714Skris out[i]=p[i]; 33455714Skris } 33555714Skris out[n]='\0'; 33655714Skris } 33755714Skris#else 338109998Smarkm#ifdef OPENSSL_SYS_VMS 33955714Skrisvoid program_name(char *in, char *out, int size) 34055714Skris { 34155714Skris char *p=in, *q; 34255714Skris char *chars=":]>"; 34355714Skris 34455714Skris while(*chars != '\0') 34555714Skris { 34655714Skris q=strrchr(p,*chars); 34755714Skris if (q > p) 34855714Skris p = q + 1; 34955714Skris chars++; 35055714Skris } 35155714Skris 35255714Skris q=strrchr(p,'.'); 35355714Skris if (q == NULL) 354100936Snectar q = p + strlen(p); 355100936Snectar strncpy(out,p,size-1); 356100936Snectar if (q-p >= size) 357100936Snectar { 358100936Snectar out[size-1]='\0'; 359100936Snectar } 360100936Snectar else 361100936Snectar { 362100936Snectar out[q-p]='\0'; 363100936Snectar } 36455714Skris } 36555714Skris#else 36655714Skrisvoid program_name(char *in, char *out, int size) 36755714Skris { 36855714Skris char *p; 36955714Skris 37055714Skris p=strrchr(in,'/'); 37155714Skris if (p != NULL) 37255714Skris p++; 37355714Skris else 37455714Skris p=in; 375109998Smarkm BUF_strlcpy(out,p,size); 37655714Skris } 37755714Skris#endif 37855714Skris#endif 37955714Skris 38055714Skrisint chopup_args(ARGS *arg, char *buf, int *argc, char **argv[]) 38155714Skris { 382215697Ssimon int num,i; 38355714Skris char *p; 38455714Skris 38555714Skris *argc=0; 38655714Skris *argv=NULL; 38755714Skris 38855714Skris i=0; 38955714Skris if (arg->count == 0) 39055714Skris { 39155714Skris arg->count=20; 39268651Skris arg->data=(char **)OPENSSL_malloc(sizeof(char *)*arg->count); 393279264Sdelphij if (arg->data == NULL) 394279264Sdelphij return 0; 39555714Skris } 39655714Skris for (i=0; i<arg->count; i++) 39755714Skris arg->data[i]=NULL; 39855714Skris 39955714Skris num=0; 40055714Skris p=buf; 40155714Skris for (;;) 40255714Skris { 40355714Skris /* first scan over white space */ 40455714Skris if (!*p) break; 40555714Skris while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n'))) 40655714Skris p++; 40755714Skris if (!*p) break; 40855714Skris 40955714Skris /* The start of something good :-) */ 41055714Skris if (num >= arg->count) 41155714Skris { 412160814Ssimon char **tmp_p; 413160814Ssimon int tlen = arg->count + 20; 414160814Ssimon tmp_p = (char **)OPENSSL_realloc(arg->data, 415160814Ssimon sizeof(char *)*tlen); 416160814Ssimon if (tmp_p == NULL) 417160814Ssimon return 0; 418160814Ssimon arg->data = tmp_p; 419160814Ssimon arg->count = tlen; 420160814Ssimon /* initialize newly allocated data */ 421160814Ssimon for (i = num; i < arg->count; i++) 422160814Ssimon arg->data[i] = NULL; 42355714Skris } 42455714Skris arg->data[num++]=p; 42555714Skris 42655714Skris /* now look for the end of this */ 42755714Skris if ((*p == '\'') || (*p == '\"')) /* scan for closing quote */ 42855714Skris { 42955714Skris i= *(p++); 43055714Skris arg->data[num-1]++; /* jump over quote */ 43155714Skris while (*p && (*p != i)) 43255714Skris p++; 43355714Skris *p='\0'; 43455714Skris } 43555714Skris else 43655714Skris { 43755714Skris while (*p && ((*p != ' ') && 43855714Skris (*p != '\t') && (*p != '\n'))) 43955714Skris p++; 44055714Skris 44155714Skris if (*p == '\0') 44255714Skris p--; 44355714Skris else 44455714Skris *p='\0'; 44555714Skris } 44655714Skris p++; 44755714Skris } 44855714Skris *argc=num; 44955714Skris *argv=arg->data; 45055714Skris return(1); 45155714Skris } 45255714Skris 45355714Skris#ifndef APP_INIT 45455714Skrisint app_init(long mesgwin) 45555714Skris { 45655714Skris return(1); 45755714Skris } 45855714Skris#endif 45959191Skris 46059191Skris 46159191Skrisint dump_cert_text (BIO *out, X509 *x) 46259191Skris{ 463109998Smarkm char *p; 464109998Smarkm 465109998Smarkm p=X509_NAME_oneline(X509_get_subject_name(x),NULL,0); 46659191Skris BIO_puts(out,"subject="); 467109998Smarkm BIO_puts(out,p); 468109998Smarkm OPENSSL_free(p); 46959191Skris 470109998Smarkm p=X509_NAME_oneline(X509_get_issuer_name(x),NULL,0); 471109998Smarkm BIO_puts(out,"\nissuer="); 472109998Smarkm BIO_puts(out,p); 47359191Skris BIO_puts(out,"\n"); 474109998Smarkm OPENSSL_free(p); 475109998Smarkm 476109998Smarkm return 0; 47759191Skris} 47859191Skris 479109998Smarkmstatic int ui_open(UI *ui) 480109998Smarkm { 481109998Smarkm return UI_method_get_opener(UI_OpenSSL())(ui); 482109998Smarkm } 483109998Smarkmstatic int ui_read(UI *ui, UI_STRING *uis) 484109998Smarkm { 485109998Smarkm if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD 486109998Smarkm && UI_get0_user_data(ui)) 487109998Smarkm { 488109998Smarkm switch(UI_get_string_type(uis)) 489109998Smarkm { 490109998Smarkm case UIT_PROMPT: 491109998Smarkm case UIT_VERIFY: 492109998Smarkm { 493109998Smarkm const char *password = 494109998Smarkm ((PW_CB_DATA *)UI_get0_user_data(ui))->password; 495127128Snectar if (password && password[0] != '\0') 496109998Smarkm { 497109998Smarkm UI_set_result(ui, uis, password); 498109998Smarkm return 1; 499109998Smarkm } 500109998Smarkm } 501109998Smarkm default: 502109998Smarkm break; 503109998Smarkm } 504109998Smarkm } 505109998Smarkm return UI_method_get_reader(UI_OpenSSL())(ui, uis); 506109998Smarkm } 507109998Smarkmstatic int ui_write(UI *ui, UI_STRING *uis) 508109998Smarkm { 509109998Smarkm if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD 510109998Smarkm && UI_get0_user_data(ui)) 511109998Smarkm { 512109998Smarkm switch(UI_get_string_type(uis)) 513109998Smarkm { 514109998Smarkm case UIT_PROMPT: 515109998Smarkm case UIT_VERIFY: 516109998Smarkm { 517109998Smarkm const char *password = 518109998Smarkm ((PW_CB_DATA *)UI_get0_user_data(ui))->password; 519127128Snectar if (password && password[0] != '\0') 520109998Smarkm return 1; 521109998Smarkm } 522109998Smarkm default: 523109998Smarkm break; 524109998Smarkm } 525109998Smarkm } 526109998Smarkm return UI_method_get_writer(UI_OpenSSL())(ui, uis); 527109998Smarkm } 528109998Smarkmstatic int ui_close(UI *ui) 529109998Smarkm { 530109998Smarkm return UI_method_get_closer(UI_OpenSSL())(ui); 531109998Smarkm } 532109998Smarkmint setup_ui_method(void) 533109998Smarkm { 534109998Smarkm ui_method = UI_create_method("OpenSSL application user interface"); 535109998Smarkm UI_method_set_opener(ui_method, ui_open); 536109998Smarkm UI_method_set_reader(ui_method, ui_read); 537109998Smarkm UI_method_set_writer(ui_method, ui_write); 538109998Smarkm UI_method_set_closer(ui_method, ui_close); 539109998Smarkm return 0; 540109998Smarkm } 541109998Smarkmvoid destroy_ui_method(void) 542109998Smarkm { 543109998Smarkm if(ui_method) 544109998Smarkm { 545109998Smarkm UI_destroy_method(ui_method); 546109998Smarkm ui_method = NULL; 547109998Smarkm } 548109998Smarkm } 549109998Smarkmint password_callback(char *buf, int bufsiz, int verify, 550109998Smarkm PW_CB_DATA *cb_tmp) 551109998Smarkm { 552109998Smarkm UI *ui = NULL; 553109998Smarkm int res = 0; 554109998Smarkm const char *prompt_info = NULL; 555109998Smarkm const char *password = NULL; 556109998Smarkm PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp; 557109998Smarkm 558109998Smarkm if (cb_data) 559109998Smarkm { 560109998Smarkm if (cb_data->password) 561109998Smarkm password = cb_data->password; 562109998Smarkm if (cb_data->prompt_info) 563109998Smarkm prompt_info = cb_data->prompt_info; 564109998Smarkm } 565109998Smarkm 566109998Smarkm if (password) 567109998Smarkm { 568109998Smarkm res = strlen(password); 569109998Smarkm if (res > bufsiz) 570109998Smarkm res = bufsiz; 571109998Smarkm memcpy(buf, password, res); 572109998Smarkm return res; 573109998Smarkm } 574109998Smarkm 575109998Smarkm ui = UI_new_method(ui_method); 576109998Smarkm if (ui) 577109998Smarkm { 578109998Smarkm int ok = 0; 579109998Smarkm char *buff = NULL; 580109998Smarkm int ui_flags = 0; 581109998Smarkm char *prompt = NULL; 582109998Smarkm 583109998Smarkm prompt = UI_construct_prompt(ui, "pass phrase", 584160814Ssimon prompt_info); 585109998Smarkm 586109998Smarkm ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD; 587109998Smarkm UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); 588109998Smarkm 589109998Smarkm if (ok >= 0) 590109998Smarkm ok = UI_add_input_string(ui,prompt,ui_flags,buf, 591279264Sdelphij PW_MIN_LENGTH,bufsiz-1); 592109998Smarkm if (ok >= 0 && verify) 593109998Smarkm { 594109998Smarkm buff = (char *)OPENSSL_malloc(bufsiz); 595109998Smarkm ok = UI_add_verify_string(ui,prompt,ui_flags,buff, 596279264Sdelphij PW_MIN_LENGTH,bufsiz-1, buf); 597109998Smarkm } 598109998Smarkm if (ok >= 0) 599109998Smarkm do 600109998Smarkm { 601109998Smarkm ok = UI_process(ui); 602109998Smarkm } 603109998Smarkm while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); 604109998Smarkm 605109998Smarkm if (buff) 606109998Smarkm { 607109998Smarkm OPENSSL_cleanse(buff,(unsigned int)bufsiz); 608109998Smarkm OPENSSL_free(buff); 609109998Smarkm } 610109998Smarkm 611109998Smarkm if (ok >= 0) 612109998Smarkm res = strlen(buf); 613109998Smarkm if (ok == -1) 614109998Smarkm { 615109998Smarkm BIO_printf(bio_err, "User interface error\n"); 616109998Smarkm ERR_print_errors(bio_err); 617109998Smarkm OPENSSL_cleanse(buf,(unsigned int)bufsiz); 618109998Smarkm res = 0; 619109998Smarkm } 620109998Smarkm if (ok == -2) 621109998Smarkm { 622109998Smarkm BIO_printf(bio_err,"aborted!\n"); 623109998Smarkm OPENSSL_cleanse(buf,(unsigned int)bufsiz); 624109998Smarkm res = 0; 625109998Smarkm } 626109998Smarkm UI_free(ui); 627109998Smarkm OPENSSL_free(prompt); 628109998Smarkm } 629109998Smarkm return res; 630109998Smarkm } 631109998Smarkm 63259191Skrisstatic char *app_get_pass(BIO *err, char *arg, int keepbio); 63359191Skris 63459191Skrisint app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2) 63559191Skris{ 63659191Skris int same; 63759191Skris if(!arg2 || !arg1 || strcmp(arg1, arg2)) same = 0; 63859191Skris else same = 1; 63959191Skris if(arg1) { 64059191Skris *pass1 = app_get_pass(err, arg1, same); 64159191Skris if(!*pass1) return 0; 64259191Skris } else if(pass1) *pass1 = NULL; 64359191Skris if(arg2) { 64459191Skris *pass2 = app_get_pass(err, arg2, same ? 2 : 0); 64559191Skris if(!*pass2) return 0; 64659191Skris } else if(pass2) *pass2 = NULL; 64759191Skris return 1; 64859191Skris} 64959191Skris 65059191Skrisstatic char *app_get_pass(BIO *err, char *arg, int keepbio) 65159191Skris{ 65259191Skris char *tmp, tpass[APP_PASS_LEN]; 65359191Skris static BIO *pwdbio = NULL; 65459191Skris int i; 65559191Skris if(!strncmp(arg, "pass:", 5)) return BUF_strdup(arg + 5); 65659191Skris if(!strncmp(arg, "env:", 4)) { 65759191Skris tmp = getenv(arg + 4); 65859191Skris if(!tmp) { 65959191Skris BIO_printf(err, "Can't read environment variable %s\n", arg + 4); 66059191Skris return NULL; 66159191Skris } 66259191Skris return BUF_strdup(tmp); 66359191Skris } 66459191Skris if(!keepbio || !pwdbio) { 66559191Skris if(!strncmp(arg, "file:", 5)) { 66659191Skris pwdbio = BIO_new_file(arg + 5, "r"); 66759191Skris if(!pwdbio) { 66859191Skris BIO_printf(err, "Can't open file %s\n", arg + 5); 66959191Skris return NULL; 67059191Skris } 671238405Sjkim#if !defined(_WIN32) 672238405Sjkim /* 673238405Sjkim * Under _WIN32, which covers even Win64 and CE, file 674238405Sjkim * descriptors referenced by BIO_s_fd are not inherited 675238405Sjkim * by child process and therefore below is not an option. 676238405Sjkim * It could have been an option if bss_fd.c was operating 677238405Sjkim * on real Windows descriptors, such as those obtained 678238405Sjkim * with CreateFile. 679238405Sjkim */ 68059191Skris } else if(!strncmp(arg, "fd:", 3)) { 68159191Skris BIO *btmp; 68259191Skris i = atoi(arg + 3); 68359191Skris if(i >= 0) pwdbio = BIO_new_fd(i, BIO_NOCLOSE); 68459191Skris if((i < 0) || !pwdbio) { 68559191Skris BIO_printf(err, "Can't access file descriptor %s\n", arg + 3); 68659191Skris return NULL; 68759191Skris } 68859191Skris /* Can't do BIO_gets on an fd BIO so add a buffering BIO */ 68959191Skris btmp = BIO_new(BIO_f_buffer()); 69059191Skris pwdbio = BIO_push(btmp, pwdbio); 691238405Sjkim#endif 69259191Skris } else if(!strcmp(arg, "stdin")) { 69359191Skris pwdbio = BIO_new_fp(stdin, BIO_NOCLOSE); 69459191Skris if(!pwdbio) { 69559191Skris BIO_printf(err, "Can't open BIO for stdin\n"); 69659191Skris return NULL; 69759191Skris } 69859191Skris } else { 69959191Skris BIO_printf(err, "Invalid password argument \"%s\"\n", arg); 70059191Skris return NULL; 70159191Skris } 70259191Skris } 70359191Skris i = BIO_gets(pwdbio, tpass, APP_PASS_LEN); 70459191Skris if(keepbio != 1) { 70559191Skris BIO_free_all(pwdbio); 70659191Skris pwdbio = NULL; 70759191Skris } 70859191Skris if(i <= 0) { 70959191Skris BIO_printf(err, "Error reading password from BIO\n"); 71059191Skris return NULL; 71159191Skris } 71259191Skris tmp = strchr(tpass, '\n'); 71359191Skris if(tmp) *tmp = 0; 71459191Skris return BUF_strdup(tpass); 71559191Skris} 71668651Skris 717109998Smarkmint add_oid_section(BIO *err, CONF *conf) 71868651Skris{ 71968651Skris char *p; 72068651Skris STACK_OF(CONF_VALUE) *sktmp; 72168651Skris CONF_VALUE *cnf; 72268651Skris int i; 723109998Smarkm if(!(p=NCONF_get_string(conf,NULL,"oid_section"))) 724109998Smarkm { 725109998Smarkm ERR_clear_error(); 726109998Smarkm return 1; 727109998Smarkm } 728109998Smarkm if(!(sktmp = NCONF_get_section(conf, p))) { 72968651Skris BIO_printf(err, "problem loading oid section %s\n", p); 73068651Skris return 0; 73168651Skris } 73268651Skris for(i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { 73368651Skris cnf = sk_CONF_VALUE_value(sktmp, i); 73468651Skris if(OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) { 73568651Skris BIO_printf(err, "problem creating object %s=%s\n", 73668651Skris cnf->name, cnf->value); 73768651Skris return 0; 73868651Skris } 73968651Skris } 74068651Skris return 1; 74168651Skris} 74268651Skris 743160814Ssimonstatic int load_pkcs12(BIO *err, BIO *in, const char *desc, 744160814Ssimon pem_password_cb *pem_cb, void *cb_data, 745160814Ssimon EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca) 746160814Ssimon { 747160814Ssimon const char *pass; 748160814Ssimon char tpass[PEM_BUFSIZE]; 749160814Ssimon int len, ret = 0; 750160814Ssimon PKCS12 *p12; 751160814Ssimon p12 = d2i_PKCS12_bio(in, NULL); 752160814Ssimon if (p12 == NULL) 753160814Ssimon { 754160814Ssimon BIO_printf(err, "Error loading PKCS12 file for %s\n", desc); 755160814Ssimon goto die; 756160814Ssimon } 757160814Ssimon /* See if an empty password will do */ 758160814Ssimon if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0)) 759160814Ssimon pass = ""; 760160814Ssimon else 761160814Ssimon { 762160814Ssimon if (!pem_cb) 763160814Ssimon pem_cb = (pem_password_cb *)password_callback; 764160814Ssimon len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data); 765160814Ssimon if (len < 0) 766160814Ssimon { 767160814Ssimon BIO_printf(err, "Passpharse callback error for %s\n", 768160814Ssimon desc); 769160814Ssimon goto die; 770160814Ssimon } 771160814Ssimon if (len < PEM_BUFSIZE) 772160814Ssimon tpass[len] = 0; 773160814Ssimon if (!PKCS12_verify_mac(p12, tpass, len)) 774160814Ssimon { 775160814Ssimon BIO_printf(err, 776160814Ssimon "Mac verify error (wrong password?) in PKCS12 file for %s\n", desc); 777160814Ssimon goto die; 778160814Ssimon } 779160814Ssimon pass = tpass; 780160814Ssimon } 781160814Ssimon ret = PKCS12_parse(p12, pass, pkey, cert, ca); 782160814Ssimon die: 783160814Ssimon if (p12) 784160814Ssimon PKCS12_free(p12); 785160814Ssimon return ret; 786160814Ssimon } 787160814Ssimon 788109998SmarkmX509 *load_cert(BIO *err, const char *file, int format, 789109998Smarkm const char *pass, ENGINE *e, const char *cert_descrip) 79068651Skris { 79168651Skris X509 *x=NULL; 79268651Skris BIO *cert; 79368651Skris 79468651Skris if ((cert=BIO_new(BIO_s_file())) == NULL) 79568651Skris { 79668651Skris ERR_print_errors(err); 79768651Skris goto end; 79868651Skris } 79968651Skris 80068651Skris if (file == NULL) 801109998Smarkm { 802238405Sjkim#ifdef _IONBF 803238405Sjkim# ifndef OPENSSL_NO_SETVBUF_IONBF 804109998Smarkm setvbuf(stdin, NULL, _IONBF, 0); 805238405Sjkim# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ 806238405Sjkim#endif 80768651Skris BIO_set_fp(cert,stdin,BIO_NOCLOSE); 808109998Smarkm } 80968651Skris else 81068651Skris { 81168651Skris if (BIO_read_filename(cert,file) <= 0) 81268651Skris { 813109998Smarkm BIO_printf(err, "Error opening %s %s\n", 814109998Smarkm cert_descrip, file); 815109998Smarkm ERR_print_errors(err); 81668651Skris goto end; 81768651Skris } 81868651Skris } 81968651Skris 82068651Skris if (format == FORMAT_ASN1) 82168651Skris x=d2i_X509_bio(cert,NULL); 82268651Skris else if (format == FORMAT_NETSCAPE) 82368651Skris { 824238405Sjkim NETSCAPE_X509 *nx; 825238405Sjkim nx=ASN1_item_d2i_bio(ASN1_ITEM_rptr(NETSCAPE_X509),cert,NULL); 826238405Sjkim if (nx == NULL) 82768651Skris goto end; 82868651Skris 829238405Sjkim if ((strncmp(NETSCAPE_CERT_HDR,(char *)nx->header->data, 830238405Sjkim nx->header->length) != 0)) 83168651Skris { 832238405Sjkim NETSCAPE_X509_free(nx); 83368651Skris BIO_printf(err,"Error reading header on certificate\n"); 83468651Skris goto end; 83568651Skris } 836238405Sjkim x=nx->cert; 837238405Sjkim nx->cert = NULL; 838238405Sjkim NETSCAPE_X509_free(nx); 83968651Skris } 84068651Skris else if (format == FORMAT_PEM) 841109998Smarkm x=PEM_read_bio_X509_AUX(cert,NULL, 842109998Smarkm (pem_password_cb *)password_callback, NULL); 84368651Skris else if (format == FORMAT_PKCS12) 84468651Skris { 845160814Ssimon if (!load_pkcs12(err, cert,cert_descrip, NULL, NULL, 846160814Ssimon NULL, &x, NULL)) 847160814Ssimon goto end; 84868651Skris } 84968651Skris else { 850109998Smarkm BIO_printf(err,"bad input format specified for %s\n", 851109998Smarkm cert_descrip); 85268651Skris goto end; 85368651Skris } 85468651Skrisend: 85568651Skris if (x == NULL) 85668651Skris { 85768651Skris BIO_printf(err,"unable to load certificate\n"); 85868651Skris ERR_print_errors(err); 85968651Skris } 86068651Skris if (cert != NULL) BIO_free(cert); 86168651Skris return(x); 86268651Skris } 86368651Skris 864109998SmarkmEVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin, 865109998Smarkm const char *pass, ENGINE *e, const char *key_descrip) 86668651Skris { 86768651Skris BIO *key=NULL; 86868651Skris EVP_PKEY *pkey=NULL; 869109998Smarkm PW_CB_DATA cb_data; 87068651Skris 871109998Smarkm cb_data.password = pass; 872109998Smarkm cb_data.prompt_info = file; 873109998Smarkm 874109998Smarkm if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) 87568651Skris { 87668651Skris BIO_printf(err,"no keyfile specified\n"); 87768651Skris goto end; 87868651Skris } 879111147Snectar#ifndef OPENSSL_NO_ENGINE 880109998Smarkm if (format == FORMAT_ENGINE) 881109998Smarkm { 882109998Smarkm if (!e) 883215697Ssimon BIO_printf(err,"no engine specified\n"); 884109998Smarkm else 885215697Ssimon { 886109998Smarkm pkey = ENGINE_load_private_key(e, file, 887109998Smarkm ui_method, &cb_data); 888215697Ssimon if (!pkey) 889215697Ssimon { 890215697Ssimon BIO_printf(err,"cannot load %s from engine\n",key_descrip); 891215697Ssimon ERR_print_errors(err); 892215697Ssimon } 893215697Ssimon } 894109998Smarkm goto end; 895109998Smarkm } 896111147Snectar#endif 89768651Skris key=BIO_new(BIO_s_file()); 89868651Skris if (key == NULL) 89968651Skris { 90068651Skris ERR_print_errors(err); 90168651Skris goto end; 90268651Skris } 903109998Smarkm if (file == NULL && maybe_stdin) 90468651Skris { 905238405Sjkim#ifdef _IONBF 906238405Sjkim# ifndef OPENSSL_NO_SETVBUF_IONBF 907109998Smarkm setvbuf(stdin, NULL, _IONBF, 0); 908238405Sjkim# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ 909238405Sjkim#endif 910109998Smarkm BIO_set_fp(key,stdin,BIO_NOCLOSE); 91168651Skris } 912109998Smarkm else 913109998Smarkm if (BIO_read_filename(key,file) <= 0) 914109998Smarkm { 915109998Smarkm BIO_printf(err, "Error opening %s %s\n", 916109998Smarkm key_descrip, file); 917109998Smarkm ERR_print_errors(err); 918109998Smarkm goto end; 919109998Smarkm } 92068651Skris if (format == FORMAT_ASN1) 92168651Skris { 92268651Skris pkey=d2i_PrivateKey_bio(key, NULL); 92368651Skris } 92468651Skris else if (format == FORMAT_PEM) 92568651Skris { 926109998Smarkm pkey=PEM_read_bio_PrivateKey(key,NULL, 927109998Smarkm (pem_password_cb *)password_callback, &cb_data); 92868651Skris } 929109998Smarkm#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA) 930109998Smarkm else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC) 931109998Smarkm pkey = load_netscape_key(err, key, file, key_descrip, format); 932109998Smarkm#endif 93368651Skris else if (format == FORMAT_PKCS12) 93468651Skris { 935160814Ssimon if (!load_pkcs12(err, key, key_descrip, 936160814Ssimon (pem_password_cb *)password_callback, &cb_data, 937160814Ssimon &pkey, NULL, NULL)) 938160814Ssimon goto end; 93968651Skris } 940238405Sjkim#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4) 941238405Sjkim else if (format == FORMAT_MSBLOB) 942238405Sjkim pkey = b2i_PrivateKey_bio(key); 943238405Sjkim else if (format == FORMAT_PVK) 944238405Sjkim pkey = b2i_PVK_bio(key, (pem_password_cb *)password_callback, 945238405Sjkim &cb_data); 946238405Sjkim#endif 94768651Skris else 94868651Skris { 949109998Smarkm BIO_printf(err,"bad input format specified for key file\n"); 95068651Skris goto end; 95168651Skris } 95268651Skris end: 95368651Skris if (key != NULL) BIO_free(key); 954215697Ssimon if (pkey == NULL) 955215697Ssimon { 956109998Smarkm BIO_printf(err,"unable to load %s\n", key_descrip); 957215697Ssimon ERR_print_errors(err); 958215697Ssimon } 95968651Skris return(pkey); 96068651Skris } 96168651Skris 962109998SmarkmEVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin, 963109998Smarkm const char *pass, ENGINE *e, const char *key_descrip) 96468651Skris { 96568651Skris BIO *key=NULL; 96668651Skris EVP_PKEY *pkey=NULL; 967109998Smarkm PW_CB_DATA cb_data; 96868651Skris 969109998Smarkm cb_data.password = pass; 970109998Smarkm cb_data.prompt_info = file; 971109998Smarkm 972109998Smarkm if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) 97368651Skris { 97468651Skris BIO_printf(err,"no keyfile specified\n"); 97568651Skris goto end; 97668651Skris } 977111147Snectar#ifndef OPENSSL_NO_ENGINE 978109998Smarkm if (format == FORMAT_ENGINE) 979109998Smarkm { 980109998Smarkm if (!e) 981109998Smarkm BIO_printf(bio_err,"no engine specified\n"); 982109998Smarkm else 983109998Smarkm pkey = ENGINE_load_public_key(e, file, 984109998Smarkm ui_method, &cb_data); 985109998Smarkm goto end; 986109998Smarkm } 987111147Snectar#endif 98868651Skris key=BIO_new(BIO_s_file()); 98968651Skris if (key == NULL) 99068651Skris { 99168651Skris ERR_print_errors(err); 99268651Skris goto end; 99368651Skris } 994109998Smarkm if (file == NULL && maybe_stdin) 99568651Skris { 996238405Sjkim#ifdef _IONBF 997238405Sjkim# ifndef OPENSSL_NO_SETVBUF_IONBF 998109998Smarkm setvbuf(stdin, NULL, _IONBF, 0); 999238405Sjkim# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */ 1000238405Sjkim#endif 1001109998Smarkm BIO_set_fp(key,stdin,BIO_NOCLOSE); 100268651Skris } 1003109998Smarkm else 1004109998Smarkm if (BIO_read_filename(key,file) <= 0) 1005109998Smarkm { 1006109998Smarkm BIO_printf(err, "Error opening %s %s\n", 1007109998Smarkm key_descrip, file); 1008109998Smarkm ERR_print_errors(err); 1009109998Smarkm goto end; 1010109998Smarkm } 101168651Skris if (format == FORMAT_ASN1) 101268651Skris { 101368651Skris pkey=d2i_PUBKEY_bio(key, NULL); 101468651Skris } 1015238405Sjkim#ifndef OPENSSL_NO_RSA 1016238405Sjkim else if (format == FORMAT_ASN1RSA) 1017238405Sjkim { 1018238405Sjkim RSA *rsa; 1019238405Sjkim rsa = d2i_RSAPublicKey_bio(key, NULL); 1020238405Sjkim if (rsa) 1021238405Sjkim { 1022238405Sjkim pkey = EVP_PKEY_new(); 1023238405Sjkim if (pkey) 1024238405Sjkim EVP_PKEY_set1_RSA(pkey, rsa); 1025238405Sjkim RSA_free(rsa); 1026238405Sjkim } 1027238405Sjkim else 1028238405Sjkim pkey = NULL; 1029238405Sjkim } 1030238405Sjkim else if (format == FORMAT_PEMRSA) 1031238405Sjkim { 1032238405Sjkim RSA *rsa; 1033238405Sjkim rsa = PEM_read_bio_RSAPublicKey(key, NULL, 1034238405Sjkim (pem_password_cb *)password_callback, &cb_data); 1035238405Sjkim if (rsa) 1036238405Sjkim { 1037238405Sjkim pkey = EVP_PKEY_new(); 1038238405Sjkim if (pkey) 1039238405Sjkim EVP_PKEY_set1_RSA(pkey, rsa); 1040238405Sjkim RSA_free(rsa); 1041238405Sjkim } 1042238405Sjkim else 1043238405Sjkim pkey = NULL; 1044238405Sjkim } 1045238405Sjkim#endif 104668651Skris else if (format == FORMAT_PEM) 104768651Skris { 1048109998Smarkm pkey=PEM_read_bio_PUBKEY(key,NULL, 1049109998Smarkm (pem_password_cb *)password_callback, &cb_data); 105068651Skris } 1051109998Smarkm#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA) 1052109998Smarkm else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC) 1053109998Smarkm pkey = load_netscape_key(err, key, file, key_descrip, format); 1054109998Smarkm#endif 1055238405Sjkim#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) 1056238405Sjkim else if (format == FORMAT_MSBLOB) 1057238405Sjkim pkey = b2i_PublicKey_bio(key); 1058238405Sjkim#endif 105968651Skris else 106068651Skris { 1061109998Smarkm BIO_printf(err,"bad input format specified for key file\n"); 106268651Skris goto end; 106368651Skris } 106468651Skris end: 106568651Skris if (key != NULL) BIO_free(key); 106668651Skris if (pkey == NULL) 1067109998Smarkm BIO_printf(err,"unable to load %s\n", key_descrip); 106868651Skris return(pkey); 106968651Skris } 107068651Skris 1071109998Smarkm#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA) 1072109998Smarkmstatic EVP_PKEY * 1073109998Smarkmload_netscape_key(BIO *err, BIO *key, const char *file, 1074109998Smarkm const char *key_descrip, int format) 107568651Skris { 1076109998Smarkm EVP_PKEY *pkey; 1077109998Smarkm BUF_MEM *buf; 1078109998Smarkm RSA *rsa; 1079109998Smarkm const unsigned char *p; 1080109998Smarkm int size, i; 1081109998Smarkm 1082109998Smarkm buf=BUF_MEM_new(); 1083109998Smarkm pkey = EVP_PKEY_new(); 1084109998Smarkm size = 0; 1085109998Smarkm if (buf == NULL || pkey == NULL) 1086109998Smarkm goto error; 1087109998Smarkm for (;;) 1088109998Smarkm { 1089109998Smarkm if (!BUF_MEM_grow_clean(buf,size+1024*10)) 1090109998Smarkm goto error; 1091109998Smarkm i = BIO_read(key, &(buf->data[size]), 1024*10); 1092109998Smarkm size += i; 1093109998Smarkm if (i == 0) 1094109998Smarkm break; 1095109998Smarkm if (i < 0) 1096109998Smarkm { 1097109998Smarkm BIO_printf(err, "Error reading %s %s", 1098109998Smarkm key_descrip, file); 1099109998Smarkm goto error; 1100109998Smarkm } 1101109998Smarkm } 1102109998Smarkm p=(unsigned char *)buf->data; 1103109998Smarkm rsa = d2i_RSA_NET(NULL,&p,(long)size,NULL, 1104109998Smarkm (format == FORMAT_IISSGC ? 1 : 0)); 1105109998Smarkm if (rsa == NULL) 1106109998Smarkm goto error; 1107109998Smarkm BUF_MEM_free(buf); 1108109998Smarkm EVP_PKEY_set1_RSA(pkey, rsa); 1109109998Smarkm return pkey; 1110109998Smarkmerror: 1111109998Smarkm BUF_MEM_free(buf); 1112109998Smarkm EVP_PKEY_free(pkey); 1113109998Smarkm return NULL; 1114109998Smarkm } 1115109998Smarkm#endif /* ndef OPENSSL_NO_RC4 */ 1116109998Smarkm 1117238405Sjkimstatic int load_certs_crls(BIO *err, const char *file, int format, 1118238405Sjkim const char *pass, ENGINE *e, const char *desc, 1119238405Sjkim STACK_OF(X509) **pcerts, STACK_OF(X509_CRL) **pcrls) 1120109998Smarkm { 112168651Skris int i; 1122238405Sjkim BIO *bio; 1123238405Sjkim STACK_OF(X509_INFO) *xis = NULL; 112468651Skris X509_INFO *xi; 1125109998Smarkm PW_CB_DATA cb_data; 1126238405Sjkim int rv = 0; 112768651Skris 1128109998Smarkm cb_data.password = pass; 1129109998Smarkm cb_data.prompt_info = file; 1130109998Smarkm 1131238405Sjkim if (format != FORMAT_PEM) 113268651Skris { 1133238405Sjkim BIO_printf(err,"bad input format specified for %s\n", desc); 1134238405Sjkim return 0; 113568651Skris } 113668651Skris 113768651Skris if (file == NULL) 1138238405Sjkim bio = BIO_new_fp(stdin,BIO_NOCLOSE); 113968651Skris else 1140238405Sjkim bio = BIO_new_file(file, "r"); 1141238405Sjkim 1142238405Sjkim if (bio == NULL) 114368651Skris { 1144238405Sjkim BIO_printf(err, "Error opening %s %s\n", 1145238405Sjkim desc, file ? file : "stdin"); 1146238405Sjkim ERR_print_errors(err); 1147238405Sjkim return 0; 1148238405Sjkim } 1149238405Sjkim 1150238405Sjkim xis = PEM_X509_INFO_read_bio(bio, NULL, 1151238405Sjkim (pem_password_cb *)password_callback, &cb_data); 1152238405Sjkim 1153238405Sjkim BIO_free(bio); 1154238405Sjkim 1155238405Sjkim if (pcerts) 1156238405Sjkim { 1157238405Sjkim *pcerts = sk_X509_new_null(); 1158238405Sjkim if (!*pcerts) 115968651Skris goto end; 116068651Skris } 116168651Skris 1162238405Sjkim if (pcrls) 116368651Skris { 1164238405Sjkim *pcrls = sk_X509_CRL_new_null(); 1165238405Sjkim if (!*pcrls) 1166238405Sjkim goto end; 1167238405Sjkim } 1168238405Sjkim 1169238405Sjkim for(i = 0; i < sk_X509_INFO_num(xis); i++) 1170238405Sjkim { 1171238405Sjkim xi = sk_X509_INFO_value (xis, i); 1172238405Sjkim if (xi->x509 && pcerts) 117368651Skris { 1174238405Sjkim if (!sk_X509_push(*pcerts, xi->x509)) 1175238405Sjkim goto end; 1176238405Sjkim xi->x509 = NULL; 117768651Skris } 1178238405Sjkim if (xi->crl && pcrls) 117968651Skris { 1180238405Sjkim if (!sk_X509_CRL_push(*pcrls, xi->crl)) 1181238405Sjkim goto end; 1182238405Sjkim xi->crl = NULL; 118368651Skris } 118468651Skris } 1185238405Sjkim 1186238405Sjkim if (pcerts && sk_X509_num(*pcerts) > 0) 1187238405Sjkim rv = 1; 1188238405Sjkim 1189238405Sjkim if (pcrls && sk_X509_CRL_num(*pcrls) > 0) 1190238405Sjkim rv = 1; 1191238405Sjkim 1192238405Sjkim end: 1193238405Sjkim 1194238405Sjkim if (xis) 1195238405Sjkim sk_X509_INFO_pop_free(xis, X509_INFO_free); 1196238405Sjkim 1197238405Sjkim if (rv == 0) 119868651Skris { 1199238405Sjkim if (pcerts) 1200238405Sjkim { 1201238405Sjkim sk_X509_pop_free(*pcerts, X509_free); 1202238405Sjkim *pcerts = NULL; 1203238405Sjkim } 1204238405Sjkim if (pcrls) 1205238405Sjkim { 1206238405Sjkim sk_X509_CRL_pop_free(*pcrls, X509_CRL_free); 1207238405Sjkim *pcrls = NULL; 1208238405Sjkim } 1209238405Sjkim BIO_printf(err,"unable to load %s\n", 1210238405Sjkim pcerts ? "certificates" : "CRLs"); 121168651Skris ERR_print_errors(err); 121268651Skris } 1213238405Sjkim return rv; 121468651Skris } 121568651Skris 1216238405SjkimSTACK_OF(X509) *load_certs(BIO *err, const char *file, int format, 1217238405Sjkim const char *pass, ENGINE *e, const char *desc) 1218238405Sjkim { 1219238405Sjkim STACK_OF(X509) *certs; 1220238405Sjkim if (!load_certs_crls(err, file, format, pass, e, desc, &certs, NULL)) 1221238405Sjkim return NULL; 1222238405Sjkim return certs; 1223238405Sjkim } 122468651Skris 1225238405SjkimSTACK_OF(X509_CRL) *load_crls(BIO *err, const char *file, int format, 1226238405Sjkim const char *pass, ENGINE *e, const char *desc) 1227238405Sjkim { 1228238405Sjkim STACK_OF(X509_CRL) *crls; 1229238405Sjkim if (!load_certs_crls(err, file, format, pass, e, desc, NULL, &crls)) 1230238405Sjkim return NULL; 1231238405Sjkim return crls; 1232238405Sjkim } 1233238405Sjkim 1234109998Smarkm#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) 1235109998Smarkm/* Return error for unknown extensions */ 1236109998Smarkm#define X509V3_EXT_DEFAULT 0 1237109998Smarkm/* Print error for unknown extensions */ 1238109998Smarkm#define X509V3_EXT_ERROR_UNKNOWN (1L << 16) 1239109998Smarkm/* ASN1 parse unknown extensions */ 1240109998Smarkm#define X509V3_EXT_PARSE_UNKNOWN (2L << 16) 1241109998Smarkm/* BIO_dump unknown extensions */ 1242109998Smarkm#define X509V3_EXT_DUMP_UNKNOWN (3L << 16) 1243109998Smarkm 1244109998Smarkm#define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \ 1245109998Smarkm X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION) 1246109998Smarkm 1247109998Smarkmint set_cert_ex(unsigned long *flags, const char *arg) 1248109998Smarkm{ 1249109998Smarkm static const NAME_EX_TBL cert_tbl[] = { 1250109998Smarkm { "compatible", X509_FLAG_COMPAT, 0xffffffffl}, 1251109998Smarkm { "ca_default", X509_FLAG_CA, 0xffffffffl}, 1252109998Smarkm { "no_header", X509_FLAG_NO_HEADER, 0}, 1253109998Smarkm { "no_version", X509_FLAG_NO_VERSION, 0}, 1254109998Smarkm { "no_serial", X509_FLAG_NO_SERIAL, 0}, 1255109998Smarkm { "no_signame", X509_FLAG_NO_SIGNAME, 0}, 1256109998Smarkm { "no_validity", X509_FLAG_NO_VALIDITY, 0}, 1257109998Smarkm { "no_subject", X509_FLAG_NO_SUBJECT, 0}, 1258109998Smarkm { "no_issuer", X509_FLAG_NO_ISSUER, 0}, 1259109998Smarkm { "no_pubkey", X509_FLAG_NO_PUBKEY, 0}, 1260109998Smarkm { "no_extensions", X509_FLAG_NO_EXTENSIONS, 0}, 1261109998Smarkm { "no_sigdump", X509_FLAG_NO_SIGDUMP, 0}, 1262109998Smarkm { "no_aux", X509_FLAG_NO_AUX, 0}, 1263109998Smarkm { "no_attributes", X509_FLAG_NO_ATTRIBUTES, 0}, 1264109998Smarkm { "ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK}, 1265109998Smarkm { "ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, 1266109998Smarkm { "ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, 1267109998Smarkm { "ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, 1268109998Smarkm { NULL, 0, 0} 1269109998Smarkm }; 1270109998Smarkm return set_multi_opts(flags, arg, cert_tbl); 1271109998Smarkm} 1272109998Smarkm 127368651Skrisint set_name_ex(unsigned long *flags, const char *arg) 127468651Skris{ 1275109998Smarkm static const NAME_EX_TBL ex_tbl[] = { 127668651Skris { "esc_2253", ASN1_STRFLGS_ESC_2253, 0}, 127768651Skris { "esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0}, 127868651Skris { "esc_msb", ASN1_STRFLGS_ESC_MSB, 0}, 127968651Skris { "use_quote", ASN1_STRFLGS_ESC_QUOTE, 0}, 128068651Skris { "utf8", ASN1_STRFLGS_UTF8_CONVERT, 0}, 128168651Skris { "ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0}, 128268651Skris { "show_type", ASN1_STRFLGS_SHOW_TYPE, 0}, 128368651Skris { "dump_all", ASN1_STRFLGS_DUMP_ALL, 0}, 128468651Skris { "dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0}, 128568651Skris { "dump_der", ASN1_STRFLGS_DUMP_DER, 0}, 128668651Skris { "compat", XN_FLAG_COMPAT, 0xffffffffL}, 128768651Skris { "sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK}, 128868651Skris { "sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK}, 128968651Skris { "sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK}, 129068651Skris { "sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK}, 129168651Skris { "dn_rev", XN_FLAG_DN_REV, 0}, 129268651Skris { "nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK}, 129368651Skris { "sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK}, 129468651Skris { "lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK}, 1295109998Smarkm { "align", XN_FLAG_FN_ALIGN, 0}, 129668651Skris { "oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK}, 129768651Skris { "space_eq", XN_FLAG_SPC_EQ, 0}, 129868651Skris { "dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0}, 129968651Skris { "RFC2253", XN_FLAG_RFC2253, 0xffffffffL}, 130068651Skris { "oneline", XN_FLAG_ONELINE, 0xffffffffL}, 130168651Skris { "multiline", XN_FLAG_MULTILINE, 0xffffffffL}, 1302109998Smarkm { "ca_default", XN_FLAG_MULTILINE, 0xffffffffL}, 130368651Skris { NULL, 0, 0} 130468651Skris }; 1305109998Smarkm return set_multi_opts(flags, arg, ex_tbl); 1306109998Smarkm} 130768651Skris 1308109998Smarkmint set_ext_copy(int *copy_type, const char *arg) 1309109998Smarkm{ 1310109998Smarkm if (!strcasecmp(arg, "none")) 1311109998Smarkm *copy_type = EXT_COPY_NONE; 1312109998Smarkm else if (!strcasecmp(arg, "copy")) 1313109998Smarkm *copy_type = EXT_COPY_ADD; 1314109998Smarkm else if (!strcasecmp(arg, "copyall")) 1315109998Smarkm *copy_type = EXT_COPY_ALL; 1316109998Smarkm else 1317109998Smarkm return 0; 1318109998Smarkm return 1; 1319109998Smarkm} 1320109998Smarkm 1321109998Smarkmint copy_extensions(X509 *x, X509_REQ *req, int copy_type) 1322109998Smarkm{ 1323109998Smarkm STACK_OF(X509_EXTENSION) *exts = NULL; 1324109998Smarkm X509_EXTENSION *ext, *tmpext; 1325109998Smarkm ASN1_OBJECT *obj; 1326109998Smarkm int i, idx, ret = 0; 1327109998Smarkm if (!x || !req || (copy_type == EXT_COPY_NONE)) 1328109998Smarkm return 1; 1329109998Smarkm exts = X509_REQ_get_extensions(req); 1330109998Smarkm 1331109998Smarkm for(i = 0; i < sk_X509_EXTENSION_num(exts); i++) { 1332109998Smarkm ext = sk_X509_EXTENSION_value(exts, i); 1333109998Smarkm obj = X509_EXTENSION_get_object(ext); 1334109998Smarkm idx = X509_get_ext_by_OBJ(x, obj, -1); 1335109998Smarkm /* Does extension exist? */ 1336109998Smarkm if (idx != -1) { 1337109998Smarkm /* If normal copy don't override existing extension */ 1338109998Smarkm if (copy_type == EXT_COPY_ADD) 1339109998Smarkm continue; 1340109998Smarkm /* Delete all extensions of same type */ 1341109998Smarkm do { 1342109998Smarkm tmpext = X509_get_ext(x, idx); 1343109998Smarkm X509_delete_ext(x, idx); 1344109998Smarkm X509_EXTENSION_free(tmpext); 1345109998Smarkm idx = X509_get_ext_by_OBJ(x, obj, -1); 1346109998Smarkm } while (idx != -1); 1347109998Smarkm } 1348109998Smarkm if (!X509_add_ext(x, ext, -1)) 1349109998Smarkm goto end; 1350109998Smarkm } 1351109998Smarkm 1352109998Smarkm ret = 1; 1353109998Smarkm 1354109998Smarkm end: 1355109998Smarkm 1356109998Smarkm sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); 1357109998Smarkm 1358109998Smarkm return ret; 1359109998Smarkm} 1360109998Smarkm 1361109998Smarkm 1362109998Smarkm 1363109998Smarkm 1364109998Smarkmstatic int set_multi_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl) 1365109998Smarkm{ 1366109998Smarkm STACK_OF(CONF_VALUE) *vals; 1367109998Smarkm CONF_VALUE *val; 1368109998Smarkm int i, ret = 1; 1369109998Smarkm if(!arg) return 0; 1370109998Smarkm vals = X509V3_parse_list(arg); 1371109998Smarkm for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { 1372109998Smarkm val = sk_CONF_VALUE_value(vals, i); 1373109998Smarkm if (!set_table_opts(flags, val->name, in_tbl)) 1374109998Smarkm ret = 0; 1375109998Smarkm } 1376109998Smarkm sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); 1377109998Smarkm return ret; 1378109998Smarkm} 1379109998Smarkm 1380109998Smarkmstatic int set_table_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl) 1381109998Smarkm{ 1382109998Smarkm char c; 1383109998Smarkm const NAME_EX_TBL *ptbl; 138468651Skris c = arg[0]; 138568651Skris 138668651Skris if(c == '-') { 138768651Skris c = 0; 138868651Skris arg++; 138968651Skris } else if (c == '+') { 139068651Skris c = 1; 139168651Skris arg++; 139268651Skris } else c = 1; 139368651Skris 1394109998Smarkm for(ptbl = in_tbl; ptbl->name; ptbl++) { 1395109998Smarkm if(!strcasecmp(arg, ptbl->name)) { 139668651Skris *flags &= ~ptbl->mask; 139768651Skris if(c) *flags |= ptbl->flag; 139868651Skris else *flags &= ~ptbl->flag; 139968651Skris return 1; 140068651Skris } 140168651Skris } 140268651Skris return 0; 140368651Skris} 140468651Skris 1405160814Ssimonvoid print_name(BIO *out, const char *title, X509_NAME *nm, unsigned long lflags) 140668651Skris{ 1407100936Snectar char *buf; 140868651Skris char mline = 0; 140968651Skris int indent = 0; 1410109998Smarkm 141168651Skris if(title) BIO_puts(out, title); 141268651Skris if((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { 141368651Skris mline = 1; 141468651Skris indent = 4; 141568651Skris } 141668651Skris if(lflags == XN_FLAG_COMPAT) { 1417100936Snectar buf = X509_NAME_oneline(nm, 0, 0); 1418100936Snectar BIO_puts(out, buf); 141968651Skris BIO_puts(out, "\n"); 1420100936Snectar OPENSSL_free(buf); 142168651Skris } else { 142268651Skris if(mline) BIO_puts(out, "\n"); 142368651Skris X509_NAME_print_ex(out, nm, indent, lflags); 142468651Skris BIO_puts(out, "\n"); 142568651Skris } 142668651Skris} 142768651Skris 1428109998SmarkmX509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath) 1429109998Smarkm{ 1430109998Smarkm X509_STORE *store; 1431109998Smarkm X509_LOOKUP *lookup; 1432109998Smarkm if(!(store = X509_STORE_new())) goto end; 1433109998Smarkm lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file()); 1434109998Smarkm if (lookup == NULL) goto end; 1435109998Smarkm if (CAfile) { 1436109998Smarkm if(!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) { 1437109998Smarkm BIO_printf(bp, "Error loading file %s\n", CAfile); 1438109998Smarkm goto end; 1439109998Smarkm } 1440109998Smarkm } else X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT); 1441109998Smarkm 1442109998Smarkm lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir()); 1443109998Smarkm if (lookup == NULL) goto end; 1444109998Smarkm if (CApath) { 1445109998Smarkm if(!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) { 1446109998Smarkm BIO_printf(bp, "Error loading directory %s\n", CApath); 1447109998Smarkm goto end; 1448109998Smarkm } 1449109998Smarkm } else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT); 1450109998Smarkm 1451109998Smarkm ERR_clear_error(); 1452109998Smarkm return store; 1453109998Smarkm end: 1454109998Smarkm X509_STORE_free(store); 1455109998Smarkm return NULL; 1456109998Smarkm} 1457109998Smarkm 1458111147Snectar#ifndef OPENSSL_NO_ENGINE 1459109998Smarkm/* Try to load an engine in a shareable library */ 1460109998Smarkmstatic ENGINE *try_load_engine(BIO *err, const char *engine, int debug) 1461109998Smarkm { 1462109998Smarkm ENGINE *e = ENGINE_by_id("dynamic"); 1463109998Smarkm if (e) 1464109998Smarkm { 1465109998Smarkm if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0) 1466109998Smarkm || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) 1467109998Smarkm { 1468109998Smarkm ENGINE_free(e); 1469109998Smarkm e = NULL; 1470109998Smarkm } 1471109998Smarkm } 1472109998Smarkm return e; 1473109998Smarkm } 1474109998Smarkm 1475109998SmarkmENGINE *setup_engine(BIO *err, const char *engine, int debug) 1476109998Smarkm { 1477109998Smarkm ENGINE *e = NULL; 1478109998Smarkm 1479109998Smarkm if (engine) 1480109998Smarkm { 1481109998Smarkm if(strcmp(engine, "auto") == 0) 1482109998Smarkm { 1483109998Smarkm BIO_printf(err,"enabling auto ENGINE support\n"); 1484109998Smarkm ENGINE_register_all_complete(); 1485109998Smarkm return NULL; 1486109998Smarkm } 1487109998Smarkm if((e = ENGINE_by_id(engine)) == NULL 1488109998Smarkm && (e = try_load_engine(err, engine, debug)) == NULL) 1489109998Smarkm { 1490109998Smarkm BIO_printf(err,"invalid engine \"%s\"\n", engine); 1491109998Smarkm ERR_print_errors(err); 1492109998Smarkm return NULL; 1493109998Smarkm } 1494109998Smarkm if (debug) 1495109998Smarkm { 1496109998Smarkm ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM, 1497109998Smarkm 0, err, 0); 1498109998Smarkm } 1499109998Smarkm ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, ui_method, 0, 1); 1500109998Smarkm if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) 1501109998Smarkm { 1502109998Smarkm BIO_printf(err,"can't use that engine\n"); 1503109998Smarkm ERR_print_errors(err); 1504109998Smarkm ENGINE_free(e); 1505109998Smarkm return NULL; 1506109998Smarkm } 1507109998Smarkm 1508109998Smarkm BIO_printf(err,"engine \"%s\" set.\n", ENGINE_get_id(e)); 1509109998Smarkm 1510109998Smarkm /* Free our "structural" reference. */ 1511109998Smarkm ENGINE_free(e); 1512109998Smarkm } 1513109998Smarkm return e; 1514109998Smarkm } 1515111147Snectar#endif 1516109998Smarkm 1517109998Smarkmint load_config(BIO *err, CONF *cnf) 1518109998Smarkm { 1519238405Sjkim static int load_config_called = 0; 1520238405Sjkim if (load_config_called) 1521238405Sjkim return 1; 1522238405Sjkim load_config_called = 1; 1523109998Smarkm if (!cnf) 1524109998Smarkm cnf = config; 1525109998Smarkm if (!cnf) 1526109998Smarkm return 1; 1527109998Smarkm 1528109998Smarkm OPENSSL_load_builtin_modules(); 1529109998Smarkm 1530109998Smarkm if (CONF_modules_load(cnf, NULL, 0) <= 0) 1531109998Smarkm { 1532109998Smarkm BIO_printf(err, "Error configuring OpenSSL\n"); 1533109998Smarkm ERR_print_errors(err); 1534109998Smarkm return 0; 1535109998Smarkm } 1536109998Smarkm return 1; 1537109998Smarkm } 1538109998Smarkm 1539109998Smarkmchar *make_config_name() 1540109998Smarkm { 1541109998Smarkm const char *t=X509_get_default_cert_area(); 1542127128Snectar size_t len; 1543109998Smarkm char *p; 1544109998Smarkm 1545127128Snectar len=strlen(t)+strlen(OPENSSL_CONF)+2; 1546127128Snectar p=OPENSSL_malloc(len); 1547279264Sdelphij if (p == NULL) 1548279264Sdelphij return NULL; 1549127128Snectar BUF_strlcpy(p,t,len); 1550109998Smarkm#ifndef OPENSSL_SYS_VMS 1551127128Snectar BUF_strlcat(p,"/",len); 1552109998Smarkm#endif 1553127128Snectar BUF_strlcat(p,OPENSSL_CONF,len); 1554109998Smarkm 1555109998Smarkm return p; 1556109998Smarkm } 1557127128Snectar 1558238405Sjkimstatic unsigned long index_serial_hash(const OPENSSL_CSTRING *a) 1559127128Snectar { 1560127128Snectar const char *n; 1561127128Snectar 1562127128Snectar n=a[DB_serial]; 1563127128Snectar while (*n == '0') n++; 1564127128Snectar return(lh_strhash(n)); 1565127128Snectar } 1566127128Snectar 1567238405Sjkimstatic int index_serial_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b) 1568127128Snectar { 1569127128Snectar const char *aa,*bb; 1570127128Snectar 1571127128Snectar for (aa=a[DB_serial]; *aa == '0'; aa++); 1572127128Snectar for (bb=b[DB_serial]; *bb == '0'; bb++); 1573127128Snectar return(strcmp(aa,bb)); 1574127128Snectar } 1575127128Snectar 1576127128Snectarstatic int index_name_qual(char **a) 1577127128Snectar { return(a[0][0] == 'V'); } 1578127128Snectar 1579238405Sjkimstatic unsigned long index_name_hash(const OPENSSL_CSTRING *a) 1580127128Snectar { return(lh_strhash(a[DB_name])); } 1581127128Snectar 1582238405Sjkimint index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b) 1583238405Sjkim { return(strcmp(a[DB_name], b[DB_name])); } 1584127128Snectar 1585238405Sjkimstatic IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING) 1586238405Sjkimstatic IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING) 1587238405Sjkimstatic IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING) 1588238405Sjkimstatic IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING) 1589127128Snectar 1590127128Snectar#undef BSIZE 1591127128Snectar#define BSIZE 256 1592127128Snectar 1593127128SnectarBIGNUM *load_serial(char *serialfile, int create, ASN1_INTEGER **retai) 1594127128Snectar { 1595127128Snectar BIO *in=NULL; 1596127128Snectar BIGNUM *ret=NULL; 1597127128Snectar MS_STATIC char buf[1024]; 1598127128Snectar ASN1_INTEGER *ai=NULL; 1599127128Snectar 1600127128Snectar ai=ASN1_INTEGER_new(); 1601127128Snectar if (ai == NULL) goto err; 1602127128Snectar 1603127128Snectar if ((in=BIO_new(BIO_s_file())) == NULL) 1604127128Snectar { 1605127128Snectar ERR_print_errors(bio_err); 1606127128Snectar goto err; 1607127128Snectar } 1608127128Snectar 1609127128Snectar if (BIO_read_filename(in,serialfile) <= 0) 1610127128Snectar { 1611127128Snectar if (!create) 1612127128Snectar { 1613127128Snectar perror(serialfile); 1614127128Snectar goto err; 1615127128Snectar } 1616127128Snectar else 1617127128Snectar { 1618127128Snectar ret=BN_new(); 1619142425Snectar if (ret == NULL || !rand_serial(ret, ai)) 1620127128Snectar BIO_printf(bio_err, "Out of memory\n"); 1621127128Snectar } 1622127128Snectar } 1623127128Snectar else 1624127128Snectar { 1625127128Snectar if (!a2i_ASN1_INTEGER(in,ai,buf,1024)) 1626127128Snectar { 1627127128Snectar BIO_printf(bio_err,"unable to load number from %s\n", 1628127128Snectar serialfile); 1629127128Snectar goto err; 1630127128Snectar } 1631127128Snectar ret=ASN1_INTEGER_to_BN(ai,NULL); 1632127128Snectar if (ret == NULL) 1633127128Snectar { 1634127128Snectar BIO_printf(bio_err,"error converting number from bin to BIGNUM\n"); 1635127128Snectar goto err; 1636127128Snectar } 1637127128Snectar } 1638127128Snectar 1639127128Snectar if (ret && retai) 1640127128Snectar { 1641127128Snectar *retai = ai; 1642127128Snectar ai = NULL; 1643127128Snectar } 1644127128Snectar err: 1645127128Snectar if (in != NULL) BIO_free(in); 1646127128Snectar if (ai != NULL) ASN1_INTEGER_free(ai); 1647127128Snectar return(ret); 1648127128Snectar } 1649127128Snectar 1650127128Snectarint save_serial(char *serialfile, char *suffix, BIGNUM *serial, ASN1_INTEGER **retai) 1651127128Snectar { 1652127128Snectar char buf[1][BSIZE]; 1653127128Snectar BIO *out = NULL; 1654127128Snectar int ret=0; 1655127128Snectar ASN1_INTEGER *ai=NULL; 1656127128Snectar int j; 1657127128Snectar 1658127128Snectar if (suffix == NULL) 1659127128Snectar j = strlen(serialfile); 1660127128Snectar else 1661127128Snectar j = strlen(serialfile) + strlen(suffix) + 1; 1662127128Snectar if (j >= BSIZE) 1663127128Snectar { 1664127128Snectar BIO_printf(bio_err,"file name too long\n"); 1665127128Snectar goto err; 1666127128Snectar } 1667127128Snectar 1668127128Snectar if (suffix == NULL) 1669127128Snectar BUF_strlcpy(buf[0], serialfile, BSIZE); 1670127128Snectar else 1671127128Snectar { 1672127128Snectar#ifndef OPENSSL_SYS_VMS 1673127128Snectar j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", serialfile, suffix); 1674127128Snectar#else 1675127128Snectar j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", serialfile, suffix); 1676127128Snectar#endif 1677127128Snectar } 1678127128Snectar#ifdef RL_DEBUG 1679127128Snectar BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[0]); 1680127128Snectar#endif 1681127128Snectar out=BIO_new(BIO_s_file()); 1682127128Snectar if (out == NULL) 1683127128Snectar { 1684127128Snectar ERR_print_errors(bio_err); 1685127128Snectar goto err; 1686127128Snectar } 1687127128Snectar if (BIO_write_filename(out,buf[0]) <= 0) 1688127128Snectar { 1689127128Snectar perror(serialfile); 1690127128Snectar goto err; 1691127128Snectar } 1692127128Snectar 1693127128Snectar if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL) 1694127128Snectar { 1695127128Snectar BIO_printf(bio_err,"error converting serial to ASN.1 format\n"); 1696127128Snectar goto err; 1697127128Snectar } 1698127128Snectar i2a_ASN1_INTEGER(out,ai); 1699127128Snectar BIO_puts(out,"\n"); 1700127128Snectar ret=1; 1701127128Snectar if (retai) 1702127128Snectar { 1703127128Snectar *retai = ai; 1704127128Snectar ai = NULL; 1705127128Snectar } 1706127128Snectarerr: 1707127128Snectar if (out != NULL) BIO_free_all(out); 1708127128Snectar if (ai != NULL) ASN1_INTEGER_free(ai); 1709127128Snectar return(ret); 1710127128Snectar } 1711127128Snectar 1712127128Snectarint rotate_serial(char *serialfile, char *new_suffix, char *old_suffix) 1713127128Snectar { 1714127128Snectar char buf[5][BSIZE]; 1715127128Snectar int i,j; 1716127128Snectar 1717127128Snectar i = strlen(serialfile) + strlen(old_suffix); 1718127128Snectar j = strlen(serialfile) + strlen(new_suffix); 1719127128Snectar if (i > j) j = i; 1720127128Snectar if (j + 1 >= BSIZE) 1721127128Snectar { 1722127128Snectar BIO_printf(bio_err,"file name too long\n"); 1723127128Snectar goto err; 1724127128Snectar } 1725127128Snectar 1726127128Snectar#ifndef OPENSSL_SYS_VMS 1727127128Snectar j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", 1728127128Snectar serialfile, new_suffix); 1729127128Snectar#else 1730127128Snectar j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", 1731127128Snectar serialfile, new_suffix); 1732127128Snectar#endif 1733127128Snectar#ifndef OPENSSL_SYS_VMS 1734127128Snectar j = BIO_snprintf(buf[1], sizeof buf[1], "%s.%s", 1735127128Snectar serialfile, old_suffix); 1736127128Snectar#else 1737127128Snectar j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s", 1738127128Snectar serialfile, old_suffix); 1739127128Snectar#endif 1740238405Sjkim#ifdef RL_DEBUG 1741238405Sjkim BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", 1742238405Sjkim serialfile, buf[1]); 1743238405Sjkim#endif 1744238405Sjkim if (rename(serialfile,buf[1]) < 0 && errno != ENOENT 1745127128Snectar#ifdef ENOTDIR 1746160814Ssimon && errno != ENOTDIR 1747127128Snectar#endif 1748238405Sjkim ) { 1749127128Snectar BIO_printf(bio_err, 1750127128Snectar "unable to rename %s to %s\n", 1751127128Snectar serialfile, buf[1]); 1752127128Snectar perror("reason"); 1753127128Snectar goto err; 1754127128Snectar } 1755127128Snectar#ifdef RL_DEBUG 1756127128Snectar BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", 1757127128Snectar buf[0],serialfile); 1758127128Snectar#endif 1759127128Snectar if (rename(buf[0],serialfile) < 0) 1760127128Snectar { 1761127128Snectar BIO_printf(bio_err, 1762127128Snectar "unable to rename %s to %s\n", 1763127128Snectar buf[0],serialfile); 1764127128Snectar perror("reason"); 1765127128Snectar rename(buf[1],serialfile); 1766127128Snectar goto err; 1767127128Snectar } 1768127128Snectar return 1; 1769127128Snectar err: 1770127128Snectar return 0; 1771127128Snectar } 1772127128Snectar 1773142425Snectarint rand_serial(BIGNUM *b, ASN1_INTEGER *ai) 1774142425Snectar { 1775142425Snectar BIGNUM *btmp; 1776142425Snectar int ret = 0; 1777142425Snectar if (b) 1778142425Snectar btmp = b; 1779142425Snectar else 1780142425Snectar btmp = BN_new(); 1781142425Snectar 1782142425Snectar if (!btmp) 1783142425Snectar return 0; 1784142425Snectar 1785142425Snectar if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) 1786142425Snectar goto error; 1787142425Snectar if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) 1788142425Snectar goto error; 1789142425Snectar 1790142425Snectar ret = 1; 1791142425Snectar 1792142425Snectar error: 1793142425Snectar 1794142425Snectar if (!b) 1795142425Snectar BN_free(btmp); 1796142425Snectar 1797142425Snectar return ret; 1798142425Snectar } 1799142425Snectar 1800127128SnectarCA_DB *load_index(char *dbfile, DB_ATTR *db_attr) 1801127128Snectar { 1802127128Snectar CA_DB *retdb = NULL; 1803127128Snectar TXT_DB *tmpdb = NULL; 1804127128Snectar BIO *in = BIO_new(BIO_s_file()); 1805127128Snectar CONF *dbattr_conf = NULL; 1806127128Snectar char buf[1][BSIZE]; 1807127128Snectar long errorline= -1; 1808127128Snectar 1809127128Snectar if (in == NULL) 1810127128Snectar { 1811127128Snectar ERR_print_errors(bio_err); 1812127128Snectar goto err; 1813127128Snectar } 1814127128Snectar if (BIO_read_filename(in,dbfile) <= 0) 1815127128Snectar { 1816127128Snectar perror(dbfile); 1817127128Snectar BIO_printf(bio_err,"unable to open '%s'\n",dbfile); 1818127128Snectar goto err; 1819127128Snectar } 1820127128Snectar if ((tmpdb = TXT_DB_read(in,DB_NUMBER)) == NULL) 1821127128Snectar goto err; 1822127128Snectar 1823127128Snectar#ifndef OPENSSL_SYS_VMS 1824127128Snectar BIO_snprintf(buf[0], sizeof buf[0], "%s.attr", dbfile); 1825127128Snectar#else 1826127128Snectar BIO_snprintf(buf[0], sizeof buf[0], "%s-attr", dbfile); 1827127128Snectar#endif 1828127128Snectar dbattr_conf = NCONF_new(NULL); 1829127128Snectar if (NCONF_load(dbattr_conf,buf[0],&errorline) <= 0) 1830127128Snectar { 1831127128Snectar if (errorline > 0) 1832127128Snectar { 1833127128Snectar BIO_printf(bio_err, 1834127128Snectar "error on line %ld of db attribute file '%s'\n" 1835127128Snectar ,errorline,buf[0]); 1836127128Snectar goto err; 1837127128Snectar } 1838127128Snectar else 1839127128Snectar { 1840127128Snectar NCONF_free(dbattr_conf); 1841127128Snectar dbattr_conf = NULL; 1842127128Snectar } 1843127128Snectar } 1844127128Snectar 1845127128Snectar if ((retdb = OPENSSL_malloc(sizeof(CA_DB))) == NULL) 1846127128Snectar { 1847127128Snectar fprintf(stderr, "Out of memory\n"); 1848127128Snectar goto err; 1849127128Snectar } 1850127128Snectar 1851127128Snectar retdb->db = tmpdb; 1852127128Snectar tmpdb = NULL; 1853127128Snectar if (db_attr) 1854127128Snectar retdb->attributes = *db_attr; 1855127128Snectar else 1856127128Snectar { 1857127128Snectar retdb->attributes.unique_subject = 1; 1858127128Snectar } 1859127128Snectar 1860127128Snectar if (dbattr_conf) 1861127128Snectar { 1862127128Snectar char *p = NCONF_get_string(dbattr_conf,NULL,"unique_subject"); 1863127128Snectar if (p) 1864127128Snectar { 1865160814Ssimon#ifdef RL_DEBUG 1866127128Snectar BIO_printf(bio_err, "DEBUG[load_index]: unique_subject = \"%s\"\n", p); 1867160814Ssimon#endif 1868160814Ssimon retdb->attributes.unique_subject = parse_yesno(p,1); 1869127128Snectar } 1870127128Snectar } 1871127128Snectar 1872127128Snectar err: 1873127128Snectar if (dbattr_conf) NCONF_free(dbattr_conf); 1874127128Snectar if (tmpdb) TXT_DB_free(tmpdb); 1875127128Snectar if (in) BIO_free_all(in); 1876127128Snectar return retdb; 1877127128Snectar } 1878127128Snectar 1879127128Snectarint index_index(CA_DB *db) 1880127128Snectar { 1881127128Snectar if (!TXT_DB_create_index(db->db, DB_serial, NULL, 1882238405Sjkim LHASH_HASH_FN(index_serial), 1883238405Sjkim LHASH_COMP_FN(index_serial))) 1884127128Snectar { 1885127128Snectar BIO_printf(bio_err, 1886127128Snectar "error creating serial number index:(%ld,%ld,%ld)\n", 1887127128Snectar db->db->error,db->db->arg1,db->db->arg2); 1888127128Snectar return 0; 1889127128Snectar } 1890127128Snectar 1891127128Snectar if (db->attributes.unique_subject 1892127128Snectar && !TXT_DB_create_index(db->db, DB_name, index_name_qual, 1893238405Sjkim LHASH_HASH_FN(index_name), 1894238405Sjkim LHASH_COMP_FN(index_name))) 1895127128Snectar { 1896127128Snectar BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n", 1897127128Snectar db->db->error,db->db->arg1,db->db->arg2); 1898127128Snectar return 0; 1899127128Snectar } 1900127128Snectar return 1; 1901127128Snectar } 1902127128Snectar 1903160814Ssimonint save_index(const char *dbfile, const char *suffix, CA_DB *db) 1904127128Snectar { 1905127128Snectar char buf[3][BSIZE]; 1906127128Snectar BIO *out = BIO_new(BIO_s_file()); 1907127128Snectar int j; 1908127128Snectar 1909127128Snectar if (out == NULL) 1910127128Snectar { 1911127128Snectar ERR_print_errors(bio_err); 1912127128Snectar goto err; 1913127128Snectar } 1914127128Snectar 1915127128Snectar j = strlen(dbfile) + strlen(suffix); 1916127128Snectar if (j + 6 >= BSIZE) 1917127128Snectar { 1918127128Snectar BIO_printf(bio_err,"file name too long\n"); 1919127128Snectar goto err; 1920127128Snectar } 1921127128Snectar 1922127128Snectar#ifndef OPENSSL_SYS_VMS 1923127128Snectar j = BIO_snprintf(buf[2], sizeof buf[2], "%s.attr", dbfile); 1924127128Snectar#else 1925127128Snectar j = BIO_snprintf(buf[2], sizeof buf[2], "%s-attr", dbfile); 1926127128Snectar#endif 1927127128Snectar#ifndef OPENSSL_SYS_VMS 1928127128Snectar j = BIO_snprintf(buf[1], sizeof buf[1], "%s.attr.%s", dbfile, suffix); 1929127128Snectar#else 1930127128Snectar j = BIO_snprintf(buf[1], sizeof buf[1], "%s-attr-%s", dbfile, suffix); 1931127128Snectar#endif 1932127128Snectar#ifndef OPENSSL_SYS_VMS 1933127128Snectar j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", dbfile, suffix); 1934127128Snectar#else 1935127128Snectar j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", dbfile, suffix); 1936127128Snectar#endif 1937127128Snectar#ifdef RL_DEBUG 1938127128Snectar BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[0]); 1939127128Snectar#endif 1940127128Snectar if (BIO_write_filename(out,buf[0]) <= 0) 1941127128Snectar { 1942127128Snectar perror(dbfile); 1943127128Snectar BIO_printf(bio_err,"unable to open '%s'\n", dbfile); 1944127128Snectar goto err; 1945127128Snectar } 1946127128Snectar j=TXT_DB_write(out,db->db); 1947127128Snectar if (j <= 0) goto err; 1948127128Snectar 1949127128Snectar BIO_free(out); 1950127128Snectar 1951127128Snectar out = BIO_new(BIO_s_file()); 1952127128Snectar#ifdef RL_DEBUG 1953127128Snectar BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[1]); 1954127128Snectar#endif 1955127128Snectar if (BIO_write_filename(out,buf[1]) <= 0) 1956127128Snectar { 1957127128Snectar perror(buf[2]); 1958127128Snectar BIO_printf(bio_err,"unable to open '%s'\n", buf[2]); 1959127128Snectar goto err; 1960127128Snectar } 1961127128Snectar BIO_printf(out,"unique_subject = %s\n", 1962127128Snectar db->attributes.unique_subject ? "yes" : "no"); 1963127128Snectar BIO_free(out); 1964127128Snectar 1965127128Snectar return 1; 1966127128Snectar err: 1967127128Snectar return 0; 1968127128Snectar } 1969127128Snectar 1970160814Ssimonint rotate_index(const char *dbfile, const char *new_suffix, const char *old_suffix) 1971127128Snectar { 1972127128Snectar char buf[5][BSIZE]; 1973127128Snectar int i,j; 1974127128Snectar 1975127128Snectar i = strlen(dbfile) + strlen(old_suffix); 1976127128Snectar j = strlen(dbfile) + strlen(new_suffix); 1977127128Snectar if (i > j) j = i; 1978127128Snectar if (j + 6 >= BSIZE) 1979127128Snectar { 1980127128Snectar BIO_printf(bio_err,"file name too long\n"); 1981127128Snectar goto err; 1982127128Snectar } 1983127128Snectar 1984127128Snectar#ifndef OPENSSL_SYS_VMS 1985127128Snectar j = BIO_snprintf(buf[4], sizeof buf[4], "%s.attr", dbfile); 1986127128Snectar#else 1987127128Snectar j = BIO_snprintf(buf[4], sizeof buf[4], "%s-attr", dbfile); 1988127128Snectar#endif 1989127128Snectar#ifndef OPENSSL_SYS_VMS 1990127128Snectar j = BIO_snprintf(buf[2], sizeof buf[2], "%s.attr.%s", 1991127128Snectar dbfile, new_suffix); 1992127128Snectar#else 1993127128Snectar j = BIO_snprintf(buf[2], sizeof buf[2], "%s-attr-%s", 1994127128Snectar dbfile, new_suffix); 1995127128Snectar#endif 1996127128Snectar#ifndef OPENSSL_SYS_VMS 1997127128Snectar j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", 1998127128Snectar dbfile, new_suffix); 1999127128Snectar#else 2000127128Snectar j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", 2001127128Snectar dbfile, new_suffix); 2002127128Snectar#endif 2003127128Snectar#ifndef OPENSSL_SYS_VMS 2004127128Snectar j = BIO_snprintf(buf[1], sizeof buf[1], "%s.%s", 2005127128Snectar dbfile, old_suffix); 2006127128Snectar#else 2007127128Snectar j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s", 2008127128Snectar dbfile, old_suffix); 2009127128Snectar#endif 2010127128Snectar#ifndef OPENSSL_SYS_VMS 2011127128Snectar j = BIO_snprintf(buf[3], sizeof buf[3], "%s.attr.%s", 2012127128Snectar dbfile, old_suffix); 2013127128Snectar#else 2014127128Snectar j = BIO_snprintf(buf[3], sizeof buf[3], "%s-attr-%s", 2015127128Snectar dbfile, old_suffix); 2016127128Snectar#endif 2017238405Sjkim#ifdef RL_DEBUG 2018238405Sjkim BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", 2019238405Sjkim dbfile, buf[1]); 2020238405Sjkim#endif 2021238405Sjkim if (rename(dbfile,buf[1]) < 0 && errno != ENOENT 2022127128Snectar#ifdef ENOTDIR 2023238405Sjkim && errno != ENOTDIR 2024127128Snectar#endif 2025238405Sjkim ) { 2026127128Snectar BIO_printf(bio_err, 2027127128Snectar "unable to rename %s to %s\n", 2028127128Snectar dbfile, buf[1]); 2029127128Snectar perror("reason"); 2030127128Snectar goto err; 2031127128Snectar } 2032127128Snectar#ifdef RL_DEBUG 2033127128Snectar BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", 2034127128Snectar buf[0],dbfile); 2035127128Snectar#endif 2036127128Snectar if (rename(buf[0],dbfile) < 0) 2037127128Snectar { 2038127128Snectar BIO_printf(bio_err, 2039127128Snectar "unable to rename %s to %s\n", 2040127128Snectar buf[0],dbfile); 2041127128Snectar perror("reason"); 2042127128Snectar rename(buf[1],dbfile); 2043127128Snectar goto err; 2044127128Snectar } 2045238405Sjkim#ifdef RL_DEBUG 2046238405Sjkim BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", 2047238405Sjkim buf[4],buf[3]); 2048238405Sjkim#endif 2049238405Sjkim if (rename(buf[4],buf[3]) < 0 && errno != ENOENT 2050127128Snectar#ifdef ENOTDIR 2051238405Sjkim && errno != ENOTDIR 2052127128Snectar#endif 2053238405Sjkim ) { 2054127128Snectar BIO_printf(bio_err, 2055127128Snectar "unable to rename %s to %s\n", 2056127128Snectar buf[4], buf[3]); 2057127128Snectar perror("reason"); 2058127128Snectar rename(dbfile,buf[0]); 2059127128Snectar rename(buf[1],dbfile); 2060127128Snectar goto err; 2061127128Snectar } 2062127128Snectar#ifdef RL_DEBUG 2063127128Snectar BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n", 2064127128Snectar buf[2],buf[4]); 2065127128Snectar#endif 2066127128Snectar if (rename(buf[2],buf[4]) < 0) 2067127128Snectar { 2068127128Snectar BIO_printf(bio_err, 2069127128Snectar "unable to rename %s to %s\n", 2070127128Snectar buf[2],buf[4]); 2071127128Snectar perror("reason"); 2072127128Snectar rename(buf[3],buf[4]); 2073127128Snectar rename(dbfile,buf[0]); 2074127128Snectar rename(buf[1],dbfile); 2075127128Snectar goto err; 2076127128Snectar } 2077127128Snectar return 1; 2078127128Snectar err: 2079127128Snectar return 0; 2080127128Snectar } 2081127128Snectar 2082127128Snectarvoid free_index(CA_DB *db) 2083127128Snectar { 2084142425Snectar if (db) 2085142425Snectar { 2086142425Snectar if (db->db) TXT_DB_free(db->db); 2087142425Snectar OPENSSL_free(db); 2088142425Snectar } 2089127128Snectar } 2090142425Snectar 2091160814Ssimonint parse_yesno(const char *str, int def) 2092160814Ssimon { 2093160814Ssimon int ret = def; 2094160814Ssimon if (str) 2095160814Ssimon { 2096160814Ssimon switch (*str) 2097160814Ssimon { 2098160814Ssimon case 'f': /* false */ 2099160814Ssimon case 'F': /* FALSE */ 2100160814Ssimon case 'n': /* no */ 2101160814Ssimon case 'N': /* NO */ 2102160814Ssimon case '0': /* 0 */ 2103160814Ssimon ret = 0; 2104160814Ssimon break; 2105160814Ssimon case 't': /* true */ 2106160814Ssimon case 'T': /* TRUE */ 2107160814Ssimon case 'y': /* yes */ 2108160814Ssimon case 'Y': /* YES */ 2109160814Ssimon case '1': /* 1 */ 2110194206Ssimon ret = 1; 2111160814Ssimon break; 2112160814Ssimon default: 2113160814Ssimon ret = def; 2114160814Ssimon break; 2115160814Ssimon } 2116160814Ssimon } 2117160814Ssimon return ret; 2118160814Ssimon } 2119160814Ssimon 2120160814Ssimon/* 2121160814Ssimon * subject is expected to be in the format /type0=value0/type1=value1/type2=... 2122160814Ssimon * where characters may be escaped by \ 2123160814Ssimon */ 2124160814SsimonX509_NAME *parse_name(char *subject, long chtype, int multirdn) 2125160814Ssimon { 2126160814Ssimon size_t buflen = strlen(subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */ 2127160814Ssimon char *buf = OPENSSL_malloc(buflen); 2128160814Ssimon size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */ 2129160814Ssimon char **ne_types = OPENSSL_malloc(max_ne * sizeof (char *)); 2130160814Ssimon char **ne_values = OPENSSL_malloc(max_ne * sizeof (char *)); 2131160814Ssimon int *mval = OPENSSL_malloc (max_ne * sizeof (int)); 2132160814Ssimon 2133160814Ssimon char *sp = subject, *bp = buf; 2134160814Ssimon int i, ne_num = 0; 2135160814Ssimon 2136160814Ssimon X509_NAME *n = NULL; 2137160814Ssimon int nid; 2138160814Ssimon 2139246772Sjkim if (!buf || !ne_types || !ne_values || !mval) 2140160814Ssimon { 2141160814Ssimon BIO_printf(bio_err, "malloc error\n"); 2142160814Ssimon goto error; 2143160814Ssimon } 2144160814Ssimon 2145160814Ssimon if (*subject != '/') 2146160814Ssimon { 2147160814Ssimon BIO_printf(bio_err, "Subject does not start with '/'.\n"); 2148160814Ssimon goto error; 2149160814Ssimon } 2150160814Ssimon sp++; /* skip leading / */ 2151160814Ssimon 2152160814Ssimon /* no multivalued RDN by default */ 2153160814Ssimon mval[ne_num] = 0; 2154160814Ssimon 2155160814Ssimon while (*sp) 2156160814Ssimon { 2157160814Ssimon /* collect type */ 2158160814Ssimon ne_types[ne_num] = bp; 2159160814Ssimon while (*sp) 2160160814Ssimon { 2161160814Ssimon if (*sp == '\\') /* is there anything to escape in the type...? */ 2162160814Ssimon { 2163160814Ssimon if (*++sp) 2164160814Ssimon *bp++ = *sp++; 2165160814Ssimon else 2166160814Ssimon { 2167160814Ssimon BIO_printf(bio_err, "escape character at end of string\n"); 2168160814Ssimon goto error; 2169160814Ssimon } 2170160814Ssimon } 2171160814Ssimon else if (*sp == '=') 2172160814Ssimon { 2173160814Ssimon sp++; 2174160814Ssimon *bp++ = '\0'; 2175160814Ssimon break; 2176160814Ssimon } 2177160814Ssimon else 2178160814Ssimon *bp++ = *sp++; 2179160814Ssimon } 2180160814Ssimon if (!*sp) 2181160814Ssimon { 2182160814Ssimon BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num); 2183160814Ssimon goto error; 2184160814Ssimon } 2185160814Ssimon ne_values[ne_num] = bp; 2186160814Ssimon while (*sp) 2187160814Ssimon { 2188160814Ssimon if (*sp == '\\') 2189160814Ssimon { 2190160814Ssimon if (*++sp) 2191160814Ssimon *bp++ = *sp++; 2192160814Ssimon else 2193160814Ssimon { 2194160814Ssimon BIO_printf(bio_err, "escape character at end of string\n"); 2195160814Ssimon goto error; 2196160814Ssimon } 2197160814Ssimon } 2198160814Ssimon else if (*sp == '/') 2199160814Ssimon { 2200160814Ssimon sp++; 2201160814Ssimon /* no multivalued RDN by default */ 2202160814Ssimon mval[ne_num+1] = 0; 2203160814Ssimon break; 2204160814Ssimon } 2205160814Ssimon else if (*sp == '+' && multirdn) 2206160814Ssimon { 2207160814Ssimon /* a not escaped + signals a mutlivalued RDN */ 2208160814Ssimon sp++; 2209160814Ssimon mval[ne_num+1] = -1; 2210160814Ssimon break; 2211160814Ssimon } 2212160814Ssimon else 2213160814Ssimon *bp++ = *sp++; 2214160814Ssimon } 2215160814Ssimon *bp++ = '\0'; 2216160814Ssimon ne_num++; 2217160814Ssimon } 2218160814Ssimon 2219160814Ssimon if (!(n = X509_NAME_new())) 2220160814Ssimon goto error; 2221160814Ssimon 2222160814Ssimon for (i = 0; i < ne_num; i++) 2223160814Ssimon { 2224160814Ssimon if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef) 2225160814Ssimon { 2226160814Ssimon BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]); 2227160814Ssimon continue; 2228160814Ssimon } 2229160814Ssimon 2230160814Ssimon if (!*ne_values[i]) 2231160814Ssimon { 2232160814Ssimon BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]); 2233160814Ssimon continue; 2234160814Ssimon } 2235160814Ssimon 2236160814Ssimon if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,mval[i])) 2237160814Ssimon goto error; 2238160814Ssimon } 2239160814Ssimon 2240160814Ssimon OPENSSL_free(ne_values); 2241160814Ssimon OPENSSL_free(ne_types); 2242160814Ssimon OPENSSL_free(buf); 2243246772Sjkim OPENSSL_free(mval); 2244160814Ssimon return n; 2245160814Ssimon 2246160814Ssimonerror: 2247160814Ssimon X509_NAME_free(n); 2248160814Ssimon if (ne_values) 2249160814Ssimon OPENSSL_free(ne_values); 2250160814Ssimon if (ne_types) 2251160814Ssimon OPENSSL_free(ne_types); 2252246772Sjkim if (mval) 2253246772Sjkim OPENSSL_free(mval); 2254160814Ssimon if (buf) 2255160814Ssimon OPENSSL_free(buf); 2256160814Ssimon return NULL; 2257160814Ssimon} 2258160814Ssimon 2259160814Ssimonint args_verify(char ***pargs, int *pargc, 2260160814Ssimon int *badarg, BIO *err, X509_VERIFY_PARAM **pm) 2261160814Ssimon { 2262160814Ssimon ASN1_OBJECT *otmp = NULL; 2263160814Ssimon unsigned long flags = 0; 2264160814Ssimon int i; 2265238405Sjkim int purpose = 0, depth = -1; 2266160814Ssimon char **oldargs = *pargs; 2267160814Ssimon char *arg = **pargs, *argn = (*pargs)[1]; 2268238405Sjkim time_t at_time = 0; 2269160814Ssimon if (!strcmp(arg, "-policy")) 2270160814Ssimon { 2271160814Ssimon if (!argn) 2272160814Ssimon *badarg = 1; 2273160814Ssimon else 2274160814Ssimon { 2275160814Ssimon otmp = OBJ_txt2obj(argn, 0); 2276160814Ssimon if (!otmp) 2277160814Ssimon { 2278160814Ssimon BIO_printf(err, "Invalid Policy \"%s\"\n", 2279160814Ssimon argn); 2280160814Ssimon *badarg = 1; 2281160814Ssimon } 2282160814Ssimon } 2283160814Ssimon (*pargs)++; 2284160814Ssimon } 2285160814Ssimon else if (strcmp(arg,"-purpose") == 0) 2286160814Ssimon { 2287160814Ssimon X509_PURPOSE *xptmp; 2288160814Ssimon if (!argn) 2289160814Ssimon *badarg = 1; 2290160814Ssimon else 2291160814Ssimon { 2292160814Ssimon i = X509_PURPOSE_get_by_sname(argn); 2293160814Ssimon if(i < 0) 2294160814Ssimon { 2295160814Ssimon BIO_printf(err, "unrecognized purpose\n"); 2296160814Ssimon *badarg = 1; 2297160814Ssimon } 2298160814Ssimon else 2299160814Ssimon { 2300160814Ssimon xptmp = X509_PURPOSE_get0(i); 2301160814Ssimon purpose = X509_PURPOSE_get_id(xptmp); 2302160814Ssimon } 2303160814Ssimon } 2304160814Ssimon (*pargs)++; 2305160814Ssimon } 2306238405Sjkim else if (strcmp(arg,"-verify_depth") == 0) 2307238405Sjkim { 2308238405Sjkim if (!argn) 2309238405Sjkim *badarg = 1; 2310238405Sjkim else 2311238405Sjkim { 2312238405Sjkim depth = atoi(argn); 2313238405Sjkim if(depth < 0) 2314238405Sjkim { 2315238405Sjkim BIO_printf(err, "invalid depth\n"); 2316238405Sjkim *badarg = 1; 2317238405Sjkim } 2318238405Sjkim } 2319238405Sjkim (*pargs)++; 2320238405Sjkim } 2321238405Sjkim else if (strcmp(arg,"-attime") == 0) 2322238405Sjkim { 2323238405Sjkim if (!argn) 2324238405Sjkim *badarg = 1; 2325238405Sjkim else 2326238405Sjkim { 2327238405Sjkim long timestamp; 2328238405Sjkim /* interpret the -attime argument as seconds since 2329238405Sjkim * Epoch */ 2330238405Sjkim if (sscanf(argn, "%li", ×tamp) != 1) 2331238405Sjkim { 2332238405Sjkim BIO_printf(bio_err, 2333238405Sjkim "Error parsing timestamp %s\n", 2334238405Sjkim argn); 2335238405Sjkim *badarg = 1; 2336238405Sjkim } 2337238405Sjkim /* on some platforms time_t may be a float */ 2338238405Sjkim at_time = (time_t) timestamp; 2339238405Sjkim } 2340238405Sjkim (*pargs)++; 2341238405Sjkim } 2342160814Ssimon else if (!strcmp(arg, "-ignore_critical")) 2343160814Ssimon flags |= X509_V_FLAG_IGNORE_CRITICAL; 2344160814Ssimon else if (!strcmp(arg, "-issuer_checks")) 2345160814Ssimon flags |= X509_V_FLAG_CB_ISSUER_CHECK; 2346160814Ssimon else if (!strcmp(arg, "-crl_check")) 2347160814Ssimon flags |= X509_V_FLAG_CRL_CHECK; 2348160814Ssimon else if (!strcmp(arg, "-crl_check_all")) 2349160814Ssimon flags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL; 2350160814Ssimon else if (!strcmp(arg, "-policy_check")) 2351160814Ssimon flags |= X509_V_FLAG_POLICY_CHECK; 2352160814Ssimon else if (!strcmp(arg, "-explicit_policy")) 2353160814Ssimon flags |= X509_V_FLAG_EXPLICIT_POLICY; 2354238405Sjkim else if (!strcmp(arg, "-inhibit_any")) 2355238405Sjkim flags |= X509_V_FLAG_INHIBIT_ANY; 2356238405Sjkim else if (!strcmp(arg, "-inhibit_map")) 2357238405Sjkim flags |= X509_V_FLAG_INHIBIT_MAP; 2358160814Ssimon else if (!strcmp(arg, "-x509_strict")) 2359160814Ssimon flags |= X509_V_FLAG_X509_STRICT; 2360238405Sjkim else if (!strcmp(arg, "-extended_crl")) 2361238405Sjkim flags |= X509_V_FLAG_EXTENDED_CRL_SUPPORT; 2362238405Sjkim else if (!strcmp(arg, "-use_deltas")) 2363238405Sjkim flags |= X509_V_FLAG_USE_DELTAS; 2364160814Ssimon else if (!strcmp(arg, "-policy_print")) 2365160814Ssimon flags |= X509_V_FLAG_NOTIFY_POLICY; 2366205128Ssimon else if (!strcmp(arg, "-check_ss_sig")) 2367205128Ssimon flags |= X509_V_FLAG_CHECK_SS_SIGNATURE; 2368160814Ssimon else 2369160814Ssimon return 0; 2370160814Ssimon 2371160814Ssimon if (*badarg) 2372160814Ssimon { 2373160814Ssimon if (*pm) 2374160814Ssimon X509_VERIFY_PARAM_free(*pm); 2375160814Ssimon *pm = NULL; 2376160814Ssimon goto end; 2377160814Ssimon } 2378160814Ssimon 2379160814Ssimon if (!*pm && !(*pm = X509_VERIFY_PARAM_new())) 2380160814Ssimon { 2381160814Ssimon *badarg = 1; 2382160814Ssimon goto end; 2383160814Ssimon } 2384160814Ssimon 2385160814Ssimon if (otmp) 2386160814Ssimon X509_VERIFY_PARAM_add0_policy(*pm, otmp); 2387160814Ssimon if (flags) 2388160814Ssimon X509_VERIFY_PARAM_set_flags(*pm, flags); 2389160814Ssimon 2390160814Ssimon if (purpose) 2391160814Ssimon X509_VERIFY_PARAM_set_purpose(*pm, purpose); 2392160814Ssimon 2393238405Sjkim if (depth >= 0) 2394238405Sjkim X509_VERIFY_PARAM_set_depth(*pm, depth); 2395238405Sjkim 2396238405Sjkim if (at_time) 2397238405Sjkim X509_VERIFY_PARAM_set_time(*pm, at_time); 2398238405Sjkim 2399160814Ssimon end: 2400160814Ssimon 2401160814Ssimon (*pargs)++; 2402160814Ssimon 2403160814Ssimon if (pargc) 2404160814Ssimon *pargc -= *pargs - oldargs; 2405160814Ssimon 2406160814Ssimon return 1; 2407160814Ssimon 2408160814Ssimon } 2409160814Ssimon 2410238405Sjkim/* Read whole contents of a BIO into an allocated memory buffer and 2411238405Sjkim * return it. 2412238405Sjkim */ 2413238405Sjkim 2414238405Sjkimint bio_to_mem(unsigned char **out, int maxlen, BIO *in) 2415238405Sjkim { 2416238405Sjkim BIO *mem; 2417238405Sjkim int len, ret; 2418238405Sjkim unsigned char tbuf[1024]; 2419238405Sjkim mem = BIO_new(BIO_s_mem()); 2420238405Sjkim if (!mem) 2421238405Sjkim return -1; 2422238405Sjkim for(;;) 2423238405Sjkim { 2424238405Sjkim if ((maxlen != -1) && maxlen < 1024) 2425238405Sjkim len = maxlen; 2426238405Sjkim else 2427238405Sjkim len = 1024; 2428238405Sjkim len = BIO_read(in, tbuf, len); 2429238405Sjkim if (len <= 0) 2430238405Sjkim break; 2431238405Sjkim if (BIO_write(mem, tbuf, len) != len) 2432238405Sjkim { 2433238405Sjkim BIO_free(mem); 2434238405Sjkim return -1; 2435238405Sjkim } 2436238405Sjkim maxlen -= len; 2437238405Sjkim 2438238405Sjkim if (maxlen == 0) 2439238405Sjkim break; 2440238405Sjkim } 2441238405Sjkim ret = BIO_get_mem_data(mem, (char **)out); 2442238405Sjkim BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY); 2443238405Sjkim BIO_free(mem); 2444238405Sjkim return ret; 2445238405Sjkim } 2446238405Sjkim 2447238405Sjkimint pkey_ctrl_string(EVP_PKEY_CTX *ctx, char *value) 2448238405Sjkim { 2449238405Sjkim int rv; 2450238405Sjkim char *stmp, *vtmp = NULL; 2451238405Sjkim stmp = BUF_strdup(value); 2452238405Sjkim if (!stmp) 2453238405Sjkim return -1; 2454238405Sjkim vtmp = strchr(stmp, ':'); 2455238405Sjkim if (vtmp) 2456238405Sjkim { 2457238405Sjkim *vtmp = 0; 2458238405Sjkim vtmp++; 2459238405Sjkim } 2460238405Sjkim rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp); 2461238405Sjkim OPENSSL_free(stmp); 2462238405Sjkim return rv; 2463238405Sjkim } 2464238405Sjkim 2465160814Ssimonstatic void nodes_print(BIO *out, const char *name, 2466160814Ssimon STACK_OF(X509_POLICY_NODE) *nodes) 2467160814Ssimon { 2468160814Ssimon X509_POLICY_NODE *node; 2469160814Ssimon int i; 2470160814Ssimon BIO_printf(out, "%s Policies:", name); 2471160814Ssimon if (nodes) 2472160814Ssimon { 2473160814Ssimon BIO_puts(out, "\n"); 2474160814Ssimon for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) 2475160814Ssimon { 2476160814Ssimon node = sk_X509_POLICY_NODE_value(nodes, i); 2477160814Ssimon X509_POLICY_NODE_print(out, node, 2); 2478160814Ssimon } 2479160814Ssimon } 2480160814Ssimon else 2481160814Ssimon BIO_puts(out, " <empty>\n"); 2482160814Ssimon } 2483160814Ssimon 2484160814Ssimonvoid policies_print(BIO *out, X509_STORE_CTX *ctx) 2485160814Ssimon { 2486160814Ssimon X509_POLICY_TREE *tree; 2487160814Ssimon int explicit_policy; 2488160814Ssimon int free_out = 0; 2489160814Ssimon if (out == NULL) 2490160814Ssimon { 2491160814Ssimon out = BIO_new_fp(stderr, BIO_NOCLOSE); 2492160814Ssimon free_out = 1; 2493160814Ssimon } 2494160814Ssimon tree = X509_STORE_CTX_get0_policy_tree(ctx); 2495160814Ssimon explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx); 2496160814Ssimon 2497160814Ssimon BIO_printf(out, "Require explicit Policy: %s\n", 2498160814Ssimon explicit_policy ? "True" : "False"); 2499160814Ssimon 2500160814Ssimon nodes_print(out, "Authority", X509_policy_tree_get0_policies(tree)); 2501160814Ssimon nodes_print(out, "User", X509_policy_tree_get0_user_policies(tree)); 2502160814Ssimon if (free_out) 2503160814Ssimon BIO_free(out); 2504160814Ssimon } 2505194206Ssimon 2506238405Sjkim#if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK) 2507194206Ssimon 2508194206Ssimonstatic JPAKE_CTX *jpake_init(const char *us, const char *them, 2509194206Ssimon const char *secret) 2510194206Ssimon { 2511194206Ssimon BIGNUM *p = NULL; 2512194206Ssimon BIGNUM *g = NULL; 2513194206Ssimon BIGNUM *q = NULL; 2514194206Ssimon BIGNUM *bnsecret = BN_new(); 2515194206Ssimon JPAKE_CTX *ctx; 2516194206Ssimon 2517194206Ssimon /* Use a safe prime for p (that we found earlier) */ 2518194206Ssimon BN_hex2bn(&p, "F9E5B365665EA7A05A9C534502780FEE6F1AB5BD4F49947FD036DBD7E905269AF46EF28B0FC07487EE4F5D20FB3C0AF8E700F3A2FA3414970CBED44FEDFF80CE78D800F184BB82435D137AADA2C6C16523247930A63B85661D1FC817A51ACD96168E95898A1F83A79FFB529368AA7833ABD1B0C3AEDDB14D2E1A2F71D99F763F"); 2519194206Ssimon g = BN_new(); 2520194206Ssimon BN_set_word(g, 2); 2521194206Ssimon q = BN_new(); 2522194206Ssimon BN_rshift1(q, p); 2523194206Ssimon 2524194206Ssimon BN_bin2bn((const unsigned char *)secret, strlen(secret), bnsecret); 2525194206Ssimon 2526194206Ssimon ctx = JPAKE_CTX_new(us, them, p, g, q, bnsecret); 2527194206Ssimon BN_free(bnsecret); 2528194206Ssimon BN_free(q); 2529194206Ssimon BN_free(g); 2530194206Ssimon BN_free(p); 2531194206Ssimon 2532194206Ssimon return ctx; 2533194206Ssimon } 2534194206Ssimon 2535194206Ssimonstatic void jpake_send_part(BIO *conn, const JPAKE_STEP_PART *p) 2536194206Ssimon { 2537194206Ssimon BN_print(conn, p->gx); 2538194206Ssimon BIO_puts(conn, "\n"); 2539194206Ssimon BN_print(conn, p->zkpx.gr); 2540194206Ssimon BIO_puts(conn, "\n"); 2541194206Ssimon BN_print(conn, p->zkpx.b); 2542194206Ssimon BIO_puts(conn, "\n"); 2543194206Ssimon } 2544194206Ssimon 2545194206Ssimonstatic void jpake_send_step1(BIO *bconn, JPAKE_CTX *ctx) 2546194206Ssimon { 2547194206Ssimon JPAKE_STEP1 s1; 2548194206Ssimon 2549194206Ssimon JPAKE_STEP1_init(&s1); 2550194206Ssimon JPAKE_STEP1_generate(&s1, ctx); 2551194206Ssimon jpake_send_part(bconn, &s1.p1); 2552194206Ssimon jpake_send_part(bconn, &s1.p2); 2553194206Ssimon (void)BIO_flush(bconn); 2554194206Ssimon JPAKE_STEP1_release(&s1); 2555194206Ssimon } 2556194206Ssimon 2557194206Ssimonstatic void jpake_send_step2(BIO *bconn, JPAKE_CTX *ctx) 2558194206Ssimon { 2559194206Ssimon JPAKE_STEP2 s2; 2560194206Ssimon 2561194206Ssimon JPAKE_STEP2_init(&s2); 2562194206Ssimon JPAKE_STEP2_generate(&s2, ctx); 2563194206Ssimon jpake_send_part(bconn, &s2); 2564194206Ssimon (void)BIO_flush(bconn); 2565194206Ssimon JPAKE_STEP2_release(&s2); 2566194206Ssimon } 2567194206Ssimon 2568194206Ssimonstatic void jpake_send_step3a(BIO *bconn, JPAKE_CTX *ctx) 2569194206Ssimon { 2570194206Ssimon JPAKE_STEP3A s3a; 2571194206Ssimon 2572194206Ssimon JPAKE_STEP3A_init(&s3a); 2573194206Ssimon JPAKE_STEP3A_generate(&s3a, ctx); 2574194206Ssimon BIO_write(bconn, s3a.hhk, sizeof s3a.hhk); 2575194206Ssimon (void)BIO_flush(bconn); 2576194206Ssimon JPAKE_STEP3A_release(&s3a); 2577194206Ssimon } 2578194206Ssimon 2579194206Ssimonstatic void jpake_send_step3b(BIO *bconn, JPAKE_CTX *ctx) 2580194206Ssimon { 2581194206Ssimon JPAKE_STEP3B s3b; 2582194206Ssimon 2583194206Ssimon JPAKE_STEP3B_init(&s3b); 2584194206Ssimon JPAKE_STEP3B_generate(&s3b, ctx); 2585194206Ssimon BIO_write(bconn, s3b.hk, sizeof s3b.hk); 2586194206Ssimon (void)BIO_flush(bconn); 2587194206Ssimon JPAKE_STEP3B_release(&s3b); 2588194206Ssimon } 2589194206Ssimon 2590194206Ssimonstatic void readbn(BIGNUM **bn, BIO *bconn) 2591194206Ssimon { 2592194206Ssimon char buf[10240]; 2593194206Ssimon int l; 2594194206Ssimon 2595194206Ssimon l = BIO_gets(bconn, buf, sizeof buf); 2596194206Ssimon assert(l > 0); 2597194206Ssimon assert(buf[l-1] == '\n'); 2598194206Ssimon buf[l-1] = '\0'; 2599194206Ssimon BN_hex2bn(bn, buf); 2600194206Ssimon } 2601194206Ssimon 2602194206Ssimonstatic void jpake_receive_part(JPAKE_STEP_PART *p, BIO *bconn) 2603194206Ssimon { 2604194206Ssimon readbn(&p->gx, bconn); 2605194206Ssimon readbn(&p->zkpx.gr, bconn); 2606194206Ssimon readbn(&p->zkpx.b, bconn); 2607194206Ssimon } 2608194206Ssimon 2609194206Ssimonstatic void jpake_receive_step1(JPAKE_CTX *ctx, BIO *bconn) 2610194206Ssimon { 2611194206Ssimon JPAKE_STEP1 s1; 2612194206Ssimon 2613194206Ssimon JPAKE_STEP1_init(&s1); 2614194206Ssimon jpake_receive_part(&s1.p1, bconn); 2615194206Ssimon jpake_receive_part(&s1.p2, bconn); 2616194206Ssimon if(!JPAKE_STEP1_process(ctx, &s1)) 2617194206Ssimon { 2618194206Ssimon ERR_print_errors(bio_err); 2619194206Ssimon exit(1); 2620194206Ssimon } 2621194206Ssimon JPAKE_STEP1_release(&s1); 2622194206Ssimon } 2623194206Ssimon 2624194206Ssimonstatic void jpake_receive_step2(JPAKE_CTX *ctx, BIO *bconn) 2625194206Ssimon { 2626194206Ssimon JPAKE_STEP2 s2; 2627194206Ssimon 2628194206Ssimon JPAKE_STEP2_init(&s2); 2629194206Ssimon jpake_receive_part(&s2, bconn); 2630194206Ssimon if(!JPAKE_STEP2_process(ctx, &s2)) 2631194206Ssimon { 2632194206Ssimon ERR_print_errors(bio_err); 2633194206Ssimon exit(1); 2634194206Ssimon } 2635194206Ssimon JPAKE_STEP2_release(&s2); 2636194206Ssimon } 2637194206Ssimon 2638194206Ssimonstatic void jpake_receive_step3a(JPAKE_CTX *ctx, BIO *bconn) 2639194206Ssimon { 2640194206Ssimon JPAKE_STEP3A s3a; 2641194206Ssimon int l; 2642194206Ssimon 2643194206Ssimon JPAKE_STEP3A_init(&s3a); 2644194206Ssimon l = BIO_read(bconn, s3a.hhk, sizeof s3a.hhk); 2645194206Ssimon assert(l == sizeof s3a.hhk); 2646194206Ssimon if(!JPAKE_STEP3A_process(ctx, &s3a)) 2647194206Ssimon { 2648194206Ssimon ERR_print_errors(bio_err); 2649194206Ssimon exit(1); 2650194206Ssimon } 2651194206Ssimon JPAKE_STEP3A_release(&s3a); 2652194206Ssimon } 2653194206Ssimon 2654194206Ssimonstatic void jpake_receive_step3b(JPAKE_CTX *ctx, BIO *bconn) 2655194206Ssimon { 2656194206Ssimon JPAKE_STEP3B s3b; 2657194206Ssimon int l; 2658194206Ssimon 2659194206Ssimon JPAKE_STEP3B_init(&s3b); 2660194206Ssimon l = BIO_read(bconn, s3b.hk, sizeof s3b.hk); 2661194206Ssimon assert(l == sizeof s3b.hk); 2662194206Ssimon if(!JPAKE_STEP3B_process(ctx, &s3b)) 2663194206Ssimon { 2664194206Ssimon ERR_print_errors(bio_err); 2665194206Ssimon exit(1); 2666194206Ssimon } 2667194206Ssimon JPAKE_STEP3B_release(&s3b); 2668194206Ssimon } 2669194206Ssimon 2670194206Ssimonvoid jpake_client_auth(BIO *out, BIO *conn, const char *secret) 2671194206Ssimon { 2672194206Ssimon JPAKE_CTX *ctx; 2673194206Ssimon BIO *bconn; 2674194206Ssimon 2675194206Ssimon BIO_puts(out, "Authenticating with JPAKE\n"); 2676194206Ssimon 2677194206Ssimon ctx = jpake_init("client", "server", secret); 2678194206Ssimon 2679194206Ssimon bconn = BIO_new(BIO_f_buffer()); 2680194206Ssimon BIO_push(bconn, conn); 2681194206Ssimon 2682194206Ssimon jpake_send_step1(bconn, ctx); 2683194206Ssimon jpake_receive_step1(ctx, bconn); 2684194206Ssimon jpake_send_step2(bconn, ctx); 2685194206Ssimon jpake_receive_step2(ctx, bconn); 2686194206Ssimon jpake_send_step3a(bconn, ctx); 2687194206Ssimon jpake_receive_step3b(ctx, bconn); 2688194206Ssimon 2689238405Sjkim BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n"); 2690194206Ssimon 2691238405Sjkim psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx)); 2692238405Sjkim 2693194206Ssimon BIO_pop(bconn); 2694194206Ssimon BIO_free(bconn); 2695238405Sjkim 2696238405Sjkim JPAKE_CTX_free(ctx); 2697194206Ssimon } 2698194206Ssimon 2699194206Ssimonvoid jpake_server_auth(BIO *out, BIO *conn, const char *secret) 2700194206Ssimon { 2701194206Ssimon JPAKE_CTX *ctx; 2702194206Ssimon BIO *bconn; 2703194206Ssimon 2704194206Ssimon BIO_puts(out, "Authenticating with JPAKE\n"); 2705194206Ssimon 2706194206Ssimon ctx = jpake_init("server", "client", secret); 2707194206Ssimon 2708194206Ssimon bconn = BIO_new(BIO_f_buffer()); 2709194206Ssimon BIO_push(bconn, conn); 2710194206Ssimon 2711194206Ssimon jpake_receive_step1(ctx, bconn); 2712194206Ssimon jpake_send_step1(bconn, ctx); 2713194206Ssimon jpake_receive_step2(ctx, bconn); 2714194206Ssimon jpake_send_step2(bconn, ctx); 2715194206Ssimon jpake_receive_step3a(ctx, bconn); 2716194206Ssimon jpake_send_step3b(bconn, ctx); 2717194206Ssimon 2718238405Sjkim BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n"); 2719194206Ssimon 2720238405Sjkim psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx)); 2721238405Sjkim 2722194206Ssimon BIO_pop(bconn); 2723194206Ssimon BIO_free(bconn); 2724238405Sjkim 2725238405Sjkim JPAKE_CTX_free(ctx); 2726194206Ssimon } 2727194206Ssimon 2728194206Ssimon#endif 2729238405Sjkim 2730238405Sjkim#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) 2731238405Sjkim/* next_protos_parse parses a comma separated list of strings into a string 2732238405Sjkim * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. 2733238405Sjkim * outlen: (output) set to the length of the resulting buffer on success. 2734238405Sjkim * err: (maybe NULL) on failure, an error message line is written to this BIO. 2735238405Sjkim * in: a NUL termianted string like "abc,def,ghi" 2736238405Sjkim * 2737238405Sjkim * returns: a malloced buffer or NULL on failure. 2738238405Sjkim */ 2739238405Sjkimunsigned char *next_protos_parse(unsigned short *outlen, const char *in) 2740238405Sjkim { 2741238405Sjkim size_t len; 2742238405Sjkim unsigned char *out; 2743238405Sjkim size_t i, start = 0; 2744238405Sjkim 2745238405Sjkim len = strlen(in); 2746238405Sjkim if (len >= 65535) 2747238405Sjkim return NULL; 2748238405Sjkim 2749238405Sjkim out = OPENSSL_malloc(strlen(in) + 1); 2750238405Sjkim if (!out) 2751238405Sjkim return NULL; 2752238405Sjkim 2753238405Sjkim for (i = 0; i <= len; ++i) 2754238405Sjkim { 2755238405Sjkim if (i == len || in[i] == ',') 2756238405Sjkim { 2757238405Sjkim if (i - start > 255) 2758238405Sjkim { 2759238405Sjkim OPENSSL_free(out); 2760238405Sjkim return NULL; 2761238405Sjkim } 2762238405Sjkim out[start] = i - start; 2763238405Sjkim start = i + 1; 2764238405Sjkim } 2765238405Sjkim else 2766238405Sjkim out[i+1] = in[i]; 2767238405Sjkim } 2768238405Sjkim 2769238405Sjkim *outlen = len + 1; 2770238405Sjkim return out; 2771238405Sjkim } 2772238405Sjkim#endif /* !OPENSSL_NO_TLSEXT && !OPENSSL_NO_NEXTPROTONEG */ 2773238405Sjkim 2774238405Sjkim/* 2775238405Sjkim * Platform-specific sections 2776238405Sjkim */ 2777238405Sjkim#if defined(_WIN32) 2778238405Sjkim# ifdef fileno 2779238405Sjkim# undef fileno 2780238405Sjkim# define fileno(a) (int)_fileno(a) 2781238405Sjkim# endif 2782238405Sjkim 2783238405Sjkim# include <windows.h> 2784238405Sjkim# include <tchar.h> 2785238405Sjkim 2786238405Sjkimstatic int WIN32_rename(const char *from, const char *to) 2787238405Sjkim { 2788238405Sjkim TCHAR *tfrom=NULL,*tto; 2789238405Sjkim DWORD err; 2790238405Sjkim int ret=0; 2791238405Sjkim 2792238405Sjkim if (sizeof(TCHAR) == 1) 2793238405Sjkim { 2794238405Sjkim tfrom = (TCHAR *)from; 2795238405Sjkim tto = (TCHAR *)to; 2796238405Sjkim } 2797238405Sjkim else /* UNICODE path */ 2798238405Sjkim { 2799238405Sjkim size_t i,flen=strlen(from)+1,tlen=strlen(to)+1; 2800238405Sjkim tfrom = (TCHAR *)malloc(sizeof(TCHAR)*(flen+tlen)); 2801238405Sjkim if (tfrom==NULL) goto err; 2802238405Sjkim tto=tfrom+flen; 2803238405Sjkim#if !defined(_WIN32_WCE) || _WIN32_WCE>=101 2804238405Sjkim if (!MultiByteToWideChar(CP_ACP,0,from,flen,(WCHAR *)tfrom,flen)) 2805238405Sjkim#endif 2806238405Sjkim for (i=0;i<flen;i++) tfrom[i]=(TCHAR)from[i]; 2807238405Sjkim#if !defined(_WIN32_WCE) || _WIN32_WCE>=101 2808238405Sjkim if (!MultiByteToWideChar(CP_ACP,0,to, tlen,(WCHAR *)tto, tlen)) 2809238405Sjkim#endif 2810238405Sjkim for (i=0;i<tlen;i++) tto[i] =(TCHAR)to[i]; 2811238405Sjkim } 2812238405Sjkim 2813238405Sjkim if (MoveFile(tfrom,tto)) goto ok; 2814238405Sjkim err=GetLastError(); 2815238405Sjkim if (err==ERROR_ALREADY_EXISTS || err==ERROR_FILE_EXISTS) 2816238405Sjkim { 2817238405Sjkim if (DeleteFile(tto) && MoveFile(tfrom,tto)) 2818238405Sjkim goto ok; 2819238405Sjkim err=GetLastError(); 2820238405Sjkim } 2821238405Sjkim if (err==ERROR_FILE_NOT_FOUND || err==ERROR_PATH_NOT_FOUND) 2822238405Sjkim errno = ENOENT; 2823238405Sjkim else if (err==ERROR_ACCESS_DENIED) 2824238405Sjkim errno = EACCES; 2825238405Sjkim else 2826238405Sjkim errno = EINVAL; /* we could map more codes... */ 2827238405Sjkimerr: 2828238405Sjkim ret=-1; 2829238405Sjkimok: 2830238405Sjkim if (tfrom!=NULL && tfrom!=(TCHAR *)from) free(tfrom); 2831238405Sjkim return ret; 2832238405Sjkim } 2833238405Sjkim#endif 2834238405Sjkim 2835238405Sjkim/* app_tminterval section */ 2836238405Sjkim#if defined(_WIN32) 2837238405Sjkimdouble app_tminterval(int stop,int usertime) 2838238405Sjkim { 2839238405Sjkim FILETIME now; 2840238405Sjkim double ret=0; 2841238405Sjkim static ULARGE_INTEGER tmstart; 2842238405Sjkim static int warning=1; 2843238405Sjkim#ifdef _WIN32_WINNT 2844238405Sjkim static HANDLE proc=NULL; 2845238405Sjkim 2846238405Sjkim if (proc==NULL) 2847238405Sjkim { 2848279264Sdelphij if (check_winnt()) 2849238405Sjkim proc = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE, 2850238405Sjkim GetCurrentProcessId()); 2851238405Sjkim if (proc==NULL) proc = (HANDLE)-1; 2852238405Sjkim } 2853238405Sjkim 2854238405Sjkim if (usertime && proc!=(HANDLE)-1) 2855238405Sjkim { 2856238405Sjkim FILETIME junk; 2857238405Sjkim GetProcessTimes(proc,&junk,&junk,&junk,&now); 2858238405Sjkim } 2859238405Sjkim else 2860238405Sjkim#endif 2861238405Sjkim { 2862238405Sjkim SYSTEMTIME systime; 2863238405Sjkim 2864238405Sjkim if (usertime && warning) 2865238405Sjkim { 2866238405Sjkim BIO_printf(bio_err,"To get meaningful results, run " 2867238405Sjkim "this program on idle system.\n"); 2868238405Sjkim warning=0; 2869238405Sjkim } 2870238405Sjkim GetSystemTime(&systime); 2871238405Sjkim SystemTimeToFileTime(&systime,&now); 2872238405Sjkim } 2873238405Sjkim 2874238405Sjkim if (stop==TM_START) 2875238405Sjkim { 2876238405Sjkim tmstart.u.LowPart = now.dwLowDateTime; 2877238405Sjkim tmstart.u.HighPart = now.dwHighDateTime; 2878238405Sjkim } 2879238405Sjkim else { 2880238405Sjkim ULARGE_INTEGER tmstop; 2881238405Sjkim 2882238405Sjkim tmstop.u.LowPart = now.dwLowDateTime; 2883238405Sjkim tmstop.u.HighPart = now.dwHighDateTime; 2884238405Sjkim 2885238405Sjkim ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart)*1e-7; 2886238405Sjkim } 2887238405Sjkim 2888238405Sjkim return (ret); 2889238405Sjkim } 2890238405Sjkim 2891238405Sjkim#elif defined(OPENSSL_SYS_NETWARE) 2892238405Sjkim#include <time.h> 2893238405Sjkim 2894238405Sjkimdouble app_tminterval(int stop,int usertime) 2895238405Sjkim { 2896238405Sjkim double ret=0; 2897238405Sjkim static clock_t tmstart; 2898238405Sjkim static int warning=1; 2899238405Sjkim 2900238405Sjkim if (usertime && warning) 2901238405Sjkim { 2902238405Sjkim BIO_printf(bio_err,"To get meaningful results, run " 2903238405Sjkim "this program on idle system.\n"); 2904238405Sjkim warning=0; 2905238405Sjkim } 2906238405Sjkim 2907238405Sjkim if (stop==TM_START) tmstart = clock(); 2908238405Sjkim else ret = (clock()-tmstart)/(double)CLOCKS_PER_SEC; 2909238405Sjkim 2910238405Sjkim return (ret); 2911238405Sjkim } 2912238405Sjkim 2913238405Sjkim#elif defined(OPENSSL_SYSTEM_VXWORKS) 2914238405Sjkim#include <time.h> 2915238405Sjkim 2916238405Sjkimdouble app_tminterval(int stop,int usertime) 2917238405Sjkim { 2918238405Sjkim double ret=0; 2919238405Sjkim#ifdef CLOCK_REALTIME 2920238405Sjkim static struct timespec tmstart; 2921238405Sjkim struct timespec now; 2922238405Sjkim#else 2923238405Sjkim static unsigned long tmstart; 2924238405Sjkim unsigned long now; 2925238405Sjkim#endif 2926238405Sjkim static int warning=1; 2927238405Sjkim 2928238405Sjkim if (usertime && warning) 2929238405Sjkim { 2930238405Sjkim BIO_printf(bio_err,"To get meaningful results, run " 2931238405Sjkim "this program on idle system.\n"); 2932238405Sjkim warning=0; 2933238405Sjkim } 2934238405Sjkim 2935238405Sjkim#ifdef CLOCK_REALTIME 2936238405Sjkim clock_gettime(CLOCK_REALTIME,&now); 2937238405Sjkim if (stop==TM_START) tmstart = now; 2938238405Sjkim else ret = ( (now.tv_sec+now.tv_nsec*1e-9) 2939238405Sjkim - (tmstart.tv_sec+tmstart.tv_nsec*1e-9) ); 2940238405Sjkim#else 2941238405Sjkim now = tickGet(); 2942238405Sjkim if (stop==TM_START) tmstart = now; 2943238405Sjkim else ret = (now - tmstart)/(double)sysClkRateGet(); 2944238405Sjkim#endif 2945238405Sjkim return (ret); 2946238405Sjkim } 2947238405Sjkim 2948238405Sjkim#elif defined(OPENSSL_SYSTEM_VMS) 2949238405Sjkim#include <time.h> 2950238405Sjkim#include <times.h> 2951238405Sjkim 2952238405Sjkimdouble app_tminterval(int stop,int usertime) 2953238405Sjkim { 2954238405Sjkim static clock_t tmstart; 2955238405Sjkim double ret = 0; 2956238405Sjkim clock_t now; 2957238405Sjkim#ifdef __TMS 2958238405Sjkim struct tms rus; 2959238405Sjkim 2960238405Sjkim now = times(&rus); 2961238405Sjkim if (usertime) now = rus.tms_utime; 2962238405Sjkim#else 2963238405Sjkim if (usertime) 2964238405Sjkim now = clock(); /* sum of user and kernel times */ 2965238405Sjkim else { 2966238405Sjkim struct timeval tv; 2967238405Sjkim gettimeofday(&tv,NULL); 2968238405Sjkim now = (clock_t)( 2969238405Sjkim (unsigned long long)tv.tv_sec*CLK_TCK + 2970238405Sjkim (unsigned long long)tv.tv_usec*(1000000/CLK_TCK) 2971238405Sjkim ); 2972238405Sjkim } 2973238405Sjkim#endif 2974238405Sjkim if (stop==TM_START) tmstart = now; 2975238405Sjkim else ret = (now - tmstart)/(double)(CLK_TCK); 2976238405Sjkim 2977238405Sjkim return (ret); 2978238405Sjkim } 2979238405Sjkim 2980238405Sjkim#elif defined(_SC_CLK_TCK) /* by means of unistd.h */ 2981238405Sjkim#include <sys/times.h> 2982238405Sjkim 2983238405Sjkimdouble app_tminterval(int stop,int usertime) 2984238405Sjkim { 2985238405Sjkim double ret = 0; 2986238405Sjkim struct tms rus; 2987238405Sjkim clock_t now = times(&rus); 2988238405Sjkim static clock_t tmstart; 2989238405Sjkim 2990238405Sjkim if (usertime) now = rus.tms_utime; 2991238405Sjkim 2992238405Sjkim if (stop==TM_START) tmstart = now; 2993238405Sjkim else 2994238405Sjkim { 2995238405Sjkim long int tck = sysconf(_SC_CLK_TCK); 2996238405Sjkim ret = (now - tmstart)/(double)tck; 2997238405Sjkim } 2998238405Sjkim 2999238405Sjkim return (ret); 3000238405Sjkim } 3001238405Sjkim 3002238405Sjkim#else 3003238405Sjkim#include <sys/time.h> 3004238405Sjkim#include <sys/resource.h> 3005238405Sjkim 3006238405Sjkimdouble app_tminterval(int stop,int usertime) 3007238405Sjkim { 3008238405Sjkim double ret = 0; 3009238405Sjkim struct rusage rus; 3010238405Sjkim struct timeval now; 3011238405Sjkim static struct timeval tmstart; 3012238405Sjkim 3013238405Sjkim if (usertime) getrusage(RUSAGE_SELF,&rus), now = rus.ru_utime; 3014238405Sjkim else gettimeofday(&now,NULL); 3015238405Sjkim 3016238405Sjkim if (stop==TM_START) tmstart = now; 3017238405Sjkim else ret = ( (now.tv_sec+now.tv_usec*1e-6) 3018238405Sjkim - (tmstart.tv_sec+tmstart.tv_usec*1e-6) ); 3019238405Sjkim 3020238405Sjkim return ret; 3021238405Sjkim } 3022238405Sjkim#endif 3023238405Sjkim 3024238405Sjkim/* app_isdir section */ 3025238405Sjkim#ifdef _WIN32 3026238405Sjkimint app_isdir(const char *name) 3027238405Sjkim { 3028238405Sjkim HANDLE hList; 3029238405Sjkim WIN32_FIND_DATA FileData; 3030238405Sjkim#if defined(UNICODE) || defined(_UNICODE) 3031238405Sjkim size_t i, len_0 = strlen(name)+1; 3032238405Sjkim 3033238405Sjkim if (len_0 > sizeof(FileData.cFileName)/sizeof(FileData.cFileName[0])) 3034238405Sjkim return -1; 3035238405Sjkim 3036238405Sjkim#if !defined(_WIN32_WCE) || _WIN32_WCE>=101 3037238405Sjkim if (!MultiByteToWideChar(CP_ACP,0,name,len_0,FileData.cFileName,len_0)) 3038238405Sjkim#endif 3039238405Sjkim for (i=0;i<len_0;i++) 3040238405Sjkim FileData.cFileName[i] = (WCHAR)name[i]; 3041238405Sjkim 3042238405Sjkim hList = FindFirstFile(FileData.cFileName,&FileData); 3043238405Sjkim#else 3044238405Sjkim hList = FindFirstFile(name,&FileData); 3045238405Sjkim#endif 3046238405Sjkim if (hList == INVALID_HANDLE_VALUE) return -1; 3047238405Sjkim FindClose(hList); 3048238405Sjkim return ((FileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)!=0); 3049238405Sjkim } 3050238405Sjkim#else 3051238405Sjkim#include <sys/stat.h> 3052238405Sjkim#ifndef S_ISDIR 3053238405Sjkim# if defined(_S_IFMT) && defined(_S_IFDIR) 3054238405Sjkim# define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR) 3055238405Sjkim# else 3056238405Sjkim# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) 3057238405Sjkim# endif 3058238405Sjkim#endif 3059238405Sjkim 3060238405Sjkimint app_isdir(const char *name) 3061238405Sjkim { 3062238405Sjkim#if defined(S_ISDIR) 3063238405Sjkim struct stat st; 3064238405Sjkim 3065238405Sjkim if (stat(name,&st)==0) return S_ISDIR(st.st_mode); 3066238405Sjkim else return -1; 3067238405Sjkim#else 3068238405Sjkim return -1; 3069238405Sjkim#endif 3070238405Sjkim } 3071238405Sjkim#endif 3072238405Sjkim 3073238405Sjkim/* raw_read|write section */ 3074238405Sjkim#if defined(_WIN32) && defined(STD_INPUT_HANDLE) 3075238405Sjkimint raw_read_stdin(void *buf,int siz) 3076238405Sjkim { 3077238405Sjkim DWORD n; 3078238405Sjkim if (ReadFile(GetStdHandle(STD_INPUT_HANDLE),buf,siz,&n,NULL)) 3079238405Sjkim return (n); 3080238405Sjkim else return (-1); 3081238405Sjkim } 3082238405Sjkim#else 3083238405Sjkimint raw_read_stdin(void *buf,int siz) 3084238405Sjkim { return read(fileno(stdin),buf,siz); } 3085238405Sjkim#endif 3086238405Sjkim 3087238405Sjkim#if defined(_WIN32) && defined(STD_OUTPUT_HANDLE) 3088238405Sjkimint raw_write_stdout(const void *buf,int siz) 3089238405Sjkim { 3090238405Sjkim DWORD n; 3091238405Sjkim if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),buf,siz,&n,NULL)) 3092238405Sjkim return (n); 3093238405Sjkim else return (-1); 3094238405Sjkim } 3095238405Sjkim#else 3096238405Sjkimint raw_write_stdout(const void *buf,int siz) 3097238405Sjkim { return write(fileno(stdout),buf,siz); } 3098238405Sjkim#endif 3099