req.c revision 55714
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>
6355714Skris#ifdef 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/rand.h>
7055714Skris#include <openssl/conf.h>
7155714Skris#include <openssl/err.h>
7255714Skris#include <openssl/asn1.h>
7355714Skris#include <openssl/x509.h>
7455714Skris#include <openssl/x509v3.h>
7555714Skris#include <openssl/objects.h>
7655714Skris#include <openssl/pem.h>
7755714Skris
7855714Skris#define SECTION		"req"
7955714Skris
8055714Skris#define BITS		"default_bits"
8155714Skris#define KEYFILE		"default_keyfile"
8255714Skris#define DISTINGUISHED_NAME	"distinguished_name"
8355714Skris#define ATTRIBUTES	"attributes"
8455714Skris#define V3_EXTENSIONS	"x509_extensions"
8555714Skris
8655714Skris#define DEFAULT_KEY_LENGTH	512
8755714Skris#define MIN_KEY_LENGTH		384
8855714Skris
8955714Skris#undef PROG
9055714Skris#define PROG	req_main
9155714Skris
9255714Skris/* -inform arg	- input format - default PEM (one of DER, TXT or PEM)
9355714Skris * -outform arg - output format - default PEM
9455714Skris * -in arg	- input file - default stdin
9555714Skris * -out arg	- output file - default stdout
9655714Skris * -verify	- check request signature
9755714Skris * -noout	- don't print stuff out.
9855714Skris * -text	- print out human readable text.
9955714Skris * -nodes	- no des encryption
10055714Skris * -config file	- Load configuration file.
10155714Skris * -key file	- make a request using key in file (or use it for verification).
10255714Skris * -keyform	- key file format.
10355714Skris * -newkey	- make a key and a request.
10455714Skris * -modulus	- print RSA modulus.
10555714Skris * -x509	- output a self signed X509 structure instead.
10655714Skris * -asn1-kludge	- output new certificate request in a format that some CA's
10755714Skris *		  require.  This format is wrong
10855714Skris */
10955714Skris
11055714Skrisstatic int make_REQ(X509_REQ *req,EVP_PKEY *pkey,int attribs);
11155714Skrisstatic int add_attribute_object(STACK_OF(X509_ATTRIBUTE) *n, char *text,
11255714Skris				char *def, char *value, int nid, int min,
11355714Skris				int max);
11455714Skrisstatic int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
11555714Skris	int nid,int min,int max);
11655714Skrisstatic void MS_CALLBACK req_cb(int p,int n,void *arg);
11755714Skrisstatic int req_fix_data(int nid,int *type,int len,int min,int max);
11855714Skrisstatic int check_end(char *str, char *end);
11955714Skrisstatic int add_oid_section(LHASH *conf);
12055714Skris#ifndef MONOLITH
12155714Skrisstatic char *default_config_file=NULL;
12255714Skrisstatic LHASH *config=NULL;
12355714Skris#endif
12455714Skrisstatic LHASH *req_conf=NULL;
12555714Skris
12655714Skris#define TYPE_RSA	1
12755714Skris#define TYPE_DSA	2
12855714Skris#define TYPE_DH		3
12955714Skris
13055714Skrisint MAIN(int argc, char **argv)
13155714Skris	{
13255714Skris#ifndef NO_DSA
13355714Skris	DSA *dsa_params=NULL;
13455714Skris#endif
13555714Skris	int ex=1,x509=0,days=30;
13655714Skris	X509 *x509ss=NULL;
13755714Skris	X509_REQ *req=NULL;
13855714Skris	EVP_PKEY *pkey=NULL;
13955714Skris	int i,badops=0,newreq=0,newkey= -1,pkey_type=0;
14055714Skris	BIO *in=NULL,*out=NULL;
14155714Skris	int informat,outformat,verify=0,noout=0,text=0,keyform=FORMAT_PEM;
14255714Skris	int nodes=0,kludge=0;
14355714Skris	char *infile,*outfile,*prog,*keyfile=NULL,*template=NULL,*keyout=NULL;
14455714Skris	char *extensions = NULL;
14555714Skris	EVP_CIPHER *cipher=NULL;
14655714Skris	int modulus=0;
14755714Skris	char *p;
14855714Skris	const EVP_MD *md_alg=NULL,*digest=EVP_md5();
14955714Skris#ifndef MONOLITH
15055714Skris	MS_STATIC char config_name[256];
15155714Skris#endif
15255714Skris
15355714Skris#ifndef NO_DES
15455714Skris	cipher=EVP_des_ede3_cbc();
15555714Skris#endif
15655714Skris	apps_startup();
15755714Skris
15855714Skris	if (bio_err == NULL)
15955714Skris		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
16055714Skris			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
16155714Skris
16255714Skris	infile=NULL;
16355714Skris	outfile=NULL;
16455714Skris	informat=FORMAT_PEM;
16555714Skris	outformat=FORMAT_PEM;
16655714Skris
16755714Skris	prog=argv[0];
16855714Skris	argc--;
16955714Skris	argv++;
17055714Skris	while (argc >= 1)
17155714Skris		{
17255714Skris		if 	(strcmp(*argv,"-inform") == 0)
17355714Skris			{
17455714Skris			if (--argc < 1) goto bad;
17555714Skris			informat=str2fmt(*(++argv));
17655714Skris			}
17755714Skris		else if (strcmp(*argv,"-outform") == 0)
17855714Skris			{
17955714Skris			if (--argc < 1) goto bad;
18055714Skris			outformat=str2fmt(*(++argv));
18155714Skris			}
18255714Skris		else if (strcmp(*argv,"-key") == 0)
18355714Skris			{
18455714Skris			if (--argc < 1) goto bad;
18555714Skris			keyfile= *(++argv);
18655714Skris			}
18755714Skris		else if (strcmp(*argv,"-new") == 0)
18855714Skris			{
18955714Skris			pkey_type=TYPE_RSA;
19055714Skris			newreq=1;
19155714Skris			}
19255714Skris		else if (strcmp(*argv,"-config") == 0)
19355714Skris			{
19455714Skris			if (--argc < 1) goto bad;
19555714Skris			template= *(++argv);
19655714Skris			}
19755714Skris		else if (strcmp(*argv,"-keyform") == 0)
19855714Skris			{
19955714Skris			if (--argc < 1) goto bad;
20055714Skris			keyform=str2fmt(*(++argv));
20155714Skris			}
20255714Skris		else if (strcmp(*argv,"-in") == 0)
20355714Skris			{
20455714Skris			if (--argc < 1) goto bad;
20555714Skris			infile= *(++argv);
20655714Skris			}
20755714Skris		else if (strcmp(*argv,"-out") == 0)
20855714Skris			{
20955714Skris			if (--argc < 1) goto bad;
21055714Skris			outfile= *(++argv);
21155714Skris			}
21255714Skris		else if (strcmp(*argv,"-keyout") == 0)
21355714Skris			{
21455714Skris			if (--argc < 1) goto bad;
21555714Skris			keyout= *(++argv);
21655714Skris			}
21755714Skris		else if (strcmp(*argv,"-newkey") == 0)
21855714Skris			{
21955714Skris			int is_numeric;
22055714Skris
22155714Skris			if (--argc < 1) goto bad;
22255714Skris			p= *(++argv);
22355714Skris			is_numeric = p[0] >= '0' && p[0] <= '9';
22455714Skris			if (strncmp("rsa:",p,4) == 0 || is_numeric)
22555714Skris				{
22655714Skris				pkey_type=TYPE_RSA;
22755714Skris				if(!is_numeric)
22855714Skris				    p+=4;
22955714Skris				newkey= atoi(p);
23055714Skris				}
23155714Skris			else
23255714Skris#ifndef NO_DSA
23355714Skris				if (strncmp("dsa:",p,4) == 0)
23455714Skris				{
23555714Skris				X509 *xtmp=NULL;
23655714Skris				EVP_PKEY *dtmp;
23755714Skris
23855714Skris				pkey_type=TYPE_DSA;
23955714Skris				p+=4;
24055714Skris				if ((in=BIO_new_file(p,"r")) == NULL)
24155714Skris					{
24255714Skris					perror(p);
24355714Skris					goto end;
24455714Skris					}
24555714Skris				if ((dsa_params=PEM_read_bio_DSAparams(in,NULL,NULL,NULL)) == NULL)
24655714Skris					{
24755714Skris					ERR_clear_error();
24855714Skris					(void)BIO_reset(in);
24955714Skris					if ((xtmp=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
25055714Skris						{
25155714Skris						BIO_printf(bio_err,"unable to load DSA parameters from file\n");
25255714Skris						goto end;
25355714Skris						}
25455714Skris
25555714Skris					dtmp=X509_get_pubkey(xtmp);
25655714Skris					if (dtmp->type == EVP_PKEY_DSA)
25755714Skris						dsa_params=DSAparams_dup(dtmp->pkey.dsa);
25855714Skris					EVP_PKEY_free(dtmp);
25955714Skris					X509_free(xtmp);
26055714Skris					if (dsa_params == NULL)
26155714Skris						{
26255714Skris						BIO_printf(bio_err,"Certificate does not contain DSA parameters\n");
26355714Skris						goto end;
26455714Skris						}
26555714Skris					}
26655714Skris				BIO_free(in);
26755714Skris				newkey=BN_num_bits(dsa_params->p);
26855714Skris				in=NULL;
26955714Skris				}
27055714Skris			else
27155714Skris#endif
27255714Skris#ifndef NO_DH
27355714Skris				if (strncmp("dh:",p,4) == 0)
27455714Skris				{
27555714Skris				pkey_type=TYPE_DH;
27655714Skris				p+=3;
27755714Skris				}
27855714Skris			else
27955714Skris#endif
28055714Skris				pkey_type=TYPE_RSA;
28155714Skris
28255714Skris			newreq=1;
28355714Skris			}
28455714Skris		else if (strcmp(*argv,"-modulus") == 0)
28555714Skris			modulus=1;
28655714Skris		else if (strcmp(*argv,"-verify") == 0)
28755714Skris			verify=1;
28855714Skris		else if (strcmp(*argv,"-nodes") == 0)
28955714Skris			nodes=1;
29055714Skris		else if (strcmp(*argv,"-noout") == 0)
29155714Skris			noout=1;
29255714Skris		else if (strcmp(*argv,"-text") == 0)
29355714Skris			text=1;
29455714Skris		else if (strcmp(*argv,"-x509") == 0)
29555714Skris			x509=1;
29655714Skris		else if (strcmp(*argv,"-asn1-kludge") == 0)
29755714Skris			kludge=1;
29855714Skris		else if (strcmp(*argv,"-no-asn1-kludge") == 0)
29955714Skris			kludge=0;
30055714Skris		else if (strcmp(*argv,"-days") == 0)
30155714Skris			{
30255714Skris			if (--argc < 1) goto bad;
30355714Skris			days= atoi(*(++argv));
30455714Skris			if (days == 0) days=30;
30555714Skris			}
30655714Skris		else if ((md_alg=EVP_get_digestbyname(&((*argv)[1]))) != NULL)
30755714Skris			{
30855714Skris			/* ok */
30955714Skris			digest=md_alg;
31055714Skris			}
31155714Skris		else
31255714Skris
31355714Skris			{
31455714Skris			BIO_printf(bio_err,"unknown option %s\n",*argv);
31555714Skris			badops=1;
31655714Skris			break;
31755714Skris			}
31855714Skris		argc--;
31955714Skris		argv++;
32055714Skris		}
32155714Skris
32255714Skris	if (badops)
32355714Skris		{
32455714Skrisbad:
32555714Skris		BIO_printf(bio_err,"%s [options] <infile >outfile\n",prog);
32655714Skris		BIO_printf(bio_err,"where options  are\n");
32755714Skris		BIO_printf(bio_err," -inform arg    input format - one of DER TXT PEM\n");
32855714Skris		BIO_printf(bio_err," -outform arg   output format - one of DER TXT PEM\n");
32955714Skris		BIO_printf(bio_err," -in arg        input file\n");
33055714Skris		BIO_printf(bio_err," -out arg       output file\n");
33155714Skris		BIO_printf(bio_err," -text          text form of request\n");
33255714Skris		BIO_printf(bio_err," -noout         do not output REQ\n");
33355714Skris		BIO_printf(bio_err," -verify        verify signature on REQ\n");
33455714Skris		BIO_printf(bio_err," -modulus       RSA modulus\n");
33555714Skris		BIO_printf(bio_err," -nodes         don't encrypt the output key\n");
33655714Skris		BIO_printf(bio_err," -key file	use the private key contained in file\n");
33755714Skris		BIO_printf(bio_err," -keyform arg   key file format\n");
33855714Skris		BIO_printf(bio_err," -keyout arg    file to send the key to\n");
33955714Skris		BIO_printf(bio_err," -newkey rsa:bits generate a new RSA key of 'bits' in size\n");
34055714Skris		BIO_printf(bio_err," -newkey dsa:file generate a new DSA key, parameters taken from CA in 'file'\n");
34155714Skris
34255714Skris		BIO_printf(bio_err," -[digest]      Digest to sign with (md5, sha1, md2, mdc2)\n");
34355714Skris		BIO_printf(bio_err," -config file   request template file.\n");
34455714Skris		BIO_printf(bio_err," -new           new request.\n");
34555714Skris		BIO_printf(bio_err," -x509          output a x509 structure instead of a cert. req.\n");
34655714Skris		BIO_printf(bio_err," -days          number of days a x509 generated by -x509 is valid for.\n");
34755714Skris		BIO_printf(bio_err," -asn1-kludge   Output the 'request' in a format that is wrong but some CA's\n");
34855714Skris		BIO_printf(bio_err,"                have been reported as requiring\n");
34955714Skris		BIO_printf(bio_err,"                [ It is now always turned on but can be turned off with -no-asn1-kludge ]\n");
35055714Skris		goto end;
35155714Skris		}
35255714Skris
35355714Skris	ERR_load_crypto_strings();
35455714Skris	X509V3_add_standard_extensions();
35555714Skris
35655714Skris#ifndef MONOLITH
35755714Skris	/* Lets load up our environment a little */
35855714Skris	p=getenv("OPENSSL_CONF");
35955714Skris	if (p == NULL)
36055714Skris		p=getenv("SSLEAY_CONF");
36155714Skris	if (p == NULL)
36255714Skris		{
36355714Skris		strcpy(config_name,X509_get_default_cert_area());
36455714Skris#ifndef VMS
36555714Skris		strcat(config_name,"/");
36655714Skris#endif
36755714Skris		strcat(config_name,OPENSSL_CONF);
36855714Skris		p=config_name;
36955714Skris		}
37055714Skris        default_config_file=p;
37155714Skris	config=CONF_load(config,p,NULL);
37255714Skris#endif
37355714Skris
37455714Skris	if (template != NULL)
37555714Skris		{
37655714Skris		long errline;
37755714Skris
37855714Skris		BIO_printf(bio_err,"Using configuration from %s\n",template);
37955714Skris		req_conf=CONF_load(NULL,template,&errline);
38055714Skris		if (req_conf == NULL)
38155714Skris			{
38255714Skris			BIO_printf(bio_err,"error on line %ld of %s\n",errline,template);
38355714Skris			goto end;
38455714Skris			}
38555714Skris		}
38655714Skris	else
38755714Skris		{
38855714Skris		req_conf=config;
38955714Skris		BIO_printf(bio_err,"Using configuration from %s\n",
39055714Skris			default_config_file);
39155714Skris		if (req_conf == NULL)
39255714Skris			{
39355714Skris			BIO_printf(bio_err,"Unable to load config info\n");
39455714Skris			}
39555714Skris		}
39655714Skris
39755714Skris	if (req_conf != NULL)
39855714Skris		{
39955714Skris		p=CONF_get_string(req_conf,NULL,"oid_file");
40055714Skris		if (p != NULL)
40155714Skris			{
40255714Skris			BIO *oid_bio;
40355714Skris
40455714Skris			oid_bio=BIO_new_file(p,"r");
40555714Skris			if (oid_bio == NULL)
40655714Skris				{
40755714Skris				/*
40855714Skris				BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
40955714Skris				ERR_print_errors(bio_err);
41055714Skris				*/
41155714Skris				}
41255714Skris			else
41355714Skris				{
41455714Skris				OBJ_create_objects(oid_bio);
41555714Skris				BIO_free(oid_bio);
41655714Skris				}
41755714Skris			}
41855714Skris		}
41955714Skris		if(!add_oid_section(req_conf)) goto end;
42055714Skris
42155714Skris	if ((md_alg == NULL) &&
42255714Skris		((p=CONF_get_string(req_conf,SECTION,"default_md")) != NULL))
42355714Skris		{
42455714Skris		if ((md_alg=EVP_get_digestbyname(p)) != NULL)
42555714Skris			digest=md_alg;
42655714Skris		}
42755714Skris
42855714Skris	extensions = CONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
42955714Skris	if(extensions) {
43055714Skris		/* Check syntax of file */
43155714Skris		X509V3_CTX ctx;
43255714Skris		X509V3_set_ctx_test(&ctx);
43355714Skris		X509V3_set_conf_lhash(&ctx, req_conf);
43455714Skris		if(!X509V3_EXT_add_conf(req_conf, &ctx, extensions, NULL)) {
43555714Skris			BIO_printf(bio_err,
43655714Skris			 "Error Loading extension section %s\n", extensions);
43755714Skris			goto end;
43855714Skris		}
43955714Skris	}
44055714Skris
44155714Skris	in=BIO_new(BIO_s_file());
44255714Skris	out=BIO_new(BIO_s_file());
44355714Skris	if ((in == NULL) || (out == NULL))
44455714Skris		goto end;
44555714Skris
44655714Skris	if (keyfile != NULL)
44755714Skris		{
44855714Skris		if (BIO_read_filename(in,keyfile) <= 0)
44955714Skris			{
45055714Skris			perror(keyfile);
45155714Skris			goto end;
45255714Skris			}
45355714Skris
45455714Skris/*		if (keyform == FORMAT_ASN1)
45555714Skris			rsa=d2i_RSAPrivateKey_bio(in,NULL);
45655714Skris		else */
45755714Skris		if (keyform == FORMAT_PEM)
45855714Skris			pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,NULL);
45955714Skris		else
46055714Skris			{
46155714Skris			BIO_printf(bio_err,"bad input format specified for X509 request\n");
46255714Skris			goto end;
46355714Skris			}
46455714Skris
46555714Skris		if (pkey == NULL)
46655714Skris			{
46755714Skris			BIO_printf(bio_err,"unable to load Private key\n");
46855714Skris			goto end;
46955714Skris			}
47055714Skris		}
47155714Skris
47255714Skris	if (newreq && (pkey == NULL))
47355714Skris		{
47455714Skris		char *randfile;
47555714Skris		char buffer[200];
47655714Skris
47755714Skris		if ((randfile=CONF_get_string(req_conf,SECTION,"RANDFILE")) == NULL)
47855714Skris			randfile=RAND_file_name(buffer,200);
47955714Skris#ifdef WINDOWS
48055714Skris		BIO_printf(bio_err,"Loading 'screen' into random state -");
48155714Skris		BIO_flush(bio_err);
48255714Skris		RAND_screen();
48355714Skris		BIO_printf(bio_err," done\n");
48455714Skris#endif
48555714Skris		if ((randfile == NULL) || !RAND_load_file(randfile,1024L*1024L))
48655714Skris			{
48755714Skris			BIO_printf(bio_err,"unable to load 'random state'\n");
48855714Skris			BIO_printf(bio_err,"What this means is that the random number generator has not been seeded\n");
48955714Skris			BIO_printf(bio_err,"with much random data.\n");
49055714Skris			BIO_printf(bio_err,"Consider setting the RANDFILE environment variable to point at a file that\n");
49155714Skris			BIO_printf(bio_err,"'random' data can be kept in.\n");
49255714Skris			}
49355714Skris		if (newkey <= 0)
49455714Skris			{
49555714Skris			newkey=(int)CONF_get_number(req_conf,SECTION,BITS);
49655714Skris			if (newkey <= 0)
49755714Skris				newkey=DEFAULT_KEY_LENGTH;
49855714Skris			}
49955714Skris
50055714Skris		if (newkey < MIN_KEY_LENGTH)
50155714Skris			{
50255714Skris			BIO_printf(bio_err,"private key length is too short,\n");
50355714Skris			BIO_printf(bio_err,"it needs to be at least %d bits, not %d\n",MIN_KEY_LENGTH,newkey);
50455714Skris			goto end;
50555714Skris			}
50655714Skris		BIO_printf(bio_err,"Generating a %d bit %s private key\n",
50755714Skris			newkey,(pkey_type == TYPE_RSA)?"RSA":"DSA");
50855714Skris
50955714Skris		if ((pkey=EVP_PKEY_new()) == NULL) goto end;
51055714Skris
51155714Skris#ifndef NO_RSA
51255714Skris		if (pkey_type == TYPE_RSA)
51355714Skris			{
51455714Skris			if (!EVP_PKEY_assign_RSA(pkey,
51555714Skris				RSA_generate_key(newkey,0x10001,
51655714Skris					req_cb,bio_err)))
51755714Skris				goto end;
51855714Skris			}
51955714Skris		else
52055714Skris#endif
52155714Skris#ifndef NO_DSA
52255714Skris			if (pkey_type == TYPE_DSA)
52355714Skris			{
52455714Skris			if (!DSA_generate_key(dsa_params)) goto end;
52555714Skris			if (!EVP_PKEY_assign_DSA(pkey,dsa_params)) goto end;
52655714Skris			dsa_params=NULL;
52755714Skris			}
52855714Skris#endif
52955714Skris
53055714Skris		if ((randfile == NULL) || (RAND_write_file(randfile) == 0))
53155714Skris			BIO_printf(bio_err,"unable to write 'random state'\n");
53255714Skris
53355714Skris		if (pkey == NULL) goto end;
53455714Skris
53555714Skris		if (keyout == NULL)
53655714Skris			keyout=CONF_get_string(req_conf,SECTION,KEYFILE);
53755714Skris
53855714Skris		if (keyout == NULL)
53955714Skris			{
54055714Skris			BIO_printf(bio_err,"writing new private key to stdout\n");
54155714Skris			BIO_set_fp(out,stdout,BIO_NOCLOSE);
54255714Skris			}
54355714Skris		else
54455714Skris			{
54555714Skris			BIO_printf(bio_err,"writing new private key to '%s'\n",keyout);
54655714Skris			if (BIO_write_filename(out,keyout) <= 0)
54755714Skris				{
54855714Skris				perror(keyout);
54955714Skris				goto end;
55055714Skris				}
55155714Skris			}
55255714Skris
55355714Skris		p=CONF_get_string(req_conf,SECTION,"encrypt_rsa_key");
55455714Skris		if (p == NULL)
55555714Skris			p=CONF_get_string(req_conf,SECTION,"encrypt_key");
55655714Skris		if ((p != NULL) && (strcmp(p,"no") == 0))
55755714Skris			cipher=NULL;
55855714Skris		if (nodes) cipher=NULL;
55955714Skris
56055714Skris		i=0;
56155714Skrisloop:
56255714Skris		if (!PEM_write_bio_PrivateKey(out,pkey,cipher,
56355714Skris			NULL,0,NULL,NULL))
56455714Skris			{
56555714Skris			if ((ERR_GET_REASON(ERR_peek_error()) ==
56655714Skris				PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3))
56755714Skris				{
56855714Skris				ERR_clear_error();
56955714Skris				i++;
57055714Skris				goto loop;
57155714Skris				}
57255714Skris			goto end;
57355714Skris			}
57455714Skris		BIO_printf(bio_err,"-----\n");
57555714Skris		}
57655714Skris
57755714Skris	if (!newreq)
57855714Skris		{
57955714Skris		/* Since we are using a pre-existing certificate
58055714Skris		 * request, the kludge 'format' info should not be
58155714Skris		 * changed. */
58255714Skris		kludge= -1;
58355714Skris		if (infile == NULL)
58455714Skris			BIO_set_fp(in,stdin,BIO_NOCLOSE);
58555714Skris		else
58655714Skris			{
58755714Skris			if (BIO_read_filename(in,infile) <= 0)
58855714Skris				{
58955714Skris				perror(infile);
59055714Skris				goto end;
59155714Skris				}
59255714Skris			}
59355714Skris
59455714Skris		if	(informat == FORMAT_ASN1)
59555714Skris			req=d2i_X509_REQ_bio(in,NULL);
59655714Skris		else if (informat == FORMAT_PEM)
59755714Skris			req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
59855714Skris		else
59955714Skris			{
60055714Skris			BIO_printf(bio_err,"bad input format specified for X509 request\n");
60155714Skris			goto end;
60255714Skris			}
60355714Skris		if (req == NULL)
60455714Skris			{
60555714Skris			BIO_printf(bio_err,"unable to load X509 request\n");
60655714Skris			goto end;
60755714Skris			}
60855714Skris		}
60955714Skris
61055714Skris	if (newreq || x509)
61155714Skris		{
61255714Skris#ifndef NO_DSA
61355714Skris		if (pkey->type == EVP_PKEY_DSA)
61455714Skris			digest=EVP_dss1();
61555714Skris#endif
61655714Skris
61755714Skris		if (pkey == NULL)
61855714Skris			{
61955714Skris			BIO_printf(bio_err,"you need to specify a private key\n");
62055714Skris			goto end;
62155714Skris			}
62255714Skris		if (req == NULL)
62355714Skris			{
62455714Skris			req=X509_REQ_new();
62555714Skris			if (req == NULL)
62655714Skris				{
62755714Skris				goto end;
62855714Skris				}
62955714Skris
63055714Skris			i=make_REQ(req,pkey,!x509);
63155714Skris			if (kludge >= 0)
63255714Skris				req->req_info->req_kludge=kludge;
63355714Skris			if (!i)
63455714Skris				{
63555714Skris				BIO_printf(bio_err,"problems making Certificate Request\n");
63655714Skris				goto end;
63755714Skris				}
63855714Skris			}
63955714Skris		if (x509)
64055714Skris			{
64155714Skris			EVP_PKEY *tmppkey;
64255714Skris			X509V3_CTX ext_ctx;
64355714Skris			if ((x509ss=X509_new()) == NULL) goto end;
64455714Skris
64555714Skris			/* Set version to V3 */
64655714Skris			if(!X509_set_version(x509ss, 2)) goto end;
64755714Skris			ASN1_INTEGER_set(X509_get_serialNumber(x509ss),0L);
64855714Skris
64955714Skris			X509_set_issuer_name(x509ss,
65055714Skris				X509_REQ_get_subject_name(req));
65155714Skris			X509_gmtime_adj(X509_get_notBefore(x509ss),0);
65255714Skris			X509_gmtime_adj(X509_get_notAfter(x509ss),
65355714Skris				(long)60*60*24*days);
65455714Skris			X509_set_subject_name(x509ss,
65555714Skris				X509_REQ_get_subject_name(req));
65655714Skris			tmppkey = X509_REQ_get_pubkey(req);
65755714Skris			X509_set_pubkey(x509ss,tmppkey);
65855714Skris			EVP_PKEY_free(tmppkey);
65955714Skris
66055714Skris			/* Set up V3 context struct */
66155714Skris
66255714Skris			X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0);
66355714Skris			X509V3_set_conf_lhash(&ext_ctx, req_conf);
66455714Skris
66555714Skris			/* Add extensions */
66655714Skris			if(extensions && !X509V3_EXT_add_conf(req_conf,
66755714Skris				 	&ext_ctx, extensions, x509ss))
66855714Skris			    {
66955714Skris			    BIO_printf(bio_err,
67055714Skris				       "Error Loading extension section %s\n",
67155714Skris				       extensions);
67255714Skris			    goto end;
67355714Skris			    }
67455714Skris
67555714Skris			if (!(i=X509_sign(x509ss,pkey,digest)))
67655714Skris				goto end;
67755714Skris			}
67855714Skris		else
67955714Skris			{
68055714Skris			if (!(i=X509_REQ_sign(req,pkey,digest)))
68155714Skris				goto end;
68255714Skris			}
68355714Skris		}
68455714Skris
68555714Skris	if (verify && !x509)
68655714Skris		{
68755714Skris		int tmp=0;
68855714Skris
68955714Skris		if (pkey == NULL)
69055714Skris			{
69155714Skris			pkey=X509_REQ_get_pubkey(req);
69255714Skris			tmp=1;
69355714Skris			if (pkey == NULL) goto end;
69455714Skris			}
69555714Skris
69655714Skris		i=X509_REQ_verify(req,pkey);
69755714Skris		if (tmp) {
69855714Skris			EVP_PKEY_free(pkey);
69955714Skris			pkey=NULL;
70055714Skris		}
70155714Skris
70255714Skris		if (i < 0)
70355714Skris			{
70455714Skris			goto end;
70555714Skris			}
70655714Skris		else if (i == 0)
70755714Skris			{
70855714Skris			BIO_printf(bio_err,"verify failure\n");
70955714Skris			}
71055714Skris		else /* if (i > 0) */
71155714Skris			BIO_printf(bio_err,"verify OK\n");
71255714Skris		}
71355714Skris
71455714Skris	if (noout && !text && !modulus)
71555714Skris		{
71655714Skris		ex=0;
71755714Skris		goto end;
71855714Skris		}
71955714Skris
72055714Skris	if (outfile == NULL)
72155714Skris		BIO_set_fp(out,stdout,BIO_NOCLOSE);
72255714Skris	else
72355714Skris		{
72455714Skris		if ((keyout != NULL) && (strcmp(outfile,keyout) == 0))
72555714Skris			i=(int)BIO_append_filename(out,outfile);
72655714Skris		else
72755714Skris			i=(int)BIO_write_filename(out,outfile);
72855714Skris		if (!i)
72955714Skris			{
73055714Skris			perror(outfile);
73155714Skris			goto end;
73255714Skris			}
73355714Skris		}
73455714Skris
73555714Skris	if (text)
73655714Skris		{
73755714Skris		if (x509)
73855714Skris			X509_print(out,x509ss);
73955714Skris		else
74055714Skris			X509_REQ_print(out,req);
74155714Skris		}
74255714Skris
74355714Skris	if (modulus)
74455714Skris		{
74555714Skris		EVP_PKEY *pubkey;
74655714Skris
74755714Skris		if (x509)
74855714Skris			pubkey=X509_get_pubkey(x509ss);
74955714Skris		else
75055714Skris			pubkey=X509_REQ_get_pubkey(req);
75155714Skris		if (pubkey == NULL)
75255714Skris			{
75355714Skris			fprintf(stdout,"Modulus=unavailable\n");
75455714Skris			goto end;
75555714Skris			}
75655714Skris		fprintf(stdout,"Modulus=");
75755714Skris#ifndef NO_RSA
75855714Skris		if (pubkey->type == EVP_PKEY_RSA)
75955714Skris			BN_print(out,pubkey->pkey.rsa->n);
76055714Skris		else
76155714Skris#endif
76255714Skris			fprintf(stdout,"Wrong Algorithm type");
76355714Skris		fprintf(stdout,"\n");
76455714Skris		}
76555714Skris
76655714Skris	if (!noout && !x509)
76755714Skris		{
76855714Skris		if 	(outformat == FORMAT_ASN1)
76955714Skris			i=i2d_X509_REQ_bio(out,req);
77055714Skris		else if (outformat == FORMAT_PEM)
77155714Skris			i=PEM_write_bio_X509_REQ(out,req);
77255714Skris		else	{
77355714Skris			BIO_printf(bio_err,"bad output format specified for outfile\n");
77455714Skris			goto end;
77555714Skris			}
77655714Skris		if (!i)
77755714Skris			{
77855714Skris			BIO_printf(bio_err,"unable to write X509 request\n");
77955714Skris			goto end;
78055714Skris			}
78155714Skris		}
78255714Skris	if (!noout && x509 && (x509ss != NULL))
78355714Skris		{
78455714Skris		if 	(outformat == FORMAT_ASN1)
78555714Skris			i=i2d_X509_bio(out,x509ss);
78655714Skris		else if (outformat == FORMAT_PEM)
78755714Skris			i=PEM_write_bio_X509(out,x509ss);
78855714Skris		else	{
78955714Skris			BIO_printf(bio_err,"bad output format specified for outfile\n");
79055714Skris			goto end;
79155714Skris			}
79255714Skris		if (!i)
79355714Skris			{
79455714Skris			BIO_printf(bio_err,"unable to write X509 certificate\n");
79555714Skris			goto end;
79655714Skris			}
79755714Skris		}
79855714Skris	ex=0;
79955714Skrisend:
80055714Skris	if (ex)
80155714Skris		{
80255714Skris		ERR_print_errors(bio_err);
80355714Skris		}
80455714Skris	if ((req_conf != NULL) && (req_conf != config)) CONF_free(req_conf);
80555714Skris	BIO_free(in);
80655714Skris	BIO_free(out);
80755714Skris	EVP_PKEY_free(pkey);
80855714Skris	X509_REQ_free(req);
80955714Skris	X509_free(x509ss);
81055714Skris	X509V3_EXT_cleanup();
81155714Skris	OBJ_cleanup();
81255714Skris#ifndef NO_DSA
81355714Skris	if (dsa_params != NULL) DSA_free(dsa_params);
81455714Skris#endif
81555714Skris	EXIT(ex);
81655714Skris	}
81755714Skris
81855714Skrisstatic int make_REQ(X509_REQ *req, EVP_PKEY *pkey, int attribs)
81955714Skris	{
82055714Skris	int ret=0,i;
82155714Skris	char *p,*q;
82255714Skris	X509_REQ_INFO *ri;
82355714Skris	char buf[100];
82455714Skris	int nid,min,max;
82555714Skris	char *type,*def,*tmp,*value,*tmp_attr;
82655714Skris	STACK_OF(CONF_VALUE) *sk, *attr=NULL;
82755714Skris	CONF_VALUE *v;
82855714Skris
82955714Skris	tmp=CONF_get_string(req_conf,SECTION,DISTINGUISHED_NAME);
83055714Skris	if (tmp == NULL)
83155714Skris		{
83255714Skris		BIO_printf(bio_err,"unable to find '%s' in config\n",
83355714Skris			DISTINGUISHED_NAME);
83455714Skris		goto err;
83555714Skris		}
83655714Skris	sk=CONF_get_section(req_conf,tmp);
83755714Skris	if (sk == NULL)
83855714Skris		{
83955714Skris		BIO_printf(bio_err,"unable to get '%s' section\n",tmp);
84055714Skris		goto err;
84155714Skris		}
84255714Skris
84355714Skris	tmp_attr=CONF_get_string(req_conf,SECTION,ATTRIBUTES);
84455714Skris	if (tmp_attr == NULL)
84555714Skris		attr=NULL;
84655714Skris	else
84755714Skris		{
84855714Skris		attr=CONF_get_section(req_conf,tmp_attr);
84955714Skris		if (attr == NULL)
85055714Skris			{
85155714Skris			BIO_printf(bio_err,"unable to get '%s' section\n",tmp_attr);
85255714Skris			goto err;
85355714Skris			}
85455714Skris		}
85555714Skris
85655714Skris	ri=req->req_info;
85755714Skris
85855714Skris	BIO_printf(bio_err,"You are about to be asked to enter information that will be incorporated\n");
85955714Skris	BIO_printf(bio_err,"into your certificate request.\n");
86055714Skris	BIO_printf(bio_err,"What you are about to enter is what is called a Distinguished Name or a DN.\n");
86155714Skris	BIO_printf(bio_err,"There are quite a few fields but you can leave some blank\n");
86255714Skris	BIO_printf(bio_err,"For some fields there will be a default value,\n");
86355714Skris	BIO_printf(bio_err,"If you enter '.', the field will be left blank.\n");
86455714Skris	BIO_printf(bio_err,"-----\n");
86555714Skris
86655714Skris	/* setup version number */
86755714Skris	if (!ASN1_INTEGER_set(ri->version,0L)) goto err; /* version 1 */
86855714Skris
86955714Skris	if (sk_CONF_VALUE_num(sk))
87055714Skris		{
87155714Skris		i= -1;
87255714Skrisstart:		for (;;)
87355714Skris			{
87455714Skris			i++;
87555714Skris			if (sk_CONF_VALUE_num(sk) <= i) break;
87655714Skris
87755714Skris			v=sk_CONF_VALUE_value(sk,i);
87855714Skris			p=q=NULL;
87955714Skris			type=v->name;
88055714Skris			if(!check_end(type,"_min") || !check_end(type,"_max") ||
88155714Skris				!check_end(type,"_default") ||
88255714Skris					 !check_end(type,"_value")) continue;
88355714Skris			/* Skip past any leading X. X: X, etc to allow for
88455714Skris			 * multiple instances
88555714Skris			 */
88655714Skris			for(p = v->name; *p ; p++)
88755714Skris				if ((*p == ':') || (*p == ',') ||
88855714Skris							 (*p == '.')) {
88955714Skris					p++;
89055714Skris					if(*p) type = p;
89155714Skris					break;
89255714Skris				}
89355714Skris			/* If OBJ not recognised ignore it */
89455714Skris			if ((nid=OBJ_txt2nid(type)) == NID_undef) goto start;
89555714Skris			sprintf(buf,"%s_default",v->name);
89655714Skris			if ((def=CONF_get_string(req_conf,tmp,buf)) == NULL)
89755714Skris				def="";
89855714Skris
89955714Skris			sprintf(buf,"%s_value",v->name);
90055714Skris			if ((value=CONF_get_string(req_conf,tmp,buf)) == NULL)
90155714Skris				value=NULL;
90255714Skris
90355714Skris			sprintf(buf,"%s_min",v->name);
90455714Skris			min=(int)CONF_get_number(req_conf,tmp,buf);
90555714Skris
90655714Skris			sprintf(buf,"%s_max",v->name);
90755714Skris			max=(int)CONF_get_number(req_conf,tmp,buf);
90855714Skris
90955714Skris			if (!add_DN_object(ri->subject,v->value,def,value,nid,
91055714Skris				min,max))
91155714Skris				goto err;
91255714Skris			}
91355714Skris		if (sk_X509_NAME_ENTRY_num(ri->subject->entries) == 0)
91455714Skris			{
91555714Skris			BIO_printf(bio_err,"error, no objects specified in config file\n");
91655714Skris			goto err;
91755714Skris			}
91855714Skris
91955714Skris		if (attribs)
92055714Skris			{
92155714Skris			if ((attr != NULL) && (sk_CONF_VALUE_num(attr) > 0))
92255714Skris				{
92355714Skris				BIO_printf(bio_err,"\nPlease enter the following 'extra' attributes\n");
92455714Skris				BIO_printf(bio_err,"to be sent with your certificate request\n");
92555714Skris				}
92655714Skris
92755714Skris			i= -1;
92855714Skrisstart2:			for (;;)
92955714Skris				{
93055714Skris				i++;
93155714Skris				if ((attr == NULL) ||
93255714Skris					    (sk_CONF_VALUE_num(attr) <= i))
93355714Skris					break;
93455714Skris
93555714Skris				v=sk_CONF_VALUE_value(attr,i);
93655714Skris				type=v->name;
93755714Skris				if ((nid=OBJ_txt2nid(type)) == NID_undef)
93855714Skris					goto start2;
93955714Skris
94055714Skris				sprintf(buf,"%s_default",type);
94155714Skris				if ((def=CONF_get_string(req_conf,tmp_attr,buf))
94255714Skris					== NULL)
94355714Skris					def="";
94455714Skris
94555714Skris				sprintf(buf,"%s_value",type);
94655714Skris				if ((value=CONF_get_string(req_conf,tmp_attr,buf))
94755714Skris					== NULL)
94855714Skris					value=NULL;
94955714Skris
95055714Skris				sprintf(buf,"%s_min",type);
95155714Skris				min=(int)CONF_get_number(req_conf,tmp_attr,buf);
95255714Skris
95355714Skris				sprintf(buf,"%s_max",type);
95455714Skris				max=(int)CONF_get_number(req_conf,tmp_attr,buf);
95555714Skris
95655714Skris				if (!add_attribute_object(ri->attributes,
95755714Skris					v->value,def,value,nid,min,max))
95855714Skris					goto err;
95955714Skris				}
96055714Skris			}
96155714Skris		}
96255714Skris	else
96355714Skris		{
96455714Skris		BIO_printf(bio_err,"No template, please set one up.\n");
96555714Skris		goto err;
96655714Skris		}
96755714Skris
96855714Skris	X509_REQ_set_pubkey(req,pkey);
96955714Skris
97055714Skris	ret=1;
97155714Skriserr:
97255714Skris	return(ret);
97355714Skris	}
97455714Skris
97555714Skrisstatic int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
97655714Skris	     int nid, int min, int max)
97755714Skris	{
97855714Skris	int i,j,ret=0;
97955714Skris	X509_NAME_ENTRY *ne=NULL;
98055714Skris	MS_STATIC char buf[1024];
98155714Skris
98255714Skris	BIO_printf(bio_err,"%s [%s]:",text,def);
98355714Skris	(void)BIO_flush(bio_err);
98455714Skris	if (value != NULL)
98555714Skris		{
98655714Skris		strcpy(buf,value);
98755714Skris		strcat(buf,"\n");
98855714Skris		BIO_printf(bio_err,"%s\n",value);
98955714Skris		}
99055714Skris	else
99155714Skris		{
99255714Skris		buf[0]='\0';
99355714Skris		fgets(buf,1024,stdin);
99455714Skris		}
99555714Skris
99655714Skris	if (buf[0] == '\0') return(0);
99755714Skris	else if (buf[0] == '\n')
99855714Skris		{
99955714Skris		if ((def == NULL) || (def[0] == '\0'))
100055714Skris			return(1);
100155714Skris		strcpy(buf,def);
100255714Skris		strcat(buf,"\n");
100355714Skris		}
100455714Skris	else if ((buf[0] == '.') && (buf[1] == '\n')) return(1);
100555714Skris
100655714Skris	i=strlen(buf);
100755714Skris	if (buf[i-1] != '\n')
100855714Skris		{
100955714Skris		BIO_printf(bio_err,"weird input :-(\n");
101055714Skris		return(0);
101155714Skris		}
101255714Skris	buf[--i]='\0';
101355714Skris
101455714Skris	j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
101555714Skris	if (req_fix_data(nid,&j,i,min,max) == 0)
101655714Skris		goto err;
101755714Skris#ifdef CHARSET_EBCDIC
101855714Skris	ebcdic2ascii(buf, buf, i);
101955714Skris#endif
102055714Skris	if ((ne=X509_NAME_ENTRY_create_by_NID(NULL,nid,j,(unsigned char *)buf,
102155714Skris		strlen(buf)))
102255714Skris		== NULL) goto err;
102355714Skris	if (!X509_NAME_add_entry(n,ne,X509_NAME_entry_count(n),0))
102455714Skris		goto err;
102555714Skris
102655714Skris	ret=1;
102755714Skriserr:
102855714Skris	if (ne != NULL) X509_NAME_ENTRY_free(ne);
102955714Skris	return(ret);
103055714Skris	}
103155714Skris
103255714Skrisstatic int add_attribute_object(STACK_OF(X509_ATTRIBUTE) *n, char *text,
103355714Skris				char *def, char *value, int nid, int min,
103455714Skris				int max)
103555714Skris	{
103655714Skris	int i,z;
103755714Skris	X509_ATTRIBUTE *xa=NULL;
103855714Skris	static char buf[1024];
103955714Skris	ASN1_BIT_STRING *bs=NULL;
104055714Skris	ASN1_TYPE *at=NULL;
104155714Skris
104255714Skrisstart:
104355714Skris	BIO_printf(bio_err,"%s [%s]:",text,def);
104455714Skris	(void)BIO_flush(bio_err);
104555714Skris	if (value != NULL)
104655714Skris		{
104755714Skris		strcpy(buf,value);
104855714Skris		strcat(buf,"\n");
104955714Skris		BIO_printf(bio_err,"%s\n",value);
105055714Skris		}
105155714Skris	else
105255714Skris		{
105355714Skris		buf[0]='\0';
105455714Skris		fgets(buf,1024,stdin);
105555714Skris		}
105655714Skris
105755714Skris	if (buf[0] == '\0') return(0);
105855714Skris	else if (buf[0] == '\n')
105955714Skris		{
106055714Skris		if ((def == NULL) || (def[0] == '\0'))
106155714Skris			return(1);
106255714Skris		strcpy(buf,def);
106355714Skris		strcat(buf,"\n");
106455714Skris		}
106555714Skris	else if ((buf[0] == '.') && (buf[1] == '\n')) return(1);
106655714Skris
106755714Skris	i=strlen(buf);
106855714Skris	if (buf[i-1] != '\n')
106955714Skris		{
107055714Skris		BIO_printf(bio_err,"weird input :-(\n");
107155714Skris		return(0);
107255714Skris		}
107355714Skris	buf[--i]='\0';
107455714Skris
107555714Skris	/* add object plus value */
107655714Skris	if ((xa=X509_ATTRIBUTE_new()) == NULL)
107755714Skris		goto err;
107855714Skris	if ((xa->value.set=sk_ASN1_TYPE_new_null()) == NULL)
107955714Skris		goto err;
108055714Skris	xa->set=1;
108155714Skris
108255714Skris	if (xa->object != NULL) ASN1_OBJECT_free(xa->object);
108355714Skris	xa->object=OBJ_nid2obj(nid);
108455714Skris
108555714Skris	if ((bs=ASN1_BIT_STRING_new()) == NULL) goto err;
108655714Skris
108755714Skris	bs->type=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
108855714Skris
108955714Skris	z=req_fix_data(nid,&bs->type,i,min,max);
109055714Skris	if (z == 0)
109155714Skris		{
109255714Skris		if (value == NULL)
109355714Skris			goto start;
109455714Skris		else	goto err;
109555714Skris		}
109655714Skris
109755714Skris	if (!ASN1_STRING_set(bs,(unsigned char *)buf,i+1))
109855714Skris		{ BIO_printf(bio_err,"Malloc failure\n"); goto err; }
109955714Skris
110055714Skris	if ((at=ASN1_TYPE_new()) == NULL)
110155714Skris		{ BIO_printf(bio_err,"Malloc failure\n"); goto err; }
110255714Skris
110355714Skris	ASN1_TYPE_set(at,bs->type,(char *)bs);
110455714Skris	sk_ASN1_TYPE_push(xa->value.set,at);
110555714Skris	bs=NULL;
110655714Skris	at=NULL;
110755714Skris	/* only one item per attribute */
110855714Skris
110955714Skris	if (!sk_X509_ATTRIBUTE_push(n,xa)) goto err;
111055714Skris	return(1);
111155714Skriserr:
111255714Skris	if (xa != NULL) X509_ATTRIBUTE_free(xa);
111355714Skris	if (at != NULL) ASN1_TYPE_free(at);
111455714Skris	if (bs != NULL) ASN1_BIT_STRING_free(bs);
111555714Skris	return(0);
111655714Skris	}
111755714Skris
111855714Skrisstatic void MS_CALLBACK req_cb(int p, int n, void *arg)
111955714Skris	{
112055714Skris	char c='*';
112155714Skris
112255714Skris	if (p == 0) c='.';
112355714Skris	if (p == 1) c='+';
112455714Skris	if (p == 2) c='*';
112555714Skris	if (p == 3) c='\n';
112655714Skris	BIO_write((BIO *)arg,&c,1);
112755714Skris	(void)BIO_flush((BIO *)arg);
112855714Skris#ifdef LINT
112955714Skris	p=n;
113055714Skris#endif
113155714Skris	}
113255714Skris
113355714Skrisstatic int req_fix_data(int nid, int *type, int len, int min, int max)
113455714Skris	{
113555714Skris	if (nid == NID_pkcs9_emailAddress)
113655714Skris		*type=V_ASN1_IA5STRING;
113755714Skris	if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
113855714Skris		*type=V_ASN1_T61STRING;
113955714Skris	if ((nid == NID_pkcs9_challengePassword) &&
114055714Skris		(*type == V_ASN1_IA5STRING))
114155714Skris		*type=V_ASN1_T61STRING;
114255714Skris
114355714Skris	if ((nid == NID_pkcs9_unstructuredName) &&
114455714Skris		(*type == V_ASN1_T61STRING))
114555714Skris		{
114655714Skris		BIO_printf(bio_err,"invalid characters in string, please re-enter the string\n");
114755714Skris		return(0);
114855714Skris		}
114955714Skris	if (nid == NID_pkcs9_unstructuredName)
115055714Skris		*type=V_ASN1_IA5STRING;
115155714Skris
115255714Skris	if (len < min)
115355714Skris		{
115455714Skris		BIO_printf(bio_err,"string is too short, it needs to be at least %d bytes long\n",min);
115555714Skris		return(0);
115655714Skris		}
115755714Skris	if ((max != 0) && (len > max))
115855714Skris		{
115955714Skris		BIO_printf(bio_err,"string is too long, it needs to be less than  %d bytes long\n",max);
116055714Skris		return(0);
116155714Skris		}
116255714Skris	return(1);
116355714Skris	}
116455714Skris
116555714Skris/* Check if the end of a string matches 'end' */
116655714Skrisstatic int check_end(char *str, char *end)
116755714Skris{
116855714Skris	int elen, slen;
116955714Skris	char *tmp;
117055714Skris	elen = strlen(end);
117155714Skris	slen = strlen(str);
117255714Skris	if(elen > slen) return 1;
117355714Skris	tmp = str + slen - elen;
117455714Skris	return strcmp(tmp, end);
117555714Skris}
117655714Skris
117755714Skrisstatic int add_oid_section(LHASH *conf)
117855714Skris{
117955714Skris	char *p;
118055714Skris	STACK_OF(CONF_VALUE) *sktmp;
118155714Skris	CONF_VALUE *cnf;
118255714Skris	int i;
118355714Skris	if(!(p=CONF_get_string(conf,NULL,"oid_section"))) return 1;
118455714Skris	if(!(sktmp = CONF_get_section(conf, p))) {
118555714Skris		BIO_printf(bio_err, "problem loading oid section %s\n", p);
118655714Skris		return 0;
118755714Skris	}
118855714Skris	for(i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
118955714Skris		cnf = sk_CONF_VALUE_value(sktmp, i);
119055714Skris		if(OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
119155714Skris			BIO_printf(bio_err, "problem creating object %s=%s\n",
119255714Skris							 cnf->name, cnf->value);
119355714Skris			return 0;
119455714Skris		}
119555714Skris	}
119655714Skris	return 1;
119755714Skris}
1198