req.c revision 111147
155714Skris/* apps/req.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 */ 5855714Skris 5955714Skris#include <stdio.h> 6055714Skris#include <stdlib.h> 6155714Skris#include <time.h> 6255714Skris#include <string.h> 63109998Smarkm#ifdef OPENSSL_NO_STDIO 6455714Skris#define APPS_WIN16 6555714Skris#endif 6655714Skris#include "apps.h" 6755714Skris#include <openssl/bio.h> 6855714Skris#include <openssl/evp.h> 6955714Skris#include <openssl/conf.h> 7055714Skris#include <openssl/err.h> 7155714Skris#include <openssl/asn1.h> 7255714Skris#include <openssl/x509.h> 7355714Skris#include <openssl/x509v3.h> 7455714Skris#include <openssl/objects.h> 7555714Skris#include <openssl/pem.h> 76109998Smarkm#include "../crypto/cryptlib.h" 7755714Skris 7855714Skris#define SECTION "req" 7955714Skris 8055714Skris#define BITS "default_bits" 8155714Skris#define KEYFILE "default_keyfile" 8259191Skris#define PROMPT "prompt" 8355714Skris#define DISTINGUISHED_NAME "distinguished_name" 8455714Skris#define ATTRIBUTES "attributes" 8555714Skris#define V3_EXTENSIONS "x509_extensions" 8659191Skris#define REQ_EXTENSIONS "req_extensions" 8759191Skris#define STRING_MASK "string_mask" 88109998Smarkm#define UTF8_IN "utf8" 8955714Skris 9055714Skris#define DEFAULT_KEY_LENGTH 512 9155714Skris#define MIN_KEY_LENGTH 384 9255714Skris 9355714Skris#undef PROG 9455714Skris#define PROG req_main 9555714Skris 9659191Skris/* -inform arg - input format - default PEM (DER or PEM) 9755714Skris * -outform arg - output format - default PEM 9855714Skris * -in arg - input file - default stdin 9955714Skris * -out arg - output file - default stdout 10055714Skris * -verify - check request signature 10155714Skris * -noout - don't print stuff out. 10255714Skris * -text - print out human readable text. 10355714Skris * -nodes - no des encryption 10455714Skris * -config file - Load configuration file. 10555714Skris * -key file - make a request using key in file (or use it for verification). 106109998Smarkm * -keyform arg - key file format. 10768651Skris * -rand file(s) - load the file(s) into the PRNG. 10855714Skris * -newkey - make a key and a request. 10955714Skris * -modulus - print RSA modulus. 110109998Smarkm * -pubkey - output Public Key. 11155714Skris * -x509 - output a self signed X509 structure instead. 11255714Skris * -asn1-kludge - output new certificate request in a format that some CA's 11355714Skris * require. This format is wrong 11455714Skris */ 11555714Skris 116109998Smarkmstatic int make_REQ(X509_REQ *req,EVP_PKEY *pkey,char *dn,int attribs, 117109998Smarkm unsigned long chtype); 118109998Smarkmstatic int build_subject(X509_REQ *req, char *subj, unsigned long chtype); 11959191Skrisstatic int prompt_info(X509_REQ *req, 12059191Skris STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect, 121109998Smarkm STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, int attribs, 122109998Smarkm unsigned long chtype); 12359191Skrisstatic int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *sk, 124109998Smarkm STACK_OF(CONF_VALUE) *attr, int attribs, 125109998Smarkm unsigned long chtype); 12659191Skrisstatic int add_attribute_object(X509_REQ *req, char *text, 127109998Smarkm char *def, char *value, int nid, int n_min, 128109998Smarkm int n_max, unsigned long chtype); 12955714Skrisstatic int add_DN_object(X509_NAME *n, char *text, char *def, char *value, 130109998Smarkm int nid,int n_min,int n_max, unsigned long chtype); 131109998Smarkm#ifndef OPENSSL_NO_RSA 13255714Skrisstatic void MS_CALLBACK req_cb(int p,int n,void *arg); 13359191Skris#endif 134109998Smarkmstatic int req_check_len(int len,int n_min,int n_max); 13555714Skrisstatic int check_end(char *str, char *end); 13655714Skris#ifndef MONOLITH 13755714Skrisstatic char *default_config_file=NULL; 13855714Skris#endif 139109998Smarkmstatic CONF *req_conf=NULL; 140109998Smarkmstatic int batch=0; 14155714Skris 14255714Skris#define TYPE_RSA 1 14355714Skris#define TYPE_DSA 2 14455714Skris#define TYPE_DH 3 14555714Skris 14659191Skrisint MAIN(int, char **); 14759191Skris 14855714Skrisint MAIN(int argc, char **argv) 14955714Skris { 150109998Smarkm ENGINE *e = NULL; 151109998Smarkm#ifndef OPENSSL_NO_DSA 15255714Skris DSA *dsa_params=NULL; 15355714Skris#endif 154109998Smarkm unsigned long nmflag = 0, reqflag = 0; 15555714Skris int ex=1,x509=0,days=30; 15655714Skris X509 *x509ss=NULL; 15755714Skris X509_REQ *req=NULL; 15855714Skris EVP_PKEY *pkey=NULL; 159109998Smarkm int i=0,badops=0,newreq=0,verbose=0,pkey_type=TYPE_RSA; 160109998Smarkm long newkey = -1; 16155714Skris BIO *in=NULL,*out=NULL; 16255714Skris int informat,outformat,verify=0,noout=0,text=0,keyform=FORMAT_PEM; 163109998Smarkm int nodes=0,kludge=0,newhdr=0,subject=0,pubkey=0; 16455714Skris char *infile,*outfile,*prog,*keyfile=NULL,*template=NULL,*keyout=NULL; 165111147Snectar#ifndef OPENSSL_NO_ENGINE 166109998Smarkm char *engine=NULL; 167111147Snectar#endif 16855714Skris char *extensions = NULL; 16959191Skris char *req_exts = NULL; 170109998Smarkm const EVP_CIPHER *cipher=NULL; 171109998Smarkm ASN1_INTEGER *serial = NULL; 17255714Skris int modulus=0; 17368651Skris char *inrand=NULL; 17459191Skris char *passargin = NULL, *passargout = NULL; 17559191Skris char *passin = NULL, *passout = NULL; 17655714Skris char *p; 177109998Smarkm char *subj = NULL; 17855714Skris const EVP_MD *md_alg=NULL,*digest=EVP_md5(); 179109998Smarkm unsigned long chtype = MBSTRING_ASC; 18055714Skris#ifndef MONOLITH 181109998Smarkm char *to_free; 182109998Smarkm long errline; 18355714Skris#endif 18455714Skris 18559191Skris req_conf = NULL; 186109998Smarkm#ifndef OPENSSL_NO_DES 18755714Skris cipher=EVP_des_ede3_cbc(); 18855714Skris#endif 18955714Skris apps_startup(); 19055714Skris 19155714Skris if (bio_err == NULL) 19255714Skris if ((bio_err=BIO_new(BIO_s_file())) != NULL) 19355714Skris BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); 19455714Skris 19555714Skris infile=NULL; 19655714Skris outfile=NULL; 19755714Skris informat=FORMAT_PEM; 19855714Skris outformat=FORMAT_PEM; 19955714Skris 20055714Skris prog=argv[0]; 20155714Skris argc--; 20255714Skris argv++; 20355714Skris while (argc >= 1) 20455714Skris { 20555714Skris if (strcmp(*argv,"-inform") == 0) 20655714Skris { 20755714Skris if (--argc < 1) goto bad; 20855714Skris informat=str2fmt(*(++argv)); 20955714Skris } 21055714Skris else if (strcmp(*argv,"-outform") == 0) 21155714Skris { 21255714Skris if (--argc < 1) goto bad; 21355714Skris outformat=str2fmt(*(++argv)); 21455714Skris } 215111147Snectar#ifndef OPENSSL_NO_ENGINE 216109998Smarkm else if (strcmp(*argv,"-engine") == 0) 217109998Smarkm { 218109998Smarkm if (--argc < 1) goto bad; 219109998Smarkm engine= *(++argv); 220109998Smarkm } 221111147Snectar#endif 22255714Skris else if (strcmp(*argv,"-key") == 0) 22355714Skris { 22455714Skris if (--argc < 1) goto bad; 22555714Skris keyfile= *(++argv); 22655714Skris } 227109998Smarkm else if (strcmp(*argv,"-pubkey") == 0) 228109998Smarkm { 229109998Smarkm pubkey=1; 230109998Smarkm } 23155714Skris else if (strcmp(*argv,"-new") == 0) 23255714Skris { 23355714Skris newreq=1; 23455714Skris } 23555714Skris else if (strcmp(*argv,"-config") == 0) 23655714Skris { 23755714Skris if (--argc < 1) goto bad; 23855714Skris template= *(++argv); 23955714Skris } 24055714Skris else if (strcmp(*argv,"-keyform") == 0) 24155714Skris { 24255714Skris if (--argc < 1) goto bad; 24355714Skris keyform=str2fmt(*(++argv)); 24455714Skris } 24555714Skris else if (strcmp(*argv,"-in") == 0) 24655714Skris { 24755714Skris if (--argc < 1) goto bad; 24855714Skris infile= *(++argv); 24955714Skris } 25055714Skris else if (strcmp(*argv,"-out") == 0) 25155714Skris { 25255714Skris if (--argc < 1) goto bad; 25355714Skris outfile= *(++argv); 25455714Skris } 25555714Skris else if (strcmp(*argv,"-keyout") == 0) 25655714Skris { 25755714Skris if (--argc < 1) goto bad; 25855714Skris keyout= *(++argv); 25955714Skris } 26059191Skris else if (strcmp(*argv,"-passin") == 0) 26159191Skris { 26259191Skris if (--argc < 1) goto bad; 26359191Skris passargin= *(++argv); 26459191Skris } 26559191Skris else if (strcmp(*argv,"-passout") == 0) 26659191Skris { 26759191Skris if (--argc < 1) goto bad; 26859191Skris passargout= *(++argv); 26959191Skris } 27068651Skris else if (strcmp(*argv,"-rand") == 0) 27168651Skris { 27268651Skris if (--argc < 1) goto bad; 27368651Skris inrand= *(++argv); 27468651Skris } 27555714Skris else if (strcmp(*argv,"-newkey") == 0) 27655714Skris { 27755714Skris int is_numeric; 27855714Skris 27955714Skris if (--argc < 1) goto bad; 28055714Skris p= *(++argv); 28155714Skris is_numeric = p[0] >= '0' && p[0] <= '9'; 28255714Skris if (strncmp("rsa:",p,4) == 0 || is_numeric) 28355714Skris { 28455714Skris pkey_type=TYPE_RSA; 28555714Skris if(!is_numeric) 28655714Skris p+=4; 28755714Skris newkey= atoi(p); 28855714Skris } 28955714Skris else 290109998Smarkm#ifndef OPENSSL_NO_DSA 29155714Skris if (strncmp("dsa:",p,4) == 0) 29255714Skris { 29355714Skris X509 *xtmp=NULL; 29455714Skris EVP_PKEY *dtmp; 29555714Skris 29655714Skris pkey_type=TYPE_DSA; 29755714Skris p+=4; 29855714Skris if ((in=BIO_new_file(p,"r")) == NULL) 29955714Skris { 30055714Skris perror(p); 30155714Skris goto end; 30255714Skris } 30355714Skris if ((dsa_params=PEM_read_bio_DSAparams(in,NULL,NULL,NULL)) == NULL) 30455714Skris { 30555714Skris ERR_clear_error(); 30655714Skris (void)BIO_reset(in); 30755714Skris if ((xtmp=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL) 30855714Skris { 30955714Skris BIO_printf(bio_err,"unable to load DSA parameters from file\n"); 31055714Skris goto end; 31155714Skris } 31255714Skris 313100928Snectar if ((dtmp=X509_get_pubkey(xtmp)) == NULL) goto end; 31455714Skris if (dtmp->type == EVP_PKEY_DSA) 31555714Skris dsa_params=DSAparams_dup(dtmp->pkey.dsa); 31655714Skris EVP_PKEY_free(dtmp); 31755714Skris X509_free(xtmp); 31855714Skris if (dsa_params == NULL) 31955714Skris { 32055714Skris BIO_printf(bio_err,"Certificate does not contain DSA parameters\n"); 32155714Skris goto end; 32255714Skris } 32355714Skris } 32455714Skris BIO_free(in); 32555714Skris newkey=BN_num_bits(dsa_params->p); 32655714Skris in=NULL; 32755714Skris } 32855714Skris else 32955714Skris#endif 330109998Smarkm#ifndef OPENSSL_NO_DH 33155714Skris if (strncmp("dh:",p,4) == 0) 33255714Skris { 33355714Skris pkey_type=TYPE_DH; 33455714Skris p+=3; 33555714Skris } 33655714Skris else 33755714Skris#endif 33855714Skris pkey_type=TYPE_RSA; 33955714Skris 34055714Skris newreq=1; 34155714Skris } 342109998Smarkm else if (strcmp(*argv,"-batch") == 0) 343109998Smarkm batch=1; 34459191Skris else if (strcmp(*argv,"-newhdr") == 0) 34559191Skris newhdr=1; 34655714Skris else if (strcmp(*argv,"-modulus") == 0) 34755714Skris modulus=1; 34855714Skris else if (strcmp(*argv,"-verify") == 0) 34955714Skris verify=1; 35055714Skris else if (strcmp(*argv,"-nodes") == 0) 35155714Skris nodes=1; 35255714Skris else if (strcmp(*argv,"-noout") == 0) 35355714Skris noout=1; 354109998Smarkm else if (strcmp(*argv,"-verbose") == 0) 355109998Smarkm verbose=1; 356109998Smarkm else if (strcmp(*argv,"-utf8") == 0) 357109998Smarkm chtype = MBSTRING_UTF8; 358109998Smarkm else if (strcmp(*argv,"-nameopt") == 0) 359109998Smarkm { 360109998Smarkm if (--argc < 1) goto bad; 361109998Smarkm if (!set_name_ex(&nmflag, *(++argv))) goto bad; 362109998Smarkm } 363109998Smarkm else if (strcmp(*argv,"-reqopt") == 0) 364109998Smarkm { 365109998Smarkm if (--argc < 1) goto bad; 366109998Smarkm if (!set_cert_ex(&reqflag, *(++argv))) goto bad; 367109998Smarkm } 368109998Smarkm else if (strcmp(*argv,"-subject") == 0) 369109998Smarkm subject=1; 37055714Skris else if (strcmp(*argv,"-text") == 0) 37155714Skris text=1; 37255714Skris else if (strcmp(*argv,"-x509") == 0) 37355714Skris x509=1; 37455714Skris else if (strcmp(*argv,"-asn1-kludge") == 0) 37555714Skris kludge=1; 37655714Skris else if (strcmp(*argv,"-no-asn1-kludge") == 0) 37755714Skris kludge=0; 378109998Smarkm else if (strcmp(*argv,"-subj") == 0) 379109998Smarkm { 380109998Smarkm if (--argc < 1) goto bad; 381109998Smarkm subj= *(++argv); 382109998Smarkm } 38355714Skris else if (strcmp(*argv,"-days") == 0) 38455714Skris { 38555714Skris if (--argc < 1) goto bad; 38655714Skris days= atoi(*(++argv)); 38755714Skris if (days == 0) days=30; 38855714Skris } 389109998Smarkm else if (strcmp(*argv,"-set_serial") == 0) 390109998Smarkm { 391109998Smarkm if (--argc < 1) goto bad; 392109998Smarkm serial = s2i_ASN1_INTEGER(NULL, *(++argv)); 393109998Smarkm if (!serial) goto bad; 394109998Smarkm } 39555714Skris else if ((md_alg=EVP_get_digestbyname(&((*argv)[1]))) != NULL) 39655714Skris { 39755714Skris /* ok */ 39855714Skris digest=md_alg; 39955714Skris } 40059191Skris else if (strcmp(*argv,"-extensions") == 0) 40159191Skris { 40259191Skris if (--argc < 1) goto bad; 40359191Skris extensions = *(++argv); 40459191Skris } 40559191Skris else if (strcmp(*argv,"-reqexts") == 0) 40659191Skris { 40759191Skris if (--argc < 1) goto bad; 40859191Skris req_exts = *(++argv); 40959191Skris } 41055714Skris else 41155714Skris { 41255714Skris BIO_printf(bio_err,"unknown option %s\n",*argv); 41355714Skris badops=1; 41455714Skris break; 41555714Skris } 41655714Skris argc--; 41755714Skris argv++; 41855714Skris } 41955714Skris 42055714Skris if (badops) 42155714Skris { 42255714Skrisbad: 42355714Skris BIO_printf(bio_err,"%s [options] <infile >outfile\n",prog); 42455714Skris BIO_printf(bio_err,"where options are\n"); 42559191Skris BIO_printf(bio_err," -inform arg input format - DER or PEM\n"); 42659191Skris BIO_printf(bio_err," -outform arg output format - DER or PEM\n"); 42755714Skris BIO_printf(bio_err," -in arg input file\n"); 42855714Skris BIO_printf(bio_err," -out arg output file\n"); 42955714Skris BIO_printf(bio_err," -text text form of request\n"); 430109998Smarkm BIO_printf(bio_err," -pubkey output public key\n"); 43155714Skris BIO_printf(bio_err," -noout do not output REQ\n"); 43255714Skris BIO_printf(bio_err," -verify verify signature on REQ\n"); 43355714Skris BIO_printf(bio_err," -modulus RSA modulus\n"); 43455714Skris BIO_printf(bio_err," -nodes don't encrypt the output key\n"); 435111147Snectar#ifndef OPENSSL_NO_ENGINE 436109998Smarkm BIO_printf(bio_err," -engine e use engine e, possibly a hardware device\n"); 437111147Snectar#endif 438109998Smarkm BIO_printf(bio_err," -subject output the request's subject\n"); 439109998Smarkm BIO_printf(bio_err," -passin private key password source\n"); 440109998Smarkm BIO_printf(bio_err," -key file use the private key contained in file\n"); 44155714Skris BIO_printf(bio_err," -keyform arg key file format\n"); 44255714Skris BIO_printf(bio_err," -keyout arg file to send the key to\n"); 44368651Skris BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); 44468651Skris BIO_printf(bio_err," load the file (or the files in the directory) into\n"); 44568651Skris BIO_printf(bio_err," the random number generator\n"); 44655714Skris BIO_printf(bio_err," -newkey rsa:bits generate a new RSA key of 'bits' in size\n"); 44755714Skris BIO_printf(bio_err," -newkey dsa:file generate a new DSA key, parameters taken from CA in 'file'\n"); 44889837Skris BIO_printf(bio_err," -[digest] Digest to sign with (md5, sha1, md2, mdc2, md4)\n"); 44955714Skris BIO_printf(bio_err," -config file request template file.\n"); 450109998Smarkm BIO_printf(bio_err," -subj arg set or modify request subject\n"); 45155714Skris BIO_printf(bio_err," -new new request.\n"); 452109998Smarkm BIO_printf(bio_err," -batch do not ask anything during request generation\n"); 45355714Skris BIO_printf(bio_err," -x509 output a x509 structure instead of a cert. req.\n"); 454109998Smarkm BIO_printf(bio_err," -days number of days a certificate generated by -x509 is valid for.\n"); 455109998Smarkm BIO_printf(bio_err," -set_serial serial number to use for a certificate generated by -x509.\n"); 45659191Skris BIO_printf(bio_err," -newhdr output \"NEW\" in the header lines\n"); 45755714Skris BIO_printf(bio_err," -asn1-kludge Output the 'request' in a format that is wrong but some CA's\n"); 45855714Skris BIO_printf(bio_err," have been reported as requiring\n"); 45959191Skris BIO_printf(bio_err," -extensions .. specify certificate extension section (override value in config file)\n"); 46059191Skris BIO_printf(bio_err," -reqexts .. specify request extension section (override value in config file)\n"); 461109998Smarkm BIO_printf(bio_err," -utf8 input characters are UTF8 (default ASCII)\n"); 462111147Snectar BIO_printf(bio_err," -nameopt arg - various certificate name options\n"); 463109998Smarkm BIO_printf(bio_err," -reqopt arg - various request text options\n\n"); 46455714Skris goto end; 46555714Skris } 46655714Skris 46755714Skris ERR_load_crypto_strings(); 46859191Skris if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { 46959191Skris BIO_printf(bio_err, "Error getting passwords\n"); 47059191Skris goto end; 47159191Skris } 47255714Skris 47359191Skris#ifndef MONOLITH /* else this has happened in openssl.c (global `config') */ 47455714Skris /* Lets load up our environment a little */ 47555714Skris p=getenv("OPENSSL_CONF"); 47655714Skris if (p == NULL) 47755714Skris p=getenv("SSLEAY_CONF"); 47855714Skris if (p == NULL) 479109998Smarkm p=to_free=make_config_name(); 48059191Skris default_config_file=p; 481109998Smarkm config=NCONF_new(NULL); 482109998Smarkm i=NCONF_load(config, p, &errline); 48355714Skris#endif 48455714Skris 48555714Skris if (template != NULL) 48655714Skris { 487109998Smarkm long errline = -1; 48855714Skris 489109998Smarkm if( verbose ) 490109998Smarkm BIO_printf(bio_err,"Using configuration from %s\n",template); 491109998Smarkm req_conf=NCONF_new(NULL); 492109998Smarkm i=NCONF_load(req_conf,template,&errline); 493109998Smarkm if (i == 0) 49455714Skris { 49555714Skris BIO_printf(bio_err,"error on line %ld of %s\n",errline,template); 49655714Skris goto end; 49755714Skris } 49855714Skris } 49955714Skris else 50055714Skris { 50155714Skris req_conf=config; 502109998Smarkm if( verbose ) 503109998Smarkm BIO_printf(bio_err,"Using configuration from %s\n", 50455714Skris default_config_file); 50555714Skris if (req_conf == NULL) 50655714Skris { 50755714Skris BIO_printf(bio_err,"Unable to load config info\n"); 50855714Skris } 50955714Skris } 51055714Skris 51155714Skris if (req_conf != NULL) 51255714Skris { 513109998Smarkm if (!load_config(bio_err, req_conf)) 514109998Smarkm goto end; 515109998Smarkm p=NCONF_get_string(req_conf,NULL,"oid_file"); 516109998Smarkm if (p == NULL) 517109998Smarkm ERR_clear_error(); 51855714Skris if (p != NULL) 51955714Skris { 52055714Skris BIO *oid_bio; 52155714Skris 52255714Skris oid_bio=BIO_new_file(p,"r"); 52355714Skris if (oid_bio == NULL) 52455714Skris { 52555714Skris /* 52655714Skris BIO_printf(bio_err,"problems opening %s for extra oid's\n",p); 52755714Skris ERR_print_errors(bio_err); 52855714Skris */ 52955714Skris } 53055714Skris else 53155714Skris { 53255714Skris OBJ_create_objects(oid_bio); 53355714Skris BIO_free(oid_bio); 53455714Skris } 53555714Skris } 53655714Skris } 537109998Smarkm if(!add_oid_section(bio_err, req_conf)) goto end; 53855714Skris 539109998Smarkm if (md_alg == NULL) 54055714Skris { 541109998Smarkm p=NCONF_get_string(req_conf,SECTION,"default_md"); 542109998Smarkm if (p == NULL) 543109998Smarkm ERR_clear_error(); 544109998Smarkm if (p != NULL) 545109998Smarkm { 546109998Smarkm if ((md_alg=EVP_get_digestbyname(p)) != NULL) 547109998Smarkm digest=md_alg; 548109998Smarkm } 54955714Skris } 55055714Skris 551109998Smarkm if (!extensions) 552109998Smarkm { 553109998Smarkm extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS); 554109998Smarkm if (!extensions) 555109998Smarkm ERR_clear_error(); 556109998Smarkm } 557109998Smarkm if (extensions) { 55855714Skris /* Check syntax of file */ 55955714Skris X509V3_CTX ctx; 56055714Skris X509V3_set_ctx_test(&ctx); 561109998Smarkm X509V3_set_nconf(&ctx, req_conf); 562109998Smarkm if(!X509V3_EXT_add_nconf(req_conf, &ctx, extensions, NULL)) { 56355714Skris BIO_printf(bio_err, 56455714Skris "Error Loading extension section %s\n", extensions); 56555714Skris goto end; 56655714Skris } 56755714Skris } 56855714Skris 56959191Skris if(!passin) 570109998Smarkm { 571109998Smarkm passin = NCONF_get_string(req_conf, SECTION, "input_password"); 572109998Smarkm if (!passin) 573109998Smarkm ERR_clear_error(); 574109998Smarkm } 575109998Smarkm 57659191Skris if(!passout) 577109998Smarkm { 578109998Smarkm passout = NCONF_get_string(req_conf, SECTION, "output_password"); 579109998Smarkm if (!passout) 580109998Smarkm ERR_clear_error(); 581109998Smarkm } 58259191Skris 583109998Smarkm p = NCONF_get_string(req_conf, SECTION, STRING_MASK); 584109998Smarkm if (!p) 585109998Smarkm ERR_clear_error(); 58659191Skris 58759191Skris if(p && !ASN1_STRING_set_default_mask_asc(p)) { 58859191Skris BIO_printf(bio_err, "Invalid global string mask setting %s\n", p); 58959191Skris goto end; 59059191Skris } 59159191Skris 592109998Smarkm if (chtype != MBSTRING_UTF8) 593109998Smarkm { 594109998Smarkm p = NCONF_get_string(req_conf, SECTION, UTF8_IN); 595109998Smarkm if (!p) 596109998Smarkm ERR_clear_error(); 597109998Smarkm else if (!strcmp(p, "yes")) 598109998Smarkm chtype = MBSTRING_UTF8; 599109998Smarkm } 600109998Smarkm 601109998Smarkm 60259191Skris if(!req_exts) 603109998Smarkm { 604109998Smarkm req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS); 605109998Smarkm if (!req_exts) 606109998Smarkm ERR_clear_error(); 607109998Smarkm } 60859191Skris if(req_exts) { 60959191Skris /* Check syntax of file */ 61059191Skris X509V3_CTX ctx; 61159191Skris X509V3_set_ctx_test(&ctx); 612109998Smarkm X509V3_set_nconf(&ctx, req_conf); 613109998Smarkm if(!X509V3_EXT_add_nconf(req_conf, &ctx, req_exts, NULL)) { 61459191Skris BIO_printf(bio_err, 61559191Skris "Error Loading request extension section %s\n", 61659191Skris req_exts); 61759191Skris goto end; 61859191Skris } 61959191Skris } 62059191Skris 62155714Skris in=BIO_new(BIO_s_file()); 62255714Skris out=BIO_new(BIO_s_file()); 62355714Skris if ((in == NULL) || (out == NULL)) 62455714Skris goto end; 62555714Skris 626111147Snectar#ifndef OPENSSL_NO_ENGINE 627109998Smarkm e = setup_engine(bio_err, engine, 0); 628111147Snectar#endif 629109998Smarkm 63055714Skris if (keyfile != NULL) 63155714Skris { 632109998Smarkm pkey = load_key(bio_err, keyfile, keyform, 0, passin, e, 633109998Smarkm "Private Key"); 634109998Smarkm if (!pkey) 63555714Skris { 636109998Smarkm /* load_key() has already printed an appropriate 637109998Smarkm message */ 63855714Skris goto end; 63955714Skris } 640109998Smarkm if (EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA) 64159191Skris { 642109998Smarkm char *randfile = NCONF_get_string(req_conf,SECTION,"RANDFILE"); 643109998Smarkm if (randfile == NULL) 644109998Smarkm ERR_clear_error(); 645109998Smarkm app_RAND_load_file(randfile, bio_err, 0); 64659191Skris } 64755714Skris } 64855714Skris 64955714Skris if (newreq && (pkey == NULL)) 65055714Skris { 651109998Smarkm char *randfile = NCONF_get_string(req_conf,SECTION,"RANDFILE"); 652109998Smarkm if (randfile == NULL) 653109998Smarkm ERR_clear_error(); 65459191Skris app_RAND_load_file(randfile, bio_err, 0); 65568651Skris if (inrand) 65668651Skris app_RAND_load_files(inrand); 65759191Skris 65855714Skris if (newkey <= 0) 65955714Skris { 660109998Smarkm if (!NCONF_get_number(req_conf,SECTION,BITS, &newkey)) 66155714Skris newkey=DEFAULT_KEY_LENGTH; 66255714Skris } 66355714Skris 66455714Skris if (newkey < MIN_KEY_LENGTH) 66555714Skris { 66655714Skris BIO_printf(bio_err,"private key length is too short,\n"); 66755714Skris BIO_printf(bio_err,"it needs to be at least %d bits, not %d\n",MIN_KEY_LENGTH,newkey); 66855714Skris goto end; 66955714Skris } 67055714Skris BIO_printf(bio_err,"Generating a %d bit %s private key\n", 67155714Skris newkey,(pkey_type == TYPE_RSA)?"RSA":"DSA"); 67255714Skris 67355714Skris if ((pkey=EVP_PKEY_new()) == NULL) goto end; 67455714Skris 675109998Smarkm#ifndef OPENSSL_NO_RSA 67655714Skris if (pkey_type == TYPE_RSA) 67755714Skris { 67855714Skris if (!EVP_PKEY_assign_RSA(pkey, 67955714Skris RSA_generate_key(newkey,0x10001, 68055714Skris req_cb,bio_err))) 68155714Skris goto end; 68255714Skris } 68355714Skris else 68455714Skris#endif 685109998Smarkm#ifndef OPENSSL_NO_DSA 68655714Skris if (pkey_type == TYPE_DSA) 68755714Skris { 68855714Skris if (!DSA_generate_key(dsa_params)) goto end; 68955714Skris if (!EVP_PKEY_assign_DSA(pkey,dsa_params)) goto end; 69055714Skris dsa_params=NULL; 69155714Skris } 69255714Skris#endif 69355714Skris 69459191Skris app_RAND_write_file(randfile, bio_err); 69555714Skris 69655714Skris if (pkey == NULL) goto end; 69755714Skris 69855714Skris if (keyout == NULL) 699109998Smarkm { 700109998Smarkm keyout=NCONF_get_string(req_conf,SECTION,KEYFILE); 701109998Smarkm if (keyout == NULL) 702109998Smarkm ERR_clear_error(); 703109998Smarkm } 704109998Smarkm 70555714Skris if (keyout == NULL) 70655714Skris { 70755714Skris BIO_printf(bio_err,"writing new private key to stdout\n"); 70855714Skris BIO_set_fp(out,stdout,BIO_NOCLOSE); 709109998Smarkm#ifdef OPENSSL_SYS_VMS 71068651Skris { 71168651Skris BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 71268651Skris out = BIO_push(tmpbio, out); 71355714Skris } 71468651Skris#endif 71568651Skris } 71655714Skris else 71755714Skris { 71855714Skris BIO_printf(bio_err,"writing new private key to '%s'\n",keyout); 71955714Skris if (BIO_write_filename(out,keyout) <= 0) 72055714Skris { 72155714Skris perror(keyout); 72255714Skris goto end; 72355714Skris } 72455714Skris } 72555714Skris 726109998Smarkm p=NCONF_get_string(req_conf,SECTION,"encrypt_rsa_key"); 72755714Skris if (p == NULL) 728109998Smarkm { 729109998Smarkm ERR_clear_error(); 730109998Smarkm p=NCONF_get_string(req_conf,SECTION,"encrypt_key"); 731109998Smarkm if (p == NULL) 732109998Smarkm ERR_clear_error(); 733109998Smarkm } 73455714Skris if ((p != NULL) && (strcmp(p,"no") == 0)) 73555714Skris cipher=NULL; 73655714Skris if (nodes) cipher=NULL; 73755714Skris 73855714Skris i=0; 73955714Skrisloop: 74055714Skris if (!PEM_write_bio_PrivateKey(out,pkey,cipher, 74159191Skris NULL,0,NULL,passout)) 74255714Skris { 74355714Skris if ((ERR_GET_REASON(ERR_peek_error()) == 74455714Skris PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3)) 74555714Skris { 74655714Skris ERR_clear_error(); 74755714Skris i++; 74855714Skris goto loop; 74955714Skris } 75055714Skris goto end; 75155714Skris } 75255714Skris BIO_printf(bio_err,"-----\n"); 75355714Skris } 75455714Skris 75555714Skris if (!newreq) 75655714Skris { 75755714Skris /* Since we are using a pre-existing certificate 75855714Skris * request, the kludge 'format' info should not be 75955714Skris * changed. */ 76055714Skris kludge= -1; 76155714Skris if (infile == NULL) 76255714Skris BIO_set_fp(in,stdin,BIO_NOCLOSE); 76355714Skris else 76455714Skris { 76555714Skris if (BIO_read_filename(in,infile) <= 0) 76655714Skris { 76755714Skris perror(infile); 76855714Skris goto end; 76955714Skris } 77055714Skris } 77155714Skris 77255714Skris if (informat == FORMAT_ASN1) 77355714Skris req=d2i_X509_REQ_bio(in,NULL); 77455714Skris else if (informat == FORMAT_PEM) 77555714Skris req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL); 77655714Skris else 77755714Skris { 77855714Skris BIO_printf(bio_err,"bad input format specified for X509 request\n"); 77955714Skris goto end; 78055714Skris } 78155714Skris if (req == NULL) 78255714Skris { 78355714Skris BIO_printf(bio_err,"unable to load X509 request\n"); 78455714Skris goto end; 78555714Skris } 78655714Skris } 78755714Skris 78855714Skris if (newreq || x509) 78955714Skris { 79055714Skris if (pkey == NULL) 79155714Skris { 79255714Skris BIO_printf(bio_err,"you need to specify a private key\n"); 79355714Skris goto end; 79455714Skris } 795109998Smarkm#ifndef OPENSSL_NO_DSA 79672613Skris if (pkey->type == EVP_PKEY_DSA) 79772613Skris digest=EVP_dss1(); 79872613Skris#endif 79955714Skris if (req == NULL) 80055714Skris { 80155714Skris req=X509_REQ_new(); 80255714Skris if (req == NULL) 80355714Skris { 80455714Skris goto end; 80555714Skris } 80655714Skris 807109998Smarkm i=make_REQ(req,pkey,subj,!x509, chtype); 808109998Smarkm subj=NULL; /* done processing '-subj' option */ 809109998Smarkm if ((kludge > 0) && !sk_X509_ATTRIBUTE_num(req->req_info->attributes)) 810109998Smarkm { 811109998Smarkm sk_X509_ATTRIBUTE_free(req->req_info->attributes); 812109998Smarkm req->req_info->attributes = NULL; 813109998Smarkm } 81455714Skris if (!i) 81555714Skris { 81655714Skris BIO_printf(bio_err,"problems making Certificate Request\n"); 81755714Skris goto end; 81855714Skris } 81955714Skris } 82055714Skris if (x509) 82155714Skris { 82255714Skris EVP_PKEY *tmppkey; 82355714Skris X509V3_CTX ext_ctx; 82455714Skris if ((x509ss=X509_new()) == NULL) goto end; 82555714Skris 82655714Skris /* Set version to V3 */ 82755714Skris if(!X509_set_version(x509ss, 2)) goto end; 828109998Smarkm if (serial) 829109998Smarkm { 830109998Smarkm if (!X509_set_serialNumber(x509ss, serial)) goto end; 831109998Smarkm } 832109998Smarkm else 833109998Smarkm { 834109998Smarkm if (!ASN1_INTEGER_set(X509_get_serialNumber(x509ss),0L)) goto end; 835109998Smarkm } 83655714Skris 837100928Snectar if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req))) goto end; 838100928Snectar if (!X509_gmtime_adj(X509_get_notBefore(x509ss),0)) goto end; 839100928Snectar if (!X509_gmtime_adj(X509_get_notAfter(x509ss), (long)60*60*24*days)) goto end; 840100928Snectar if (!X509_set_subject_name(x509ss, X509_REQ_get_subject_name(req))) goto end; 84155714Skris tmppkey = X509_REQ_get_pubkey(req); 842100928Snectar if (!tmppkey || !X509_set_pubkey(x509ss,tmppkey)) goto end; 84355714Skris EVP_PKEY_free(tmppkey); 84455714Skris 84555714Skris /* Set up V3 context struct */ 84655714Skris 84755714Skris X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0); 848109998Smarkm X509V3_set_nconf(&ext_ctx, req_conf); 84955714Skris 85055714Skris /* Add extensions */ 851109998Smarkm if(extensions && !X509V3_EXT_add_nconf(req_conf, 85255714Skris &ext_ctx, extensions, x509ss)) 853109998Smarkm { 854109998Smarkm BIO_printf(bio_err, 855109998Smarkm "Error Loading extension section %s\n", 856109998Smarkm extensions); 857109998Smarkm goto end; 858109998Smarkm } 859109998Smarkm 86055714Skris if (!(i=X509_sign(x509ss,pkey,digest))) 86155714Skris goto end; 86255714Skris } 86355714Skris else 86455714Skris { 86559191Skris X509V3_CTX ext_ctx; 86659191Skris 86759191Skris /* Set up V3 context struct */ 86859191Skris 86959191Skris X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0); 870109998Smarkm X509V3_set_nconf(&ext_ctx, req_conf); 87159191Skris 87259191Skris /* Add extensions */ 873109998Smarkm if(req_exts && !X509V3_EXT_REQ_add_nconf(req_conf, 87459191Skris &ext_ctx, req_exts, req)) 875109998Smarkm { 876109998Smarkm BIO_printf(bio_err, 877109998Smarkm "Error Loading extension section %s\n", 878109998Smarkm req_exts); 879109998Smarkm goto end; 880109998Smarkm } 88155714Skris if (!(i=X509_REQ_sign(req,pkey,digest))) 88255714Skris goto end; 88355714Skris } 88455714Skris } 88555714Skris 886109998Smarkm if (subj && x509) 887109998Smarkm { 888109998Smarkm BIO_printf(bio_err, "Cannot modifiy certificate subject\n"); 889109998Smarkm goto end; 890109998Smarkm } 891109998Smarkm 892109998Smarkm if (subj && !x509) 893109998Smarkm { 894109998Smarkm if (verbose) 895109998Smarkm { 896109998Smarkm BIO_printf(bio_err, "Modifying Request's Subject\n"); 897109998Smarkm print_name(bio_err, "old subject=", X509_REQ_get_subject_name(req), nmflag); 898109998Smarkm } 899109998Smarkm 900109998Smarkm if (build_subject(req, subj, chtype) == 0) 901109998Smarkm { 902109998Smarkm BIO_printf(bio_err, "ERROR: cannot modify subject\n"); 903109998Smarkm ex=1; 904109998Smarkm goto end; 905109998Smarkm } 906109998Smarkm 907109998Smarkm req->req_info->enc.modified = 1; 908109998Smarkm 909109998Smarkm if (verbose) 910109998Smarkm { 911109998Smarkm print_name(bio_err, "new subject=", X509_REQ_get_subject_name(req), nmflag); 912109998Smarkm } 913109998Smarkm } 914109998Smarkm 91555714Skris if (verify && !x509) 91655714Skris { 91755714Skris int tmp=0; 91855714Skris 91955714Skris if (pkey == NULL) 92055714Skris { 92155714Skris pkey=X509_REQ_get_pubkey(req); 92255714Skris tmp=1; 92355714Skris if (pkey == NULL) goto end; 92455714Skris } 92555714Skris 92655714Skris i=X509_REQ_verify(req,pkey); 92755714Skris if (tmp) { 92855714Skris EVP_PKEY_free(pkey); 92955714Skris pkey=NULL; 93055714Skris } 93155714Skris 93255714Skris if (i < 0) 93355714Skris { 93455714Skris goto end; 93555714Skris } 93655714Skris else if (i == 0) 93755714Skris { 93855714Skris BIO_printf(bio_err,"verify failure\n"); 939109998Smarkm ERR_print_errors(bio_err); 94055714Skris } 94155714Skris else /* if (i > 0) */ 94255714Skris BIO_printf(bio_err,"verify OK\n"); 94355714Skris } 94455714Skris 945109998Smarkm if (noout && !text && !modulus && !subject && !pubkey) 94655714Skris { 94755714Skris ex=0; 94855714Skris goto end; 94955714Skris } 95055714Skris 95155714Skris if (outfile == NULL) 95268651Skris { 95355714Skris BIO_set_fp(out,stdout,BIO_NOCLOSE); 954109998Smarkm#ifdef OPENSSL_SYS_VMS 95568651Skris { 95668651Skris BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 95768651Skris out = BIO_push(tmpbio, out); 95868651Skris } 95968651Skris#endif 96068651Skris } 96155714Skris else 96255714Skris { 96355714Skris if ((keyout != NULL) && (strcmp(outfile,keyout) == 0)) 96455714Skris i=(int)BIO_append_filename(out,outfile); 96555714Skris else 96655714Skris i=(int)BIO_write_filename(out,outfile); 96755714Skris if (!i) 96855714Skris { 96955714Skris perror(outfile); 97055714Skris goto end; 97155714Skris } 97255714Skris } 97355714Skris 974109998Smarkm if (pubkey) 975109998Smarkm { 976109998Smarkm EVP_PKEY *tpubkey; 977109998Smarkm tpubkey=X509_REQ_get_pubkey(req); 978109998Smarkm if (tpubkey == NULL) 979109998Smarkm { 980109998Smarkm BIO_printf(bio_err,"Error getting public key\n"); 981109998Smarkm ERR_print_errors(bio_err); 982109998Smarkm goto end; 983109998Smarkm } 984109998Smarkm PEM_write_bio_PUBKEY(out, tpubkey); 985109998Smarkm EVP_PKEY_free(tpubkey); 986109998Smarkm } 987109998Smarkm 98855714Skris if (text) 98955714Skris { 99055714Skris if (x509) 991109998Smarkm X509_print_ex(out, x509ss, nmflag, reqflag); 99255714Skris else 993109998Smarkm X509_REQ_print_ex(out, req, nmflag, reqflag); 99455714Skris } 99555714Skris 996109998Smarkm if(subject) 997109998Smarkm { 998109998Smarkm if(x509) 999109998Smarkm print_name(out, "subject=", X509_get_subject_name(x509ss), nmflag); 1000109998Smarkm else 1001109998Smarkm print_name(out, "subject=", X509_REQ_get_subject_name(req), nmflag); 1002109998Smarkm } 1003109998Smarkm 100455714Skris if (modulus) 100555714Skris { 1006109998Smarkm EVP_PKEY *tpubkey; 100755714Skris 100855714Skris if (x509) 1009109998Smarkm tpubkey=X509_get_pubkey(x509ss); 101055714Skris else 1011109998Smarkm tpubkey=X509_REQ_get_pubkey(req); 1012109998Smarkm if (tpubkey == NULL) 101355714Skris { 101455714Skris fprintf(stdout,"Modulus=unavailable\n"); 101555714Skris goto end; 101655714Skris } 101755714Skris fprintf(stdout,"Modulus="); 1018109998Smarkm#ifndef OPENSSL_NO_RSA 1019109998Smarkm if (tpubkey->type == EVP_PKEY_RSA) 1020109998Smarkm BN_print(out,tpubkey->pkey.rsa->n); 102155714Skris else 102255714Skris#endif 102355714Skris fprintf(stdout,"Wrong Algorithm type"); 1024109998Smarkm EVP_PKEY_free(tpubkey); 102555714Skris fprintf(stdout,"\n"); 102655714Skris } 102755714Skris 102855714Skris if (!noout && !x509) 102955714Skris { 103055714Skris if (outformat == FORMAT_ASN1) 103155714Skris i=i2d_X509_REQ_bio(out,req); 103259191Skris else if (outformat == FORMAT_PEM) { 103359191Skris if(newhdr) i=PEM_write_bio_X509_REQ_NEW(out,req); 103459191Skris else i=PEM_write_bio_X509_REQ(out,req); 103559191Skris } else { 103655714Skris BIO_printf(bio_err,"bad output format specified for outfile\n"); 103755714Skris goto end; 103855714Skris } 103955714Skris if (!i) 104055714Skris { 104155714Skris BIO_printf(bio_err,"unable to write X509 request\n"); 104255714Skris goto end; 104355714Skris } 104455714Skris } 104555714Skris if (!noout && x509 && (x509ss != NULL)) 104655714Skris { 104755714Skris if (outformat == FORMAT_ASN1) 104855714Skris i=i2d_X509_bio(out,x509ss); 104955714Skris else if (outformat == FORMAT_PEM) 105055714Skris i=PEM_write_bio_X509(out,x509ss); 105155714Skris else { 105255714Skris BIO_printf(bio_err,"bad output format specified for outfile\n"); 105355714Skris goto end; 105455714Skris } 105555714Skris if (!i) 105655714Skris { 105755714Skris BIO_printf(bio_err,"unable to write X509 certificate\n"); 105855714Skris goto end; 105955714Skris } 106055714Skris } 106155714Skris ex=0; 106255714Skrisend: 1063109998Smarkm#ifndef MONOLITH 1064109998Smarkm if(to_free) 1065109998Smarkm OPENSSL_free(to_free); 1066109998Smarkm#endif 106755714Skris if (ex) 106855714Skris { 106955714Skris ERR_print_errors(bio_err); 107055714Skris } 1071109998Smarkm if ((req_conf != NULL) && (req_conf != config)) NCONF_free(req_conf); 107255714Skris BIO_free(in); 107368651Skris BIO_free_all(out); 107455714Skris EVP_PKEY_free(pkey); 107555714Skris X509_REQ_free(req); 107655714Skris X509_free(x509ss); 1077109998Smarkm ASN1_INTEGER_free(serial); 107868651Skris if(passargin && passin) OPENSSL_free(passin); 107968651Skris if(passargout && passout) OPENSSL_free(passout); 108055714Skris OBJ_cleanup(); 1081109998Smarkm#ifndef OPENSSL_NO_DSA 108255714Skris if (dsa_params != NULL) DSA_free(dsa_params); 108355714Skris#endif 1084109998Smarkm apps_shutdown(); 1085109998Smarkm OPENSSL_EXIT(ex); 108655714Skris } 108755714Skris 1088109998Smarkmstatic int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int attribs, 1089109998Smarkm unsigned long chtype) 109055714Skris { 109155714Skris int ret=0,i; 109259191Skris char no_prompt = 0; 109359191Skris STACK_OF(CONF_VALUE) *dn_sk, *attr_sk = NULL; 109459191Skris char *tmp, *dn_sect,*attr_sect; 109559191Skris 1096109998Smarkm tmp=NCONF_get_string(req_conf,SECTION,PROMPT); 1097109998Smarkm if (tmp == NULL) 1098109998Smarkm ERR_clear_error(); 109959191Skris if((tmp != NULL) && !strcmp(tmp, "no")) no_prompt = 1; 110059191Skris 1101109998Smarkm dn_sect=NCONF_get_string(req_conf,SECTION,DISTINGUISHED_NAME); 110259191Skris if (dn_sect == NULL) 110355714Skris { 110455714Skris BIO_printf(bio_err,"unable to find '%s' in config\n", 110555714Skris DISTINGUISHED_NAME); 110655714Skris goto err; 110755714Skris } 1108109998Smarkm dn_sk=NCONF_get_section(req_conf,dn_sect); 110959191Skris if (dn_sk == NULL) 111055714Skris { 111159191Skris BIO_printf(bio_err,"unable to get '%s' section\n",dn_sect); 111255714Skris goto err; 111355714Skris } 111455714Skris 1115109998Smarkm attr_sect=NCONF_get_string(req_conf,SECTION,ATTRIBUTES); 111659191Skris if (attr_sect == NULL) 1117109998Smarkm { 1118109998Smarkm ERR_clear_error(); 111959191Skris attr_sk=NULL; 1120109998Smarkm } 112155714Skris else 112255714Skris { 1123109998Smarkm attr_sk=NCONF_get_section(req_conf,attr_sect); 112459191Skris if (attr_sk == NULL) 112555714Skris { 112659191Skris BIO_printf(bio_err,"unable to get '%s' section\n",attr_sect); 112755714Skris goto err; 112855714Skris } 112955714Skris } 113055714Skris 113159191Skris /* setup version number */ 113259191Skris if (!X509_REQ_set_version(req,0L)) goto err; /* version 1 */ 113355714Skris 1134109998Smarkm if (no_prompt) 1135109998Smarkm i = auto_info(req, dn_sk, attr_sk, attribs, chtype); 1136109998Smarkm else 1137109998Smarkm { 1138109998Smarkm if (subj) 1139109998Smarkm i = build_subject(req, subj, chtype); 1140109998Smarkm else 1141109998Smarkm i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, chtype); 1142109998Smarkm } 114359191Skris if(!i) goto err; 114459191Skris 1145100928Snectar if (!X509_REQ_set_pubkey(req,pkey)) goto err; 114659191Skris 114759191Skris ret=1; 114859191Skriserr: 114959191Skris return(ret); 115059191Skris } 115159191Skris 1152109998Smarkm/* 1153109998Smarkm * subject is expected to be in the format /type0=value0/type1=value1/type2=... 1154109998Smarkm * where characters may be escaped by \ 1155109998Smarkm */ 1156109998Smarkmstatic int build_subject(X509_REQ *req, char *subject, unsigned long chtype) 1157109998Smarkm { 1158109998Smarkm X509_NAME *n; 115959191Skris 1160109998Smarkm if (!(n = do_subject(subject, chtype))) 1161109998Smarkm return 0; 1162109998Smarkm 1163109998Smarkm if (!X509_REQ_set_subject_name(req, n)) 1164109998Smarkm { 1165109998Smarkm X509_NAME_free(n); 1166109998Smarkm return 0; 1167109998Smarkm } 1168109998Smarkm X509_NAME_free(n); 1169109998Smarkm return 1; 1170109998Smarkm} 1171109998Smarkm 1172109998Smarkm 117359191Skrisstatic int prompt_info(X509_REQ *req, 117459191Skris STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect, 1175109998Smarkm STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, int attribs, 1176109998Smarkm unsigned long chtype) 117759191Skris { 117859191Skris int i; 117959191Skris char *p,*q; 118059191Skris char buf[100]; 1181109998Smarkm int nid; 1182109998Smarkm long n_min,n_max; 118359191Skris char *type,*def,*value; 118459191Skris CONF_VALUE *v; 118559191Skris X509_NAME *subj; 118659191Skris subj = X509_REQ_get_subject_name(req); 118755714Skris 1188109998Smarkm if(!batch) 1189109998Smarkm { 1190109998Smarkm BIO_printf(bio_err,"You are about to be asked to enter information that will be incorporated\n"); 1191109998Smarkm BIO_printf(bio_err,"into your certificate request.\n"); 1192109998Smarkm BIO_printf(bio_err,"What you are about to enter is what is called a Distinguished Name or a DN.\n"); 1193109998Smarkm BIO_printf(bio_err,"There are quite a few fields but you can leave some blank\n"); 1194109998Smarkm BIO_printf(bio_err,"For some fields there will be a default value,\n"); 1195109998Smarkm BIO_printf(bio_err,"If you enter '.', the field will be left blank.\n"); 1196109998Smarkm BIO_printf(bio_err,"-----\n"); 1197109998Smarkm } 119855714Skris 1199109998Smarkm 120059191Skris if (sk_CONF_VALUE_num(dn_sk)) 120155714Skris { 120255714Skris i= -1; 120355714Skrisstart: for (;;) 120455714Skris { 120555714Skris i++; 120659191Skris if (sk_CONF_VALUE_num(dn_sk) <= i) break; 120755714Skris 120859191Skris v=sk_CONF_VALUE_value(dn_sk,i); 120955714Skris p=q=NULL; 121055714Skris type=v->name; 121155714Skris if(!check_end(type,"_min") || !check_end(type,"_max") || 121255714Skris !check_end(type,"_default") || 121355714Skris !check_end(type,"_value")) continue; 121455714Skris /* Skip past any leading X. X: X, etc to allow for 121555714Skris * multiple instances 121655714Skris */ 121755714Skris for(p = v->name; *p ; p++) 121855714Skris if ((*p == ':') || (*p == ',') || 121955714Skris (*p == '.')) { 122055714Skris p++; 122155714Skris if(*p) type = p; 122255714Skris break; 122355714Skris } 122455714Skris /* If OBJ not recognised ignore it */ 122555714Skris if ((nid=OBJ_txt2nid(type)) == NID_undef) goto start; 1226109998Smarkm 1227109998Smarkm if(strlen(v->name) > sizeof buf-9) 1228109998Smarkm { 1229109998Smarkm BIO_printf(bio_err,"Name '%s' too long\n",v->name); 1230109998Smarkm return 0; 1231109998Smarkm } 1232109998Smarkm 123355714Skris sprintf(buf,"%s_default",v->name); 1234109998Smarkm if ((def=NCONF_get_string(req_conf,dn_sect,buf)) == NULL) 1235109998Smarkm { 1236109998Smarkm ERR_clear_error(); 123755714Skris def=""; 1238109998Smarkm } 123955714Skris sprintf(buf,"%s_value",v->name); 1240109998Smarkm if ((value=NCONF_get_string(req_conf,dn_sect,buf)) == NULL) 1241109998Smarkm { 1242109998Smarkm ERR_clear_error(); 124355714Skris value=NULL; 1244109998Smarkm } 124555714Skris 124655714Skris sprintf(buf,"%s_min",v->name); 1247109998Smarkm if (!NCONF_get_number(req_conf,dn_sect,buf, &n_min)) 1248111147Snectar { 1249111147Snectar ERR_clear_error(); 1250109998Smarkm n_min = -1; 1251111147Snectar } 125255714Skris 125355714Skris sprintf(buf,"%s_max",v->name); 1254109998Smarkm if (!NCONF_get_number(req_conf,dn_sect,buf, &n_max)) 1255111147Snectar { 1256111147Snectar ERR_clear_error(); 1257109998Smarkm n_max = -1; 1258111147Snectar } 125955714Skris 126059191Skris if (!add_DN_object(subj,v->value,def,value,nid, 1261109998Smarkm n_min,n_max, chtype)) 126259191Skris return 0; 126355714Skris } 126459191Skris if (X509_NAME_entry_count(subj) == 0) 126555714Skris { 126655714Skris BIO_printf(bio_err,"error, no objects specified in config file\n"); 126759191Skris return 0; 126855714Skris } 126955714Skris 127055714Skris if (attribs) 127155714Skris { 1272109998Smarkm if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) && (!batch)) 127355714Skris { 127455714Skris BIO_printf(bio_err,"\nPlease enter the following 'extra' attributes\n"); 127555714Skris BIO_printf(bio_err,"to be sent with your certificate request\n"); 127655714Skris } 127755714Skris 127855714Skris i= -1; 127955714Skrisstart2: for (;;) 128055714Skris { 128155714Skris i++; 128259191Skris if ((attr_sk == NULL) || 128359191Skris (sk_CONF_VALUE_num(attr_sk) <= i)) 128455714Skris break; 128555714Skris 128659191Skris v=sk_CONF_VALUE_value(attr_sk,i); 128755714Skris type=v->name; 128855714Skris if ((nid=OBJ_txt2nid(type)) == NID_undef) 128955714Skris goto start2; 129055714Skris 1291109998Smarkm if(strlen(v->name) > sizeof buf-9) 1292109998Smarkm { 1293109998Smarkm BIO_printf(bio_err,"Name '%s' too long\n",v->name); 1294109998Smarkm return 0; 1295109998Smarkm } 1296109998Smarkm 129755714Skris sprintf(buf,"%s_default",type); 1298109998Smarkm if ((def=NCONF_get_string(req_conf,attr_sect,buf)) 129955714Skris == NULL) 1300109998Smarkm { 1301109998Smarkm ERR_clear_error(); 130255714Skris def=""; 1303109998Smarkm } 130455714Skris 1305109998Smarkm 130655714Skris sprintf(buf,"%s_value",type); 1307109998Smarkm if ((value=NCONF_get_string(req_conf,attr_sect,buf)) 130855714Skris == NULL) 1309109998Smarkm { 1310109998Smarkm ERR_clear_error(); 131155714Skris value=NULL; 1312109998Smarkm } 131355714Skris 131455714Skris sprintf(buf,"%s_min",type); 1315109998Smarkm if (!NCONF_get_number(req_conf,attr_sect,buf, &n_min)) 1316109998Smarkm n_min = -1; 131755714Skris 131855714Skris sprintf(buf,"%s_max",type); 1319109998Smarkm if (!NCONF_get_number(req_conf,attr_sect,buf, &n_max)) 1320109998Smarkm n_max = -1; 132155714Skris 132259191Skris if (!add_attribute_object(req, 1323109998Smarkm v->value,def,value,nid,n_min,n_max, chtype)) 132459191Skris return 0; 132555714Skris } 132655714Skris } 132755714Skris } 132855714Skris else 132955714Skris { 133055714Skris BIO_printf(bio_err,"No template, please set one up.\n"); 133159191Skris return 0; 133255714Skris } 133355714Skris 133459191Skris return 1; 133555714Skris 133655714Skris } 133755714Skris 133859191Skrisstatic int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk, 1339109998Smarkm STACK_OF(CONF_VALUE) *attr_sk, int attribs, unsigned long chtype) 134059191Skris { 134159191Skris int i; 134259191Skris char *p,*q; 134359191Skris char *type; 134459191Skris CONF_VALUE *v; 134559191Skris X509_NAME *subj; 134659191Skris 134759191Skris subj = X509_REQ_get_subject_name(req); 134859191Skris 134959191Skris for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) 135059191Skris { 135159191Skris v=sk_CONF_VALUE_value(dn_sk,i); 135259191Skris p=q=NULL; 135359191Skris type=v->name; 135459191Skris /* Skip past any leading X. X: X, etc to allow for 135559191Skris * multiple instances 135659191Skris */ 135759191Skris for(p = v->name; *p ; p++) 135868651Skris#ifndef CHARSET_EBCDIC 135959191Skris if ((*p == ':') || (*p == ',') || (*p == '.')) { 136068651Skris#else 136168651Skris if ((*p == os_toascii[':']) || (*p == os_toascii[',']) || (*p == os_toascii['.'])) { 136268651Skris#endif 136359191Skris p++; 136459191Skris if(*p) type = p; 136559191Skris break; 136659191Skris } 1367109998Smarkm if (!X509_NAME_add_entry_by_txt(subj,type, chtype, 136859191Skris (unsigned char *) v->value,-1,-1,0)) return 0; 136959191Skris 137059191Skris } 137159191Skris 137259191Skris if (!X509_NAME_entry_count(subj)) 137359191Skris { 137459191Skris BIO_printf(bio_err,"error, no objects specified in config file\n"); 137559191Skris return 0; 137659191Skris } 137759191Skris if (attribs) 137859191Skris { 137959191Skris for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) 138059191Skris { 138159191Skris v=sk_CONF_VALUE_value(attr_sk,i); 1382109998Smarkm if(!X509_REQ_add1_attr_by_txt(req, v->name, chtype, 138359191Skris (unsigned char *)v->value, -1)) return 0; 138459191Skris } 138559191Skris } 138659191Skris return 1; 138759191Skris } 138859191Skris 138959191Skris 139055714Skrisstatic int add_DN_object(X509_NAME *n, char *text, char *def, char *value, 1391109998Smarkm int nid, int n_min, int n_max, unsigned long chtype) 139255714Skris { 139359191Skris int i,ret=0; 139455714Skris MS_STATIC char buf[1024]; 139559191Skrisstart: 1396109998Smarkm if (!batch) BIO_printf(bio_err,"%s [%s]:",text,def); 139755714Skris (void)BIO_flush(bio_err); 1398109998Smarkm if(value != NULL) 139955714Skris { 1400109998Smarkm OPENSSL_assert(strlen(value) < sizeof buf-2); 140155714Skris strcpy(buf,value); 140255714Skris strcat(buf,"\n"); 140355714Skris BIO_printf(bio_err,"%s\n",value); 140455714Skris } 140555714Skris else 140655714Skris { 140755714Skris buf[0]='\0'; 1408109998Smarkm if (!batch) 1409109998Smarkm { 1410109998Smarkm fgets(buf,sizeof buf,stdin); 1411109998Smarkm } 1412109998Smarkm else 1413109998Smarkm { 1414109998Smarkm buf[0] = '\n'; 1415109998Smarkm buf[1] = '\0'; 1416109998Smarkm } 141755714Skris } 141855714Skris 141955714Skris if (buf[0] == '\0') return(0); 142055714Skris else if (buf[0] == '\n') 142155714Skris { 142255714Skris if ((def == NULL) || (def[0] == '\0')) 142355714Skris return(1); 142455714Skris strcpy(buf,def); 142555714Skris strcat(buf,"\n"); 142655714Skris } 142755714Skris else if ((buf[0] == '.') && (buf[1] == '\n')) return(1); 142855714Skris 142955714Skris i=strlen(buf); 143055714Skris if (buf[i-1] != '\n') 143155714Skris { 143255714Skris BIO_printf(bio_err,"weird input :-(\n"); 143355714Skris return(0); 143455714Skris } 143555714Skris buf[--i]='\0'; 143655714Skris#ifdef CHARSET_EBCDIC 143755714Skris ebcdic2ascii(buf, buf, i); 143855714Skris#endif 1439109998Smarkm if(!req_check_len(i, n_min, n_max)) goto start; 1440109998Smarkm if (!X509_NAME_add_entry_by_NID(n,nid, chtype, 144159191Skris (unsigned char *) buf, -1,-1,0)) goto err; 144255714Skris ret=1; 144355714Skriserr: 144455714Skris return(ret); 144555714Skris } 144655714Skris 144759191Skrisstatic int add_attribute_object(X509_REQ *req, char *text, 1448109998Smarkm char *def, char *value, int nid, int n_min, 1449109998Smarkm int n_max, unsigned long chtype) 145055714Skris { 145159191Skris int i; 145255714Skris static char buf[1024]; 145355714Skris 145455714Skrisstart: 1455109998Smarkm if (!batch) BIO_printf(bio_err,"%s [%s]:",text,def); 145655714Skris (void)BIO_flush(bio_err); 145755714Skris if (value != NULL) 145855714Skris { 1459109998Smarkm OPENSSL_assert(strlen(value) < sizeof buf-2); 146055714Skris strcpy(buf,value); 146155714Skris strcat(buf,"\n"); 146255714Skris BIO_printf(bio_err,"%s\n",value); 146355714Skris } 146455714Skris else 146555714Skris { 146655714Skris buf[0]='\0'; 1467109998Smarkm if (!batch) 1468109998Smarkm { 1469109998Smarkm fgets(buf,sizeof buf,stdin); 1470109998Smarkm } 1471109998Smarkm else 1472109998Smarkm { 1473109998Smarkm buf[0] = '\n'; 1474109998Smarkm buf[1] = '\0'; 1475109998Smarkm } 147655714Skris } 147755714Skris 147855714Skris if (buf[0] == '\0') return(0); 147955714Skris else if (buf[0] == '\n') 148055714Skris { 148155714Skris if ((def == NULL) || (def[0] == '\0')) 148255714Skris return(1); 148355714Skris strcpy(buf,def); 148455714Skris strcat(buf,"\n"); 148555714Skris } 148655714Skris else if ((buf[0] == '.') && (buf[1] == '\n')) return(1); 148755714Skris 148855714Skris i=strlen(buf); 148955714Skris if (buf[i-1] != '\n') 149055714Skris { 149155714Skris BIO_printf(bio_err,"weird input :-(\n"); 149255714Skris return(0); 149355714Skris } 149455714Skris buf[--i]='\0'; 149568651Skris#ifdef CHARSET_EBCDIC 149668651Skris ebcdic2ascii(buf, buf, i); 149768651Skris#endif 1498109998Smarkm if(!req_check_len(i, n_min, n_max)) goto start; 149955714Skris 1500109998Smarkm if(!X509_REQ_add1_attr_by_NID(req, nid, chtype, 150159191Skris (unsigned char *)buf, -1)) { 150259191Skris BIO_printf(bio_err, "Error adding attribute\n"); 150359191Skris ERR_print_errors(bio_err); 150455714Skris goto err; 150559191Skris } 150655714Skris 150755714Skris return(1); 150855714Skriserr: 150955714Skris return(0); 151055714Skris } 151155714Skris 1512109998Smarkm#ifndef OPENSSL_NO_RSA 151355714Skrisstatic void MS_CALLBACK req_cb(int p, int n, void *arg) 151455714Skris { 151555714Skris char c='*'; 151655714Skris 151755714Skris if (p == 0) c='.'; 151855714Skris if (p == 1) c='+'; 151955714Skris if (p == 2) c='*'; 152055714Skris if (p == 3) c='\n'; 152155714Skris BIO_write((BIO *)arg,&c,1); 152255714Skris (void)BIO_flush((BIO *)arg); 152355714Skris#ifdef LINT 152455714Skris p=n; 152555714Skris#endif 152655714Skris } 152759191Skris#endif 152855714Skris 1529109998Smarkmstatic int req_check_len(int len, int n_min, int n_max) 153055714Skris { 1531109998Smarkm if ((n_min > 0) && (len < n_min)) 153255714Skris { 1533109998Smarkm BIO_printf(bio_err,"string is too short, it needs to be at least %d bytes long\n",n_min); 153455714Skris return(0); 153555714Skris } 1536109998Smarkm if ((n_max >= 0) && (len > n_max)) 153755714Skris { 1538109998Smarkm BIO_printf(bio_err,"string is too long, it needs to be less than %d bytes long\n",n_max); 153955714Skris return(0); 154055714Skris } 154155714Skris return(1); 154255714Skris } 154355714Skris 154455714Skris/* Check if the end of a string matches 'end' */ 154555714Skrisstatic int check_end(char *str, char *end) 154655714Skris{ 154755714Skris int elen, slen; 154855714Skris char *tmp; 154955714Skris elen = strlen(end); 155055714Skris slen = strlen(str); 155155714Skris if(elen > slen) return 1; 155255714Skris tmp = str + slen - elen; 155355714Skris return strcmp(tmp, end); 155455714Skris} 1555