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.
8296465Sdelphij *
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).
15296465Sdelphij *
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.
22296465Sdelphij *
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 :-).
37296465Sdelphij * 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)"
40296465Sdelphij *
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.
52296465Sdelphij *
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
59296465Sdelphij/*
60296465Sdelphij * Until the key-gen callbacks are modified to use newer prototypes, we allow
61296465Sdelphij * deprecated functions for openssl-internal code
62296465Sdelphij */
63160814Ssimon#ifdef OPENSSL_NO_DEPRECATED
64296465Sdelphij# undef OPENSSL_NO_DEPRECATED
65160814Ssimon#endif
66160814Ssimon
6755714Skris#include <stdio.h>
6855714Skris#include <stdlib.h>
6955714Skris#include <time.h>
7055714Skris#include <string.h>
71109998Smarkm#ifdef OPENSSL_NO_STDIO
72296465Sdelphij# define APPS_WIN16
7355714Skris#endif
7455714Skris#include "apps.h"
7555714Skris#include <openssl/bio.h>
7655714Skris#include <openssl/evp.h>
7755714Skris#include <openssl/conf.h>
7855714Skris#include <openssl/err.h>
7955714Skris#include <openssl/asn1.h>
8055714Skris#include <openssl/x509.h>
8155714Skris#include <openssl/x509v3.h>
8255714Skris#include <openssl/objects.h>
8355714Skris#include <openssl/pem.h>
84160814Ssimon#include <openssl/bn.h>
85160814Ssimon#ifndef OPENSSL_NO_RSA
86296465Sdelphij# include <openssl/rsa.h>
87160814Ssimon#endif
88160814Ssimon#ifndef OPENSSL_NO_DSA
89296465Sdelphij# include <openssl/dsa.h>
90160814Ssimon#endif
9155714Skris
92296465Sdelphij#define SECTION         "req"
9355714Skris
94296465Sdelphij#define BITS            "default_bits"
95296465Sdelphij#define KEYFILE         "default_keyfile"
96296465Sdelphij#define PROMPT          "prompt"
97296465Sdelphij#define DISTINGUISHED_NAME      "distinguished_name"
98296465Sdelphij#define ATTRIBUTES      "attributes"
99296465Sdelphij#define V3_EXTENSIONS   "x509_extensions"
100296465Sdelphij#define REQ_EXTENSIONS  "req_extensions"
101296465Sdelphij#define STRING_MASK     "string_mask"
102296465Sdelphij#define UTF8_IN         "utf8"
10355714Skris
104296465Sdelphij#define DEFAULT_KEY_LENGTH      512
105296465Sdelphij#define MIN_KEY_LENGTH          384
10655714Skris
10755714Skris#undef PROG
108296465Sdelphij#define PROG    req_main
10955714Skris
110296465Sdelphij/*-
111296465Sdelphij * -inform arg  - input format - default PEM (DER or PEM)
11255714Skris * -outform arg - output format - default PEM
113296465Sdelphij * -in arg      - input file - default stdin
114296465Sdelphij * -out arg     - output file - default stdout
115296465Sdelphij * -verify      - check request signature
116296465Sdelphij * -noout       - don't print stuff out.
117296465Sdelphij * -text        - print out human readable text.
118296465Sdelphij * -nodes       - no des encryption
119296465Sdelphij * -config file - Load configuration file.
120296465Sdelphij * -key file    - make a request using key in file (or use it for verification).
121296465Sdelphij * -keyform arg - key file format.
12268651Skris * -rand file(s) - load the file(s) into the PRNG.
123296465Sdelphij * -newkey      - make a key and a request.
124296465Sdelphij * -modulus     - print RSA modulus.
125296465Sdelphij * -pubkey      - output Public Key.
126296465Sdelphij * -x509        - output a self signed X509 structure instead.
127296465Sdelphij * -asn1-kludge - output new certificate request in a format that some CA's
128296465Sdelphij *                require.  This format is wrong
12955714Skris */
13055714Skris
131296465Sdelphijstatic int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *dn, int mutlirdn,
132296465Sdelphij                    int attribs, unsigned long chtype);
133160814Ssimonstatic int build_subject(X509_REQ *req, char *subj, unsigned long chtype,
134296465Sdelphij                         int multirdn);
13559191Skrisstatic int prompt_info(X509_REQ *req,
136296465Sdelphij                       STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
137296465Sdelphij                       STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect,
138296465Sdelphij                       int attribs, unsigned long chtype);
13959191Skrisstatic int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *sk,
140296465Sdelphij                     STACK_OF(CONF_VALUE) *attr, int attribs,
141296465Sdelphij                     unsigned long chtype);
142160814Ssimonstatic int add_attribute_object(X509_REQ *req, char *text, const char *def,
143296465Sdelphij                                char *value, int nid, int n_min, int n_max,
144296465Sdelphij                                unsigned long chtype);
145296465Sdelphijstatic int add_DN_object(X509_NAME *n, char *text, const char *def,
146296465Sdelphij                         char *value, int nid, int n_min, int n_max,
147296465Sdelphij                         unsigned long chtype, int mval);
148109998Smarkm#ifndef OPENSSL_NO_RSA
149160814Ssimonstatic int MS_CALLBACK req_cb(int p, int n, BN_GENCB *cb);
15059191Skris#endif
151296465Sdelphijstatic int req_check_len(int len, int n_min, int n_max);
152160814Ssimonstatic int check_end(const char *str, const char *end);
15355714Skris#ifndef MONOLITH
154296465Sdelphijstatic char *default_config_file = NULL;
15555714Skris#endif
156296465Sdelphijstatic CONF *req_conf = NULL;
157296465Sdelphijstatic int batch = 0;
15855714Skris
159296465Sdelphij#define TYPE_RSA        1
160296465Sdelphij#define TYPE_DSA        2
161296465Sdelphij#define TYPE_DH         3
162296465Sdelphij#define TYPE_EC         4
16355714Skris
16459191Skrisint MAIN(int, char **);
16559191Skris
16655714Skrisint MAIN(int argc, char **argv)
167296465Sdelphij{
168296465Sdelphij    ENGINE *e = NULL;
169109998Smarkm#ifndef OPENSSL_NO_DSA
170296465Sdelphij    DSA *dsa_params = NULL;
17155714Skris#endif
172160814Ssimon#ifndef OPENSSL_NO_ECDSA
173296465Sdelphij    EC_KEY *ec_params = NULL;
174160814Ssimon#endif
175296465Sdelphij    unsigned long nmflag = 0, reqflag = 0;
176296465Sdelphij    int ex = 1, x509 = 0, days = 30;
177296465Sdelphij    X509 *x509ss = NULL;
178296465Sdelphij    X509_REQ *req = NULL;
179296465Sdelphij    EVP_PKEY *pkey = NULL;
180296465Sdelphij    int i = 0, badops = 0, newreq = 0, verbose = 0, pkey_type = TYPE_RSA;
181296465Sdelphij    long newkey = -1;
182296465Sdelphij    BIO *in = NULL, *out = NULL;
183296465Sdelphij    int informat, outformat, verify = 0, noout = 0, text = 0, keyform =
184296465Sdelphij        FORMAT_PEM;
185296465Sdelphij    int nodes = 0, kludge = 0, newhdr = 0, subject = 0, pubkey = 0;
186296465Sdelphij    char *infile, *outfile, *prog, *keyfile = NULL, *template =
187296465Sdelphij        NULL, *keyout = NULL;
188111147Snectar#ifndef OPENSSL_NO_ENGINE
189296465Sdelphij    char *engine = NULL;
190111147Snectar#endif
191296465Sdelphij    char *extensions = NULL;
192296465Sdelphij    char *req_exts = NULL;
193296465Sdelphij    const EVP_CIPHER *cipher = NULL;
194296465Sdelphij    ASN1_INTEGER *serial = NULL;
195296465Sdelphij    int modulus = 0;
196296465Sdelphij    char *inrand = NULL;
197296465Sdelphij    char *passargin = NULL, *passargout = NULL;
198296465Sdelphij    char *passin = NULL, *passout = NULL;
199296465Sdelphij    char *p;
200296465Sdelphij    char *subj = NULL;
201296465Sdelphij    int multirdn = 0;
202296465Sdelphij    const EVP_MD *md_alg = NULL, *digest = EVP_sha1();
203296465Sdelphij    unsigned long chtype = MBSTRING_ASC;
20455714Skris#ifndef MONOLITH
205296465Sdelphij    char *to_free;
206296465Sdelphij    long errline;
20755714Skris#endif
20855714Skris
209296465Sdelphij    req_conf = NULL;
210109998Smarkm#ifndef OPENSSL_NO_DES
211296465Sdelphij    cipher = EVP_des_ede3_cbc();
21255714Skris#endif
213296465Sdelphij    apps_startup();
21455714Skris
215296465Sdelphij    if (bio_err == NULL)
216296465Sdelphij        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
217296465Sdelphij            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
21855714Skris
219296465Sdelphij    infile = NULL;
220296465Sdelphij    outfile = NULL;
221296465Sdelphij    informat = FORMAT_PEM;
222296465Sdelphij    outformat = FORMAT_PEM;
22355714Skris
224296465Sdelphij    prog = argv[0];
225296465Sdelphij    argc--;
226296465Sdelphij    argv++;
227296465Sdelphij    while (argc >= 1) {
228296465Sdelphij        if (strcmp(*argv, "-inform") == 0) {
229296465Sdelphij            if (--argc < 1)
230296465Sdelphij                goto bad;
231296465Sdelphij            informat = str2fmt(*(++argv));
232296465Sdelphij        } else if (strcmp(*argv, "-outform") == 0) {
233296465Sdelphij            if (--argc < 1)
234296465Sdelphij                goto bad;
235296465Sdelphij            outformat = str2fmt(*(++argv));
236296465Sdelphij        }
237111147Snectar#ifndef OPENSSL_NO_ENGINE
238296465Sdelphij        else if (strcmp(*argv, "-engine") == 0) {
239296465Sdelphij            if (--argc < 1)
240296465Sdelphij                goto bad;
241296465Sdelphij            engine = *(++argv);
242296465Sdelphij        }
243111147Snectar#endif
244296465Sdelphij        else if (strcmp(*argv, "-key") == 0) {
245296465Sdelphij            if (--argc < 1)
246296465Sdelphij                goto bad;
247296465Sdelphij            keyfile = *(++argv);
248296465Sdelphij        } else if (strcmp(*argv, "-pubkey") == 0) {
249296465Sdelphij            pubkey = 1;
250296465Sdelphij        } else if (strcmp(*argv, "-new") == 0) {
251296465Sdelphij            newreq = 1;
252296465Sdelphij        } else if (strcmp(*argv, "-config") == 0) {
253296465Sdelphij            if (--argc < 1)
254296465Sdelphij                goto bad;
255296465Sdelphij            template = *(++argv);
256296465Sdelphij        } else if (strcmp(*argv, "-keyform") == 0) {
257296465Sdelphij            if (--argc < 1)
258296465Sdelphij                goto bad;
259296465Sdelphij            keyform = str2fmt(*(++argv));
260296465Sdelphij        } else if (strcmp(*argv, "-in") == 0) {
261296465Sdelphij            if (--argc < 1)
262296465Sdelphij                goto bad;
263296465Sdelphij            infile = *(++argv);
264296465Sdelphij        } else if (strcmp(*argv, "-out") == 0) {
265296465Sdelphij            if (--argc < 1)
266296465Sdelphij                goto bad;
267296465Sdelphij            outfile = *(++argv);
268296465Sdelphij        } else if (strcmp(*argv, "-keyout") == 0) {
269296465Sdelphij            if (--argc < 1)
270296465Sdelphij                goto bad;
271296465Sdelphij            keyout = *(++argv);
272296465Sdelphij        } else if (strcmp(*argv, "-passin") == 0) {
273296465Sdelphij            if (--argc < 1)
274296465Sdelphij                goto bad;
275296465Sdelphij            passargin = *(++argv);
276296465Sdelphij        } else if (strcmp(*argv, "-passout") == 0) {
277296465Sdelphij            if (--argc < 1)
278296465Sdelphij                goto bad;
279296465Sdelphij            passargout = *(++argv);
280296465Sdelphij        } else if (strcmp(*argv, "-rand") == 0) {
281296465Sdelphij            if (--argc < 1)
282296465Sdelphij                goto bad;
283296465Sdelphij            inrand = *(++argv);
284296465Sdelphij        } else if (strcmp(*argv, "-newkey") == 0) {
285296465Sdelphij            int is_numeric;
28655714Skris
287296465Sdelphij            if (--argc < 1)
288296465Sdelphij                goto bad;
289296465Sdelphij            p = *(++argv);
290296465Sdelphij            is_numeric = p[0] >= '0' && p[0] <= '9';
291296465Sdelphij            if (strncmp("rsa:", p, 4) == 0 || is_numeric) {
292296465Sdelphij                pkey_type = TYPE_RSA;
293296465Sdelphij                if (!is_numeric)
294296465Sdelphij                    p += 4;
295296465Sdelphij                newkey = atoi(p);
296296465Sdelphij            } else
297109998Smarkm#ifndef OPENSSL_NO_DSA
298296465Sdelphij            if (strncmp("dsa:", p, 4) == 0) {
299296465Sdelphij                X509 *xtmp = NULL;
300296465Sdelphij                EVP_PKEY *dtmp;
30155714Skris
302296465Sdelphij                pkey_type = TYPE_DSA;
303296465Sdelphij                p += 4;
304296465Sdelphij                if ((in = BIO_new_file(p, "r")) == NULL) {
305296465Sdelphij                    perror(p);
306296465Sdelphij                    goto end;
307296465Sdelphij                }
308296465Sdelphij                if ((dsa_params =
309296465Sdelphij                     PEM_read_bio_DSAparams(in, NULL, NULL, NULL)) == NULL) {
310296465Sdelphij                    ERR_clear_error();
311296465Sdelphij                    (void)BIO_reset(in);
312296465Sdelphij                    if ((xtmp =
313296465Sdelphij                         PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL) {
314296465Sdelphij                        BIO_printf(bio_err,
315296465Sdelphij                                   "unable to load DSA parameters from file\n");
316296465Sdelphij                        goto end;
317296465Sdelphij                    }
31855714Skris
319296465Sdelphij                    if ((dtmp = X509_get_pubkey(xtmp)) == NULL)
320296465Sdelphij                        goto end;
321296465Sdelphij                    if (dtmp->type == EVP_PKEY_DSA)
322296465Sdelphij                        dsa_params = DSAparams_dup(dtmp->pkey.dsa);
323296465Sdelphij                    EVP_PKEY_free(dtmp);
324296465Sdelphij                    X509_free(xtmp);
325296465Sdelphij                    if (dsa_params == NULL) {
326296465Sdelphij                        BIO_printf(bio_err,
327296465Sdelphij                                   "Certificate does not contain DSA parameters\n");
328296465Sdelphij                        goto end;
329296465Sdelphij                    }
330296465Sdelphij                }
331296465Sdelphij                BIO_free(in);
332296465Sdelphij                in = NULL;
333296465Sdelphij                newkey = BN_num_bits(dsa_params->p);
334296465Sdelphij            } else
33555714Skris#endif
336160814Ssimon#ifndef OPENSSL_NO_ECDSA
337296465Sdelphij            if (strncmp("ec:", p, 3) == 0) {
338296465Sdelphij                X509 *xtmp = NULL;
339296465Sdelphij                EVP_PKEY *dtmp;
340296465Sdelphij                EC_GROUP *group;
341160814Ssimon
342296465Sdelphij                pkey_type = TYPE_EC;
343296465Sdelphij                p += 3;
344296465Sdelphij                if ((in = BIO_new_file(p, "r")) == NULL) {
345296465Sdelphij                    perror(p);
346296465Sdelphij                    goto end;
347296465Sdelphij                }
348296465Sdelphij                if ((ec_params = EC_KEY_new()) == NULL)
349296465Sdelphij                    goto end;
350296465Sdelphij                group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
351296465Sdelphij                if (group == NULL) {
352296465Sdelphij                    EC_KEY_free(ec_params);
353296465Sdelphij                    ERR_clear_error();
354296465Sdelphij                    (void)BIO_reset(in);
355296465Sdelphij                    if ((xtmp =
356296465Sdelphij                         PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL) {
357296465Sdelphij                        BIO_printf(bio_err,
358296465Sdelphij                                   "unable to load EC parameters from file\n");
359296465Sdelphij                        goto end;
360296465Sdelphij                    }
361160814Ssimon
362296465Sdelphij                    if ((dtmp = X509_get_pubkey(xtmp)) == NULL)
363296465Sdelphij                        goto end;
364296465Sdelphij                    if (dtmp->type == EVP_PKEY_EC)
365296465Sdelphij                        ec_params = EC_KEY_dup(dtmp->pkey.ec);
366296465Sdelphij                    EVP_PKEY_free(dtmp);
367296465Sdelphij                    X509_free(xtmp);
368296465Sdelphij                    if (ec_params == NULL) {
369296465Sdelphij                        BIO_printf(bio_err,
370296465Sdelphij                                   "Certificate does not contain EC parameters\n");
371296465Sdelphij                        goto end;
372296465Sdelphij                    }
373296465Sdelphij                } else {
374296465Sdelphij                    if (EC_KEY_set_group(ec_params, group) == 0)
375296465Sdelphij                        goto end;
376296465Sdelphij                    EC_GROUP_free(group);
377296465Sdelphij                }
378160814Ssimon
379296465Sdelphij                BIO_free(in);
380296465Sdelphij                in = NULL;
381296465Sdelphij                newkey = EC_GROUP_get_degree(EC_KEY_get0_group(ec_params));
382296465Sdelphij            } else
383160814Ssimon#endif
384109998Smarkm#ifndef OPENSSL_NO_DH
385296465Sdelphij            if (strncmp("dh:", p, 4) == 0) {
386296465Sdelphij                pkey_type = TYPE_DH;
387296465Sdelphij                p += 3;
388296465Sdelphij            } else
38955714Skris#endif
390296465Sdelphij            {
391296465Sdelphij                goto bad;
392296465Sdelphij            }
39355714Skris
394296465Sdelphij            newreq = 1;
395296465Sdelphij        } else if (strcmp(*argv, "-batch") == 0)
396296465Sdelphij            batch = 1;
397296465Sdelphij        else if (strcmp(*argv, "-newhdr") == 0)
398296465Sdelphij            newhdr = 1;
399296465Sdelphij        else if (strcmp(*argv, "-modulus") == 0)
400296465Sdelphij            modulus = 1;
401296465Sdelphij        else if (strcmp(*argv, "-verify") == 0)
402296465Sdelphij            verify = 1;
403296465Sdelphij        else if (strcmp(*argv, "-nodes") == 0)
404296465Sdelphij            nodes = 1;
405296465Sdelphij        else if (strcmp(*argv, "-noout") == 0)
406296465Sdelphij            noout = 1;
407296465Sdelphij        else if (strcmp(*argv, "-verbose") == 0)
408296465Sdelphij            verbose = 1;
409296465Sdelphij        else if (strcmp(*argv, "-utf8") == 0)
410296465Sdelphij            chtype = MBSTRING_UTF8;
411296465Sdelphij        else if (strcmp(*argv, "-nameopt") == 0) {
412296465Sdelphij            if (--argc < 1)
413296465Sdelphij                goto bad;
414296465Sdelphij            if (!set_name_ex(&nmflag, *(++argv)))
415296465Sdelphij                goto bad;
416296465Sdelphij        } else if (strcmp(*argv, "-reqopt") == 0) {
417296465Sdelphij            if (--argc < 1)
418296465Sdelphij                goto bad;
419296465Sdelphij            if (!set_cert_ex(&reqflag, *(++argv)))
420296465Sdelphij                goto bad;
421296465Sdelphij        } else if (strcmp(*argv, "-subject") == 0)
422296465Sdelphij            subject = 1;
423296465Sdelphij        else if (strcmp(*argv, "-text") == 0)
424296465Sdelphij            text = 1;
425296465Sdelphij        else if (strcmp(*argv, "-x509") == 0)
426296465Sdelphij            x509 = 1;
427296465Sdelphij        else if (strcmp(*argv, "-asn1-kludge") == 0)
428296465Sdelphij            kludge = 1;
429296465Sdelphij        else if (strcmp(*argv, "-no-asn1-kludge") == 0)
430296465Sdelphij            kludge = 0;
431296465Sdelphij        else if (strcmp(*argv, "-subj") == 0) {
432296465Sdelphij            if (--argc < 1)
433296465Sdelphij                goto bad;
434296465Sdelphij            subj = *(++argv);
435296465Sdelphij        } else if (strcmp(*argv, "-multivalue-rdn") == 0)
436296465Sdelphij            multirdn = 1;
437296465Sdelphij        else if (strcmp(*argv, "-days") == 0) {
438296465Sdelphij            if (--argc < 1)
439296465Sdelphij                goto bad;
440296465Sdelphij            days = atoi(*(++argv));
441296465Sdelphij            if (days == 0)
442296465Sdelphij                days = 30;
443296465Sdelphij        } else if (strcmp(*argv, "-set_serial") == 0) {
444296465Sdelphij            if (--argc < 1)
445296465Sdelphij                goto bad;
446296465Sdelphij            serial = s2i_ASN1_INTEGER(NULL, *(++argv));
447296465Sdelphij            if (!serial)
448296465Sdelphij                goto bad;
449296465Sdelphij        } else if ((md_alg = EVP_get_digestbyname(&((*argv)[1]))) != NULL) {
450296465Sdelphij            /* ok */
451296465Sdelphij            digest = md_alg;
452296465Sdelphij        } else if (strcmp(*argv, "-extensions") == 0) {
453296465Sdelphij            if (--argc < 1)
454296465Sdelphij                goto bad;
455296465Sdelphij            extensions = *(++argv);
456296465Sdelphij        } else if (strcmp(*argv, "-reqexts") == 0) {
457296465Sdelphij            if (--argc < 1)
458296465Sdelphij                goto bad;
459296465Sdelphij            req_exts = *(++argv);
460296465Sdelphij        } else {
461296465Sdelphij            BIO_printf(bio_err, "unknown option %s\n", *argv);
462296465Sdelphij            badops = 1;
463296465Sdelphij            break;
464296465Sdelphij        }
465296465Sdelphij        argc--;
466296465Sdelphij        argv++;
467296465Sdelphij    }
46855714Skris
469296465Sdelphij    if (badops) {
470296465Sdelphij bad:
471296465Sdelphij        BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog);
472296465Sdelphij        BIO_printf(bio_err, "where options  are\n");
473296465Sdelphij        BIO_printf(bio_err, " -inform arg    input format - DER or PEM\n");
474296465Sdelphij        BIO_printf(bio_err, " -outform arg   output format - DER or PEM\n");
475296465Sdelphij        BIO_printf(bio_err, " -in arg        input file\n");
476296465Sdelphij        BIO_printf(bio_err, " -out arg       output file\n");
477296465Sdelphij        BIO_printf(bio_err, " -text          text form of request\n");
478296465Sdelphij        BIO_printf(bio_err, " -pubkey        output public key\n");
479296465Sdelphij        BIO_printf(bio_err, " -noout         do not output REQ\n");
480296465Sdelphij        BIO_printf(bio_err, " -verify        verify signature on REQ\n");
481296465Sdelphij        BIO_printf(bio_err, " -modulus       RSA modulus\n");
482296465Sdelphij        BIO_printf(bio_err, " -nodes         don't encrypt the output key\n");
483111147Snectar#ifndef OPENSSL_NO_ENGINE
484296465Sdelphij        BIO_printf(bio_err,
485296465Sdelphij                   " -engine e      use engine e, possibly a hardware device\n");
486111147Snectar#endif
487296465Sdelphij        BIO_printf(bio_err, " -subject       output the request's subject\n");
488296465Sdelphij        BIO_printf(bio_err, " -passin        private key password source\n");
489296465Sdelphij        BIO_printf(bio_err,
490296465Sdelphij                   " -key file      use the private key contained in file\n");
491296465Sdelphij        BIO_printf(bio_err, " -keyform arg   key file format\n");
492296465Sdelphij        BIO_printf(bio_err, " -keyout arg    file to send the key to\n");
493296465Sdelphij        BIO_printf(bio_err, " -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR,
494296465Sdelphij                   LIST_SEPARATOR_CHAR);
495296465Sdelphij        BIO_printf(bio_err,
496296465Sdelphij                   "                load the file (or the files in the directory) into\n");
497296465Sdelphij        BIO_printf(bio_err, "                the random number generator\n");
498296465Sdelphij        BIO_printf(bio_err,
499296465Sdelphij                   " -newkey rsa:bits generate a new RSA key of 'bits' in size\n");
500296465Sdelphij        BIO_printf(bio_err,
501296465Sdelphij                   " -newkey dsa:file generate a new DSA key, parameters taken from CA in 'file'\n");
502160814Ssimon#ifndef OPENSSL_NO_ECDSA
503296465Sdelphij        BIO_printf(bio_err,
504296465Sdelphij                   " -newkey ec:file generate a new EC key, parameters taken from CA in 'file'\n");
505160814Ssimon#endif
506296465Sdelphij        BIO_printf(bio_err,
507296465Sdelphij                   " -[digest]      Digest to sign with (md5, sha1, md2, mdc2, md4)\n");
508296465Sdelphij        BIO_printf(bio_err, " -config file   request template file.\n");
509296465Sdelphij        BIO_printf(bio_err,
510296465Sdelphij                   " -subj arg      set or modify request subject\n");
511296465Sdelphij        BIO_printf(bio_err,
512296465Sdelphij                   " -multivalue-rdn enable support for multivalued RDNs\n");
513296465Sdelphij        BIO_printf(bio_err, " -new           new request.\n");
514296465Sdelphij        BIO_printf(bio_err,
515296465Sdelphij                   " -batch         do not ask anything during request generation\n");
516296465Sdelphij        BIO_printf(bio_err,
517296465Sdelphij                   " -x509          output a x509 structure instead of a cert. req.\n");
518296465Sdelphij        BIO_printf(bio_err,
519296465Sdelphij                   " -days          number of days a certificate generated by -x509 is valid for.\n");
520296465Sdelphij        BIO_printf(bio_err,
521296465Sdelphij                   " -set_serial    serial number to use for a certificate generated by -x509.\n");
522296465Sdelphij        BIO_printf(bio_err,
523296465Sdelphij                   " -newhdr        output \"NEW\" in the header lines\n");
524296465Sdelphij        BIO_printf(bio_err,
525296465Sdelphij                   " -asn1-kludge   Output the 'request' in a format that is wrong but some CA's\n");
526296465Sdelphij        BIO_printf(bio_err,
527296465Sdelphij                   "                have been reported as requiring\n");
528296465Sdelphij        BIO_printf(bio_err,
529296465Sdelphij                   " -extensions .. specify certificate extension section (override value in config file)\n");
530296465Sdelphij        BIO_printf(bio_err,
531296465Sdelphij                   " -reqexts ..    specify request extension section (override value in config file)\n");
532296465Sdelphij        BIO_printf(bio_err,
533296465Sdelphij                   " -utf8          input characters are UTF8 (default ASCII)\n");
534296465Sdelphij        BIO_printf(bio_err,
535296465Sdelphij                   " -nameopt arg    - various certificate name options\n");
536296465Sdelphij        BIO_printf(bio_err,
537296465Sdelphij                   " -reqopt arg    - various request text options\n\n");
538296465Sdelphij        goto end;
539296465Sdelphij    }
54055714Skris
541296465Sdelphij    ERR_load_crypto_strings();
542296465Sdelphij    if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
543296465Sdelphij        BIO_printf(bio_err, "Error getting passwords\n");
544296465Sdelphij        goto end;
545296465Sdelphij    }
546296465Sdelphij#ifndef MONOLITH                /* else this has happened in openssl.c
547296465Sdelphij                                 * (global `config') */
548296465Sdelphij    /* Lets load up our environment a little */
549296465Sdelphij    p = getenv("OPENSSL_CONF");
550296465Sdelphij    if (p == NULL)
551296465Sdelphij        p = getenv("SSLEAY_CONF");
552296465Sdelphij    if (p == NULL)
553296465Sdelphij        p = to_free = make_config_name();
554296465Sdelphij    default_config_file = p;
555296465Sdelphij    config = NCONF_new(NULL);
556296465Sdelphij    i = NCONF_load(config, p, &errline);
55755714Skris#endif
55855714Skris
559296465Sdelphij    if (template != NULL) {
560296465Sdelphij        long errline = -1;
56155714Skris
562296465Sdelphij        if (verbose)
563296465Sdelphij            BIO_printf(bio_err, "Using configuration from %s\n", template);
564296465Sdelphij        req_conf = NCONF_new(NULL);
565296465Sdelphij        i = NCONF_load(req_conf, template, &errline);
566296465Sdelphij        if (i == 0) {
567296465Sdelphij            BIO_printf(bio_err, "error on line %ld of %s\n", errline,
568296465Sdelphij                       template);
569296465Sdelphij            goto end;
570296465Sdelphij        }
571296465Sdelphij    } else {
572296465Sdelphij        req_conf = config;
573160814Ssimon
574296465Sdelphij        if (req_conf == NULL) {
575296465Sdelphij            BIO_printf(bio_err, "Unable to load config info from %s\n",
576296465Sdelphij                       default_config_file);
577296465Sdelphij            if (newreq)
578296465Sdelphij                goto end;
579296465Sdelphij        } else if (verbose)
580296465Sdelphij            BIO_printf(bio_err, "Using configuration from %s\n",
581296465Sdelphij                       default_config_file);
582296465Sdelphij    }
58355714Skris
584296465Sdelphij    if (req_conf != NULL) {
585296465Sdelphij        if (!load_config(bio_err, req_conf))
586296465Sdelphij            goto end;
587296465Sdelphij        p = NCONF_get_string(req_conf, NULL, "oid_file");
588296465Sdelphij        if (p == NULL)
589296465Sdelphij            ERR_clear_error();
590296465Sdelphij        if (p != NULL) {
591296465Sdelphij            BIO *oid_bio;
59255714Skris
593296465Sdelphij            oid_bio = BIO_new_file(p, "r");
594296465Sdelphij            if (oid_bio == NULL) {
595296465Sdelphij                /*-
596296465Sdelphij                BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
597296465Sdelphij                ERR_print_errors(bio_err);
598296465Sdelphij                */
599296465Sdelphij            } else {
600296465Sdelphij                OBJ_create_objects(oid_bio);
601296465Sdelphij                BIO_free(oid_bio);
602296465Sdelphij            }
603296465Sdelphij        }
604296465Sdelphij    }
605296465Sdelphij    if (!add_oid_section(bio_err, req_conf))
606296465Sdelphij        goto end;
60755714Skris
608296465Sdelphij    if (md_alg == NULL) {
609296465Sdelphij        p = NCONF_get_string(req_conf, SECTION, "default_md");
610296465Sdelphij        if (p == NULL)
611296465Sdelphij            ERR_clear_error();
612296465Sdelphij        if (p != NULL) {
613296465Sdelphij            if ((md_alg = EVP_get_digestbyname(p)) != NULL)
614296465Sdelphij                digest = md_alg;
615296465Sdelphij        }
616296465Sdelphij    }
61755714Skris
618296465Sdelphij    if (!extensions) {
619296465Sdelphij        extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
620296465Sdelphij        if (!extensions)
621296465Sdelphij            ERR_clear_error();
622296465Sdelphij    }
623296465Sdelphij    if (extensions) {
624296465Sdelphij        /* Check syntax of file */
625296465Sdelphij        X509V3_CTX ctx;
626296465Sdelphij        X509V3_set_ctx_test(&ctx);
627296465Sdelphij        X509V3_set_nconf(&ctx, req_conf);
628296465Sdelphij        if (!X509V3_EXT_add_nconf(req_conf, &ctx, extensions, NULL)) {
629296465Sdelphij            BIO_printf(bio_err,
630296465Sdelphij                       "Error Loading extension section %s\n", extensions);
631296465Sdelphij            goto end;
632296465Sdelphij        }
633296465Sdelphij    }
63455714Skris
635296465Sdelphij    if (!passin) {
636296465Sdelphij        passin = NCONF_get_string(req_conf, SECTION, "input_password");
637296465Sdelphij        if (!passin)
638296465Sdelphij            ERR_clear_error();
639296465Sdelphij    }
64059191Skris
641296465Sdelphij    if (!passout) {
642296465Sdelphij        passout = NCONF_get_string(req_conf, SECTION, "output_password");
643296465Sdelphij        if (!passout)
644296465Sdelphij            ERR_clear_error();
645296465Sdelphij    }
64659191Skris
647296465Sdelphij    p = NCONF_get_string(req_conf, SECTION, STRING_MASK);
648296465Sdelphij    if (!p)
649296465Sdelphij        ERR_clear_error();
65059191Skris
651296465Sdelphij    if (p && !ASN1_STRING_set_default_mask_asc(p)) {
652296465Sdelphij        BIO_printf(bio_err, "Invalid global string mask setting %s\n", p);
653296465Sdelphij        goto end;
654296465Sdelphij    }
655109998Smarkm
656296465Sdelphij    if (chtype != MBSTRING_UTF8) {
657296465Sdelphij        p = NCONF_get_string(req_conf, SECTION, UTF8_IN);
658296465Sdelphij        if (!p)
659296465Sdelphij            ERR_clear_error();
660296465Sdelphij        else if (!strcmp(p, "yes"))
661296465Sdelphij            chtype = MBSTRING_UTF8;
662296465Sdelphij    }
663109998Smarkm
664296465Sdelphij    if (!req_exts) {
665296465Sdelphij        req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
666296465Sdelphij        if (!req_exts)
667296465Sdelphij            ERR_clear_error();
668296465Sdelphij    }
669296465Sdelphij    if (req_exts) {
670296465Sdelphij        /* Check syntax of file */
671296465Sdelphij        X509V3_CTX ctx;
672296465Sdelphij        X509V3_set_ctx_test(&ctx);
673296465Sdelphij        X509V3_set_nconf(&ctx, req_conf);
674296465Sdelphij        if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_exts, NULL)) {
675296465Sdelphij            BIO_printf(bio_err,
676296465Sdelphij                       "Error Loading request extension section %s\n",
677296465Sdelphij                       req_exts);
678296465Sdelphij            goto end;
679296465Sdelphij        }
680296465Sdelphij    }
68159191Skris
682296465Sdelphij    in = BIO_new(BIO_s_file());
683296465Sdelphij    out = BIO_new(BIO_s_file());
684296465Sdelphij    if ((in == NULL) || (out == NULL))
685296465Sdelphij        goto end;
68655714Skris
687111147Snectar#ifndef OPENSSL_NO_ENGINE
688296465Sdelphij    e = setup_engine(bio_err, engine, 0);
689111147Snectar#endif
690109998Smarkm
691296465Sdelphij    if (keyfile != NULL) {
692296465Sdelphij        pkey = load_key(bio_err, keyfile, keyform, 0, passin, e,
693296465Sdelphij                        "Private Key");
694296465Sdelphij        if (!pkey) {
695296465Sdelphij            /*
696296465Sdelphij             * load_key() has already printed an appropriate message
697296465Sdelphij             */
698296465Sdelphij            goto end;
699296465Sdelphij        } else {
700296465Sdelphij            char *randfile = NCONF_get_string(req_conf, SECTION, "RANDFILE");
701296465Sdelphij            if (randfile == NULL)
702296465Sdelphij                ERR_clear_error();
703296465Sdelphij            app_RAND_load_file(randfile, bio_err, 0);
704296465Sdelphij        }
705296465Sdelphij    }
70655714Skris
707296465Sdelphij    if (newreq && (pkey == NULL)) {
708160814Ssimon#ifndef OPENSSL_NO_RSA
709296465Sdelphij        BN_GENCB cb;
710160814Ssimon#endif
711296465Sdelphij        char *randfile = NCONF_get_string(req_conf, SECTION, "RANDFILE");
712296465Sdelphij        if (randfile == NULL)
713296465Sdelphij            ERR_clear_error();
714296465Sdelphij        app_RAND_load_file(randfile, bio_err, 0);
715296465Sdelphij        if (inrand)
716296465Sdelphij            app_RAND_load_files(inrand);
71755714Skris
718296465Sdelphij        if (newkey <= 0) {
719296465Sdelphij            if (!NCONF_get_number(req_conf, SECTION, BITS, &newkey))
720296465Sdelphij                newkey = DEFAULT_KEY_LENGTH;
721296465Sdelphij        }
72255714Skris
723296465Sdelphij        if (newkey < MIN_KEY_LENGTH
724296465Sdelphij            && (pkey_type == TYPE_RSA || pkey_type == TYPE_DSA)) {
725296465Sdelphij            BIO_printf(bio_err, "private key length is too short,\n");
726296465Sdelphij            BIO_printf(bio_err, "it needs to be at least %d bits, not %ld\n",
727296465Sdelphij                       MIN_KEY_LENGTH, newkey);
728296465Sdelphij            goto end;
729296465Sdelphij        }
730296465Sdelphij        BIO_printf(bio_err, "Generating a %ld bit %s private key\n",
731296465Sdelphij                   newkey, (pkey_type == TYPE_RSA) ? "RSA" :
732296465Sdelphij                   (pkey_type == TYPE_DSA) ? "DSA" : "EC");
73355714Skris
734296465Sdelphij        if ((pkey = EVP_PKEY_new()) == NULL)
735296465Sdelphij            goto end;
736296465Sdelphij
737109998Smarkm#ifndef OPENSSL_NO_RSA
738296465Sdelphij        BN_GENCB_set(&cb, req_cb, bio_err);
739296465Sdelphij        if (pkey_type == TYPE_RSA) {
740296465Sdelphij            RSA *rsa = RSA_new();
741296465Sdelphij            BIGNUM *bn = BN_new();
742296465Sdelphij            if (!bn || !rsa || !BN_set_word(bn, 0x10001) ||
743296465Sdelphij                !RSA_generate_key_ex(rsa, newkey, bn, &cb) ||
744296465Sdelphij                !EVP_PKEY_assign_RSA(pkey, rsa)) {
745296465Sdelphij                if (bn)
746296465Sdelphij                    BN_free(bn);
747296465Sdelphij                if (rsa)
748296465Sdelphij                    RSA_free(rsa);
749296465Sdelphij                goto end;
750296465Sdelphij            }
751296465Sdelphij            BN_free(bn);
752296465Sdelphij        } else
75355714Skris#endif
754109998Smarkm#ifndef OPENSSL_NO_DSA
755296465Sdelphij        if (pkey_type == TYPE_DSA) {
756296465Sdelphij            if (!DSA_generate_key(dsa_params))
757296465Sdelphij                goto end;
758296465Sdelphij            if (!EVP_PKEY_assign_DSA(pkey, dsa_params))
759296465Sdelphij                goto end;
760296465Sdelphij            dsa_params = NULL;
761296465Sdelphij        }
76255714Skris#endif
763160814Ssimon#ifndef OPENSSL_NO_ECDSA
764296465Sdelphij        if (pkey_type == TYPE_EC) {
765296465Sdelphij            if (!EC_KEY_generate_key(ec_params))
766296465Sdelphij                goto end;
767296465Sdelphij            if (!EVP_PKEY_assign_EC_KEY(pkey, ec_params))
768296465Sdelphij                goto end;
769296465Sdelphij            ec_params = NULL;
770296465Sdelphij        }
771160814Ssimon#endif
77255714Skris
773296465Sdelphij        app_RAND_write_file(randfile, bio_err);
77455714Skris
775296465Sdelphij        if (pkey == NULL)
776296465Sdelphij            goto end;
77755714Skris
778296465Sdelphij        if (keyout == NULL) {
779296465Sdelphij            keyout = NCONF_get_string(req_conf, SECTION, KEYFILE);
780296465Sdelphij            if (keyout == NULL)
781296465Sdelphij                ERR_clear_error();
782296465Sdelphij        }
783296465Sdelphij
784296465Sdelphij        if (keyout == NULL) {
785296465Sdelphij            BIO_printf(bio_err, "writing new private key to stdout\n");
786296465Sdelphij            BIO_set_fp(out, stdout, BIO_NOCLOSE);
787109998Smarkm#ifdef OPENSSL_SYS_VMS
788296465Sdelphij            {
789296465Sdelphij                BIO *tmpbio = BIO_new(BIO_f_linebuffer());
790296465Sdelphij                out = BIO_push(tmpbio, out);
791296465Sdelphij            }
79268651Skris#endif
793296465Sdelphij        } else {
794296465Sdelphij            BIO_printf(bio_err, "writing new private key to '%s'\n", keyout);
795296465Sdelphij            if (BIO_write_filename(out, keyout) <= 0) {
796296465Sdelphij                perror(keyout);
797296465Sdelphij                goto end;
798296465Sdelphij            }
799296465Sdelphij        }
80055714Skris
801296465Sdelphij        p = NCONF_get_string(req_conf, SECTION, "encrypt_rsa_key");
802296465Sdelphij        if (p == NULL) {
803296465Sdelphij            ERR_clear_error();
804296465Sdelphij            p = NCONF_get_string(req_conf, SECTION, "encrypt_key");
805296465Sdelphij            if (p == NULL)
806296465Sdelphij                ERR_clear_error();
807296465Sdelphij        }
808296465Sdelphij        if ((p != NULL) && (strcmp(p, "no") == 0))
809296465Sdelphij            cipher = NULL;
810296465Sdelphij        if (nodes)
811296465Sdelphij            cipher = NULL;
81255714Skris
813296465Sdelphij        i = 0;
814296465Sdelphij loop:
815296465Sdelphij        if (!PEM_write_bio_PrivateKey(out, pkey, cipher,
816296465Sdelphij                                      NULL, 0, NULL, passout)) {
817296465Sdelphij            if ((ERR_GET_REASON(ERR_peek_error()) ==
818296465Sdelphij                 PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3)) {
819296465Sdelphij                ERR_clear_error();
820296465Sdelphij                i++;
821296465Sdelphij                goto loop;
822296465Sdelphij            }
823296465Sdelphij            goto end;
824296465Sdelphij        }
825296465Sdelphij        BIO_printf(bio_err, "-----\n");
826296465Sdelphij    }
82755714Skris
828296465Sdelphij    if (!newreq) {
829296465Sdelphij        /*
830296465Sdelphij         * Since we are using a pre-existing certificate request, the kludge
831296465Sdelphij         * 'format' info should not be changed.
832296465Sdelphij         */
833296465Sdelphij        kludge = -1;
834296465Sdelphij        if (infile == NULL)
835296465Sdelphij            BIO_set_fp(in, stdin, BIO_NOCLOSE);
836296465Sdelphij        else {
837296465Sdelphij            if (BIO_read_filename(in, infile) <= 0) {
838296465Sdelphij                perror(infile);
839296465Sdelphij                goto end;
840296465Sdelphij            }
841296465Sdelphij        }
84255714Skris
843296465Sdelphij        if (informat == FORMAT_ASN1)
844296465Sdelphij            req = d2i_X509_REQ_bio(in, NULL);
845296465Sdelphij        else if (informat == FORMAT_PEM)
846296465Sdelphij            req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
847296465Sdelphij        else {
848296465Sdelphij            BIO_printf(bio_err,
849296465Sdelphij                       "bad input format specified for X509 request\n");
850296465Sdelphij            goto end;
851296465Sdelphij        }
852296465Sdelphij        if (req == NULL) {
853296465Sdelphij            BIO_printf(bio_err, "unable to load X509 request\n");
854296465Sdelphij            goto end;
855296465Sdelphij        }
856296465Sdelphij    }
857296465Sdelphij
858296465Sdelphij    if (newreq || x509) {
859296465Sdelphij        if (pkey == NULL) {
860296465Sdelphij            BIO_printf(bio_err, "you need to specify a private key\n");
861296465Sdelphij            goto end;
862296465Sdelphij        }
863109998Smarkm#ifndef OPENSSL_NO_DSA
864296465Sdelphij        if (pkey->type == EVP_PKEY_DSA)
865296465Sdelphij            digest = EVP_dss1();
86672613Skris#endif
867160814Ssimon#ifndef OPENSSL_NO_ECDSA
868296465Sdelphij        if (pkey->type == EVP_PKEY_EC)
869296465Sdelphij            digest = EVP_ecdsa();
870160814Ssimon#endif
871296465Sdelphij        if (req == NULL) {
872296465Sdelphij            req = X509_REQ_new();
873296465Sdelphij            if (req == NULL) {
874296465Sdelphij                goto end;
875296465Sdelphij            }
87655714Skris
877296465Sdelphij            i = make_REQ(req, pkey, subj, multirdn, !x509, chtype);
878296465Sdelphij            subj = NULL;        /* done processing '-subj' option */
879296465Sdelphij            if ((kludge > 0)
880296465Sdelphij                && !sk_X509_ATTRIBUTE_num(req->req_info->attributes)) {
881296465Sdelphij                sk_X509_ATTRIBUTE_free(req->req_info->attributes);
882296465Sdelphij                req->req_info->attributes = NULL;
883296465Sdelphij            }
884296465Sdelphij            if (!i) {
885296465Sdelphij                BIO_printf(bio_err, "problems making Certificate Request\n");
886296465Sdelphij                goto end;
887296465Sdelphij            }
888296465Sdelphij        }
889296465Sdelphij        if (x509) {
890296465Sdelphij            EVP_PKEY *tmppkey;
891296465Sdelphij            X509V3_CTX ext_ctx;
892296465Sdelphij            if ((x509ss = X509_new()) == NULL)
893296465Sdelphij                goto end;
89455714Skris
895296465Sdelphij            /* Set version to V3 */
896296465Sdelphij            if (extensions && !X509_set_version(x509ss, 2))
897296465Sdelphij                goto end;
898296465Sdelphij            if (serial) {
899296465Sdelphij                if (!X509_set_serialNumber(x509ss, serial))
900296465Sdelphij                    goto end;
901296465Sdelphij            } else {
902296465Sdelphij                if (!rand_serial(NULL, X509_get_serialNumber(x509ss)))
903296465Sdelphij                    goto end;
904296465Sdelphij            }
90555714Skris
906296465Sdelphij            if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req)))
907296465Sdelphij                goto end;
908296465Sdelphij            if (!X509_gmtime_adj(X509_get_notBefore(x509ss), 0))
909296465Sdelphij                goto end;
910296465Sdelphij            if (!X509_gmtime_adj
911296465Sdelphij                (X509_get_notAfter(x509ss), (long)60 * 60 * 24 * days))
912296465Sdelphij                goto end;
913296465Sdelphij            if (!X509_set_subject_name
914296465Sdelphij                (x509ss, X509_REQ_get_subject_name(req)))
915296465Sdelphij                goto end;
916296465Sdelphij            tmppkey = X509_REQ_get_pubkey(req);
917296465Sdelphij            if (!tmppkey || !X509_set_pubkey(x509ss, tmppkey))
918296465Sdelphij                goto end;
919296465Sdelphij            EVP_PKEY_free(tmppkey);
92055714Skris
921296465Sdelphij            /* Set up V3 context struct */
92255714Skris
923296465Sdelphij            X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0);
924296465Sdelphij            X509V3_set_nconf(&ext_ctx, req_conf);
92555714Skris
926296465Sdelphij            /* Add extensions */
927296465Sdelphij            if (extensions && !X509V3_EXT_add_nconf(req_conf,
928296465Sdelphij                                                    &ext_ctx, extensions,
929296465Sdelphij                                                    x509ss)) {
930296465Sdelphij                BIO_printf(bio_err, "Error Loading extension section %s\n",
931296465Sdelphij                           extensions);
932296465Sdelphij                goto end;
933296465Sdelphij            }
93459191Skris
935296465Sdelphij            if (!(i = X509_sign(x509ss, pkey, digest)))
936296465Sdelphij                goto end;
937296465Sdelphij        } else {
938296465Sdelphij            X509V3_CTX ext_ctx;
93959191Skris
940296465Sdelphij            /* Set up V3 context struct */
94159191Skris
942296465Sdelphij            X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
943296465Sdelphij            X509V3_set_nconf(&ext_ctx, req_conf);
94455714Skris
945296465Sdelphij            /* Add extensions */
946296465Sdelphij            if (req_exts && !X509V3_EXT_REQ_add_nconf(req_conf,
947296465Sdelphij                                                      &ext_ctx, req_exts,
948296465Sdelphij                                                      req)) {
949296465Sdelphij                BIO_printf(bio_err, "Error Loading extension section %s\n",
950296465Sdelphij                           req_exts);
951296465Sdelphij                goto end;
952296465Sdelphij            }
953296465Sdelphij            if (!(i = X509_REQ_sign(req, pkey, digest)))
954296465Sdelphij                goto end;
955296465Sdelphij        }
956296465Sdelphij    }
957109998Smarkm
958296465Sdelphij    if (subj && x509) {
959296465Sdelphij        BIO_printf(bio_err, "Cannot modifiy certificate subject\n");
960296465Sdelphij        goto end;
961296465Sdelphij    }
962109998Smarkm
963296465Sdelphij    if (subj && !x509) {
964296465Sdelphij        if (verbose) {
965296465Sdelphij            BIO_printf(bio_err, "Modifying Request's Subject\n");
966296465Sdelphij            print_name(bio_err, "old subject=",
967296465Sdelphij                       X509_REQ_get_subject_name(req), nmflag);
968296465Sdelphij        }
969109998Smarkm
970296465Sdelphij        if (build_subject(req, subj, chtype, multirdn) == 0) {
971296465Sdelphij            BIO_printf(bio_err, "ERROR: cannot modify subject\n");
972296465Sdelphij            ex = 1;
973296465Sdelphij            goto end;
974296465Sdelphij        }
975109998Smarkm
976296465Sdelphij        req->req_info->enc.modified = 1;
977109998Smarkm
978296465Sdelphij        if (verbose) {
979296465Sdelphij            print_name(bio_err, "new subject=",
980296465Sdelphij                       X509_REQ_get_subject_name(req), nmflag);
981296465Sdelphij        }
982296465Sdelphij    }
98355714Skris
984296465Sdelphij    if (verify && !x509) {
985296465Sdelphij        int tmp = 0;
98655714Skris
987296465Sdelphij        if (pkey == NULL) {
988296465Sdelphij            pkey = X509_REQ_get_pubkey(req);
989296465Sdelphij            tmp = 1;
990296465Sdelphij            if (pkey == NULL)
991296465Sdelphij                goto end;
992296465Sdelphij        }
99355714Skris
994296465Sdelphij        i = X509_REQ_verify(req, pkey);
995296465Sdelphij        if (tmp) {
996296465Sdelphij            EVP_PKEY_free(pkey);
997296465Sdelphij            pkey = NULL;
998296465Sdelphij        }
99955714Skris
1000296465Sdelphij        if (i < 0) {
1001296465Sdelphij            goto end;
1002296465Sdelphij        } else if (i == 0) {
1003296465Sdelphij            BIO_printf(bio_err, "verify failure\n");
1004296465Sdelphij            ERR_print_errors(bio_err);
1005296465Sdelphij        } else                  /* if (i > 0) */
1006296465Sdelphij            BIO_printf(bio_err, "verify OK\n");
1007296465Sdelphij    }
100855714Skris
1009296465Sdelphij    if (noout && !text && !modulus && !subject && !pubkey) {
1010296465Sdelphij        ex = 0;
1011296465Sdelphij        goto end;
1012296465Sdelphij    }
1013296465Sdelphij
1014296465Sdelphij    if (outfile == NULL) {
1015296465Sdelphij        BIO_set_fp(out, stdout, BIO_NOCLOSE);
1016109998Smarkm#ifdef OPENSSL_SYS_VMS
1017296465Sdelphij        {
1018296465Sdelphij            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
1019296465Sdelphij            out = BIO_push(tmpbio, out);
1020296465Sdelphij        }
102168651Skris#endif
1022296465Sdelphij    } else {
1023296465Sdelphij        if ((keyout != NULL) && (strcmp(outfile, keyout) == 0))
1024296465Sdelphij            i = (int)BIO_append_filename(out, outfile);
1025296465Sdelphij        else
1026296465Sdelphij            i = (int)BIO_write_filename(out, outfile);
1027296465Sdelphij        if (!i) {
1028296465Sdelphij            perror(outfile);
1029296465Sdelphij            goto end;
1030296465Sdelphij        }
1031296465Sdelphij    }
103255714Skris
1033296465Sdelphij    if (pubkey) {
1034296465Sdelphij        EVP_PKEY *tpubkey;
1035296465Sdelphij        tpubkey = X509_REQ_get_pubkey(req);
1036296465Sdelphij        if (tpubkey == NULL) {
1037296465Sdelphij            BIO_printf(bio_err, "Error getting public key\n");
1038296465Sdelphij            ERR_print_errors(bio_err);
1039296465Sdelphij            goto end;
1040296465Sdelphij        }
1041296465Sdelphij        PEM_write_bio_PUBKEY(out, tpubkey);
1042296465Sdelphij        EVP_PKEY_free(tpubkey);
1043296465Sdelphij    }
1044109998Smarkm
1045296465Sdelphij    if (text) {
1046296465Sdelphij        if (x509)
1047296465Sdelphij            X509_print_ex(out, x509ss, nmflag, reqflag);
1048296465Sdelphij        else
1049296465Sdelphij            X509_REQ_print_ex(out, req, nmflag, reqflag);
1050296465Sdelphij    }
105155714Skris
1052296465Sdelphij    if (subject) {
1053296465Sdelphij        if (x509)
1054296465Sdelphij            print_name(out, "subject=", X509_get_subject_name(x509ss),
1055296465Sdelphij                       nmflag);
1056296465Sdelphij        else
1057296465Sdelphij            print_name(out, "subject=", X509_REQ_get_subject_name(req),
1058296465Sdelphij                       nmflag);
1059296465Sdelphij    }
1060109998Smarkm
1061296465Sdelphij    if (modulus) {
1062296465Sdelphij        EVP_PKEY *tpubkey;
106355714Skris
1064296465Sdelphij        if (x509)
1065296465Sdelphij            tpubkey = X509_get_pubkey(x509ss);
1066296465Sdelphij        else
1067296465Sdelphij            tpubkey = X509_REQ_get_pubkey(req);
1068296465Sdelphij        if (tpubkey == NULL) {
1069296465Sdelphij            fprintf(stdout, "Modulus=unavailable\n");
1070296465Sdelphij            goto end;
1071296465Sdelphij        }
1072296465Sdelphij        fprintf(stdout, "Modulus=");
1073109998Smarkm#ifndef OPENSSL_NO_RSA
1074296465Sdelphij        if (tpubkey->type == EVP_PKEY_RSA)
1075296465Sdelphij            BN_print(out, tpubkey->pkey.rsa->n);
1076296465Sdelphij        else
107755714Skris#endif
1078296465Sdelphij            fprintf(stdout, "Wrong Algorithm type");
1079296465Sdelphij        EVP_PKEY_free(tpubkey);
1080296465Sdelphij        fprintf(stdout, "\n");
1081296465Sdelphij    }
108255714Skris
1083296465Sdelphij    if (!noout && !x509) {
1084296465Sdelphij        if (outformat == FORMAT_ASN1)
1085296465Sdelphij            i = i2d_X509_REQ_bio(out, req);
1086296465Sdelphij        else if (outformat == FORMAT_PEM) {
1087296465Sdelphij            if (newhdr)
1088296465Sdelphij                i = PEM_write_bio_X509_REQ_NEW(out, req);
1089296465Sdelphij            else
1090296465Sdelphij                i = PEM_write_bio_X509_REQ(out, req);
1091296465Sdelphij        } else {
1092296465Sdelphij            BIO_printf(bio_err, "bad output format specified for outfile\n");
1093296465Sdelphij            goto end;
1094296465Sdelphij        }
1095296465Sdelphij        if (!i) {
1096296465Sdelphij            BIO_printf(bio_err, "unable to write X509 request\n");
1097296465Sdelphij            goto end;
1098296465Sdelphij        }
1099296465Sdelphij    }
1100296465Sdelphij    if (!noout && x509 && (x509ss != NULL)) {
1101296465Sdelphij        if (outformat == FORMAT_ASN1)
1102296465Sdelphij            i = i2d_X509_bio(out, x509ss);
1103296465Sdelphij        else if (outformat == FORMAT_PEM)
1104296465Sdelphij            i = PEM_write_bio_X509(out, x509ss);
1105296465Sdelphij        else {
1106296465Sdelphij            BIO_printf(bio_err, "bad output format specified for outfile\n");
1107296465Sdelphij            goto end;
1108296465Sdelphij        }
1109296465Sdelphij        if (!i) {
1110296465Sdelphij            BIO_printf(bio_err, "unable to write X509 certificate\n");
1111296465Sdelphij            goto end;
1112296465Sdelphij        }
1113296465Sdelphij    }
1114296465Sdelphij    ex = 0;
1115296465Sdelphij end:
1116109998Smarkm#ifndef MONOLITH
1117296465Sdelphij    if (to_free)
1118296465Sdelphij        OPENSSL_free(to_free);
1119109998Smarkm#endif
1120296465Sdelphij    if (ex) {
1121296465Sdelphij        ERR_print_errors(bio_err);
1122296465Sdelphij    }
1123296465Sdelphij    if ((req_conf != NULL) && (req_conf != config))
1124296465Sdelphij        NCONF_free(req_conf);
1125296465Sdelphij    BIO_free(in);
1126296465Sdelphij    BIO_free_all(out);
1127296465Sdelphij    EVP_PKEY_free(pkey);
1128296465Sdelphij    X509_REQ_free(req);
1129296465Sdelphij    X509_free(x509ss);
1130296465Sdelphij    ASN1_INTEGER_free(serial);
1131296465Sdelphij    if (passargin && passin)
1132296465Sdelphij        OPENSSL_free(passin);
1133296465Sdelphij    if (passargout && passout)
1134296465Sdelphij        OPENSSL_free(passout);
1135296465Sdelphij    OBJ_cleanup();
1136109998Smarkm#ifndef OPENSSL_NO_DSA
1137296465Sdelphij    if (dsa_params != NULL)
1138296465Sdelphij        DSA_free(dsa_params);
113955714Skris#endif
1140160814Ssimon#ifndef OPENSSL_NO_ECDSA
1141296465Sdelphij    if (ec_params != NULL)
1142296465Sdelphij        EC_KEY_free(ec_params);
1143160814Ssimon#endif
1144296465Sdelphij    apps_shutdown();
1145296465Sdelphij    OPENSSL_EXIT(ex);
1146296465Sdelphij}
114755714Skris
1148160814Ssimonstatic int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn,
1149296465Sdelphij                    int attribs, unsigned long chtype)
1150296465Sdelphij{
1151296465Sdelphij    int ret = 0, i;
1152296465Sdelphij    char no_prompt = 0;
1153296465Sdelphij    STACK_OF(CONF_VALUE) *dn_sk, *attr_sk = NULL;
1154296465Sdelphij    char *tmp, *dn_sect, *attr_sect;
115559191Skris
1156296465Sdelphij    tmp = NCONF_get_string(req_conf, SECTION, PROMPT);
1157296465Sdelphij    if (tmp == NULL)
1158296465Sdelphij        ERR_clear_error();
1159296465Sdelphij    if ((tmp != NULL) && !strcmp(tmp, "no"))
1160296465Sdelphij        no_prompt = 1;
116159191Skris
1162296465Sdelphij    dn_sect = NCONF_get_string(req_conf, SECTION, DISTINGUISHED_NAME);
1163296465Sdelphij    if (dn_sect == NULL) {
1164296465Sdelphij        BIO_printf(bio_err, "unable to find '%s' in config\n",
1165296465Sdelphij                   DISTINGUISHED_NAME);
1166296465Sdelphij        goto err;
1167296465Sdelphij    }
1168296465Sdelphij    dn_sk = NCONF_get_section(req_conf, dn_sect);
1169296465Sdelphij    if (dn_sk == NULL) {
1170296465Sdelphij        BIO_printf(bio_err, "unable to get '%s' section\n", dn_sect);
1171296465Sdelphij        goto err;
1172296465Sdelphij    }
117355714Skris
1174296465Sdelphij    attr_sect = NCONF_get_string(req_conf, SECTION, ATTRIBUTES);
1175296465Sdelphij    if (attr_sect == NULL) {
1176296465Sdelphij        ERR_clear_error();
1177296465Sdelphij        attr_sk = NULL;
1178296465Sdelphij    } else {
1179296465Sdelphij        attr_sk = NCONF_get_section(req_conf, attr_sect);
1180296465Sdelphij        if (attr_sk == NULL) {
1181296465Sdelphij            BIO_printf(bio_err, "unable to get '%s' section\n", attr_sect);
1182296465Sdelphij            goto err;
1183296465Sdelphij        }
1184296465Sdelphij    }
118555714Skris
1186296465Sdelphij    /* setup version number */
1187296465Sdelphij    if (!X509_REQ_set_version(req, 0L))
1188296465Sdelphij        goto err;               /* version 1 */
118955714Skris
1190296465Sdelphij    if (no_prompt)
1191296465Sdelphij        i = auto_info(req, dn_sk, attr_sk, attribs, chtype);
1192296465Sdelphij    else {
1193296465Sdelphij        if (subj)
1194296465Sdelphij            i = build_subject(req, subj, chtype, multirdn);
1195296465Sdelphij        else
1196296465Sdelphij            i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs,
1197296465Sdelphij                            chtype);
1198296465Sdelphij    }
1199296465Sdelphij    if (!i)
1200296465Sdelphij        goto err;
120159191Skris
1202296465Sdelphij    if (!X509_REQ_set_pubkey(req, pkey))
1203296465Sdelphij        goto err;
120459191Skris
1205296465Sdelphij    ret = 1;
1206296465Sdelphij err:
1207296465Sdelphij    return (ret);
1208296465Sdelphij}
120959191Skris
1210109998Smarkm/*
1211109998Smarkm * subject is expected to be in the format /type0=value0/type1=value1/type2=...
1212109998Smarkm * where characters may be escaped by \
1213109998Smarkm */
1214296465Sdelphijstatic int build_subject(X509_REQ *req, char *subject, unsigned long chtype,
1215296465Sdelphij                         int multirdn)
1216296465Sdelphij{
1217296465Sdelphij    X509_NAME *n;
121859191Skris
1219296465Sdelphij    if (!(n = parse_name(subject, chtype, multirdn)))
1220296465Sdelphij        return 0;
1221109998Smarkm
1222296465Sdelphij    if (!X509_REQ_set_subject_name(req, n)) {
1223296465Sdelphij        X509_NAME_free(n);
1224296465Sdelphij        return 0;
1225296465Sdelphij    }
1226296465Sdelphij    X509_NAME_free(n);
1227296465Sdelphij    return 1;
1228109998Smarkm}
1229109998Smarkm
123059191Skrisstatic int prompt_info(X509_REQ *req,
1231296465Sdelphij                       STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
1232296465Sdelphij                       STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect,
1233296465Sdelphij                       int attribs, unsigned long chtype)
1234296465Sdelphij{
1235296465Sdelphij    int i;
1236296465Sdelphij    char *p, *q;
1237296465Sdelphij    char buf[100];
1238296465Sdelphij    int nid, mval;
1239296465Sdelphij    long n_min, n_max;
1240296465Sdelphij    char *type, *value;
1241296465Sdelphij    const char *def;
1242296465Sdelphij    CONF_VALUE *v;
1243296465Sdelphij    X509_NAME *subj;
1244296465Sdelphij    subj = X509_REQ_get_subject_name(req);
124555714Skris
1246296465Sdelphij    if (!batch) {
1247296465Sdelphij        BIO_printf(bio_err,
1248296465Sdelphij                   "You are about to be asked to enter information that will be incorporated\n");
1249296465Sdelphij        BIO_printf(bio_err, "into your certificate request.\n");
1250296465Sdelphij        BIO_printf(bio_err,
1251296465Sdelphij                   "What you are about to enter is what is called a Distinguished Name or a DN.\n");
1252296465Sdelphij        BIO_printf(bio_err,
1253296465Sdelphij                   "There are quite a few fields but you can leave some blank\n");
1254296465Sdelphij        BIO_printf(bio_err,
1255296465Sdelphij                   "For some fields there will be a default value,\n");
1256296465Sdelphij        BIO_printf(bio_err,
1257296465Sdelphij                   "If you enter '.', the field will be left blank.\n");
1258296465Sdelphij        BIO_printf(bio_err, "-----\n");
1259296465Sdelphij    }
126055714Skris
1261296465Sdelphij    if (sk_CONF_VALUE_num(dn_sk)) {
1262296465Sdelphij        i = -1;
1263296465Sdelphij start:for (;;) {
1264296465Sdelphij            i++;
1265296465Sdelphij            if (sk_CONF_VALUE_num(dn_sk) <= i)
1266296465Sdelphij                break;
1267109998Smarkm
1268296465Sdelphij            v = sk_CONF_VALUE_value(dn_sk, i);
1269296465Sdelphij            p = q = NULL;
1270296465Sdelphij            type = v->name;
1271296465Sdelphij            if (!check_end(type, "_min") || !check_end(type, "_max") ||
1272296465Sdelphij                !check_end(type, "_default") || !check_end(type, "_value"))
1273296465Sdelphij                continue;
1274296465Sdelphij            /*
1275296465Sdelphij             * Skip past any leading X. X: X, etc to allow for multiple
1276296465Sdelphij             * instances
1277296465Sdelphij             */
1278296465Sdelphij            for (p = v->name; *p; p++)
1279296465Sdelphij                if ((*p == ':') || (*p == ',') || (*p == '.')) {
1280296465Sdelphij                    p++;
1281296465Sdelphij                    if (*p)
1282296465Sdelphij                        type = p;
1283296465Sdelphij                    break;
1284296465Sdelphij                }
1285296465Sdelphij            if (*type == '+') {
1286296465Sdelphij                mval = -1;
1287296465Sdelphij                type++;
1288296465Sdelphij            } else
1289296465Sdelphij                mval = 0;
1290296465Sdelphij            /* If OBJ not recognised ignore it */
1291296465Sdelphij            if ((nid = OBJ_txt2nid(type)) == NID_undef)
1292296465Sdelphij                goto start;
1293296465Sdelphij            if (BIO_snprintf(buf, sizeof buf, "%s_default", v->name)
1294296465Sdelphij                >= (int)sizeof(buf)) {
1295296465Sdelphij                BIO_printf(bio_err, "Name '%s' too long\n", v->name);
1296296465Sdelphij                return 0;
1297296465Sdelphij            }
129855714Skris
1299296465Sdelphij            if ((def = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
1300296465Sdelphij                ERR_clear_error();
1301296465Sdelphij                def = "";
1302296465Sdelphij            }
1303109998Smarkm
1304296465Sdelphij            BIO_snprintf(buf, sizeof buf, "%s_value", v->name);
1305296465Sdelphij            if ((value = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
1306296465Sdelphij                ERR_clear_error();
1307296465Sdelphij                value = NULL;
1308296465Sdelphij            }
130955714Skris
1310296465Sdelphij            BIO_snprintf(buf, sizeof buf, "%s_min", v->name);
1311296465Sdelphij            if (!NCONF_get_number(req_conf, dn_sect, buf, &n_min)) {
1312296465Sdelphij                ERR_clear_error();
1313296465Sdelphij                n_min = -1;
1314296465Sdelphij            }
131555714Skris
1316296465Sdelphij            BIO_snprintf(buf, sizeof buf, "%s_max", v->name);
1317296465Sdelphij            if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) {
1318296465Sdelphij                ERR_clear_error();
1319296465Sdelphij                n_max = -1;
1320296465Sdelphij            }
132155714Skris
1322296465Sdelphij            if (!add_DN_object(subj, v->value, def, value, nid,
1323296465Sdelphij                               n_min, n_max, chtype, mval))
1324296465Sdelphij                return 0;
1325296465Sdelphij        }
1326296465Sdelphij        if (X509_NAME_entry_count(subj) == 0) {
1327296465Sdelphij            BIO_printf(bio_err,
1328296465Sdelphij                       "error, no objects specified in config file\n");
1329296465Sdelphij            return 0;
1330296465Sdelphij        }
133155714Skris
1332296465Sdelphij        if (attribs) {
1333296465Sdelphij            if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0)
1334296465Sdelphij                && (!batch)) {
1335296465Sdelphij                BIO_printf(bio_err,
1336296465Sdelphij                           "\nPlease enter the following 'extra' attributes\n");
1337296465Sdelphij                BIO_printf(bio_err,
1338296465Sdelphij                           "to be sent with your certificate request\n");
1339296465Sdelphij            }
134055714Skris
1341296465Sdelphij            i = -1;
1342296465Sdelphij start2:   for (;;) {
1343296465Sdelphij                i++;
1344296465Sdelphij                if ((attr_sk == NULL) || (sk_CONF_VALUE_num(attr_sk) <= i))
1345296465Sdelphij                    break;
134655714Skris
1347296465Sdelphij                v = sk_CONF_VALUE_value(attr_sk, i);
1348296465Sdelphij                type = v->name;
1349296465Sdelphij                if ((nid = OBJ_txt2nid(type)) == NID_undef)
1350296465Sdelphij                    goto start2;
135155714Skris
1352296465Sdelphij                if (BIO_snprintf(buf, sizeof buf, "%s_default", type)
1353296465Sdelphij                    >= (int)sizeof(buf)) {
1354296465Sdelphij                    BIO_printf(bio_err, "Name '%s' too long\n", v->name);
1355296465Sdelphij                    return 0;
1356296465Sdelphij                }
1357109998Smarkm
1358296465Sdelphij                if ((def = NCONF_get_string(req_conf, attr_sect, buf))
1359296465Sdelphij                    == NULL) {
1360296465Sdelphij                    ERR_clear_error();
1361296465Sdelphij                    def = "";
1362296465Sdelphij                }
136355714Skris
1364296465Sdelphij                BIO_snprintf(buf, sizeof buf, "%s_value", type);
1365296465Sdelphij                if ((value = NCONF_get_string(req_conf, attr_sect, buf))
1366296465Sdelphij                    == NULL) {
1367296465Sdelphij                    ERR_clear_error();
1368296465Sdelphij                    value = NULL;
1369296465Sdelphij                }
137055714Skris
1371296465Sdelphij                BIO_snprintf(buf, sizeof buf, "%s_min", type);
1372296465Sdelphij                if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) {
1373296465Sdelphij                    ERR_clear_error();
1374296465Sdelphij                    n_min = -1;
1375296465Sdelphij                }
137655714Skris
1377296465Sdelphij                BIO_snprintf(buf, sizeof buf, "%s_max", type);
1378296465Sdelphij                if (!NCONF_get_number(req_conf, attr_sect, buf, &n_max)) {
1379296465Sdelphij                    ERR_clear_error();
1380296465Sdelphij                    n_max = -1;
1381296465Sdelphij                }
138255714Skris
1383296465Sdelphij                if (!add_attribute_object(req,
1384296465Sdelphij                                          v->value, def, value, nid, n_min,
1385296465Sdelphij                                          n_max, chtype))
1386296465Sdelphij                    return 0;
1387296465Sdelphij            }
1388296465Sdelphij        }
1389296465Sdelphij    } else {
1390296465Sdelphij        BIO_printf(bio_err, "No template, please set one up.\n");
1391296465Sdelphij        return 0;
1392296465Sdelphij    }
139355714Skris
1394296465Sdelphij    return 1;
139555714Skris
1396296465Sdelphij}
1397296465Sdelphij
139859191Skrisstatic int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk,
1399296465Sdelphij                     STACK_OF(CONF_VALUE) *attr_sk, int attribs,
1400296465Sdelphij                     unsigned long chtype)
1401296465Sdelphij{
1402296465Sdelphij    int i;
1403296465Sdelphij    char *p, *q;
1404296465Sdelphij    char *type;
1405296465Sdelphij    CONF_VALUE *v;
1406296465Sdelphij    X509_NAME *subj;
140759191Skris
1408296465Sdelphij    subj = X509_REQ_get_subject_name(req);
140959191Skris
1410296465Sdelphij    for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
1411296465Sdelphij        int mval;
1412296465Sdelphij        v = sk_CONF_VALUE_value(dn_sk, i);
1413296465Sdelphij        p = q = NULL;
1414296465Sdelphij        type = v->name;
1415296465Sdelphij        /*
1416296465Sdelphij         * Skip past any leading X. X: X, etc to allow for multiple instances
1417296465Sdelphij         */
1418296465Sdelphij        for (p = v->name; *p; p++)
141968651Skris#ifndef CHARSET_EBCDIC
1420296465Sdelphij            if ((*p == ':') || (*p == ',') || (*p == '.')) {
142168651Skris#else
1422296465Sdelphij            if ((*p == os_toascii[':']) || (*p == os_toascii[','])
1423296465Sdelphij                || (*p == os_toascii['.'])) {
142468651Skris#endif
1425296465Sdelphij                p++;
1426296465Sdelphij                if (*p)
1427296465Sdelphij                    type = p;
1428296465Sdelphij                break;
1429296465Sdelphij            }
1430160814Ssimon#ifndef CHARSET_EBCDIC
1431296465Sdelphij        if (*p == '+')
1432160814Ssimon#else
1433296465Sdelphij        if (*p == os_toascii['+'])
1434160814Ssimon#endif
1435296465Sdelphij        {
1436296465Sdelphij            p++;
1437296465Sdelphij            mval = -1;
1438296465Sdelphij        } else
1439296465Sdelphij            mval = 0;
1440296465Sdelphij        if (!X509_NAME_add_entry_by_txt(subj, type, chtype,
1441296465Sdelphij                                        (unsigned char *)v->value, -1, -1,
1442296465Sdelphij                                        mval))
1443296465Sdelphij            return 0;
144459191Skris
1445296465Sdelphij    }
144659191Skris
1447296465Sdelphij    if (!X509_NAME_entry_count(subj)) {
1448296465Sdelphij        BIO_printf(bio_err, "error, no objects specified in config file\n");
1449296465Sdelphij        return 0;
1450296465Sdelphij    }
1451296465Sdelphij    if (attribs) {
1452296465Sdelphij        for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) {
1453296465Sdelphij            v = sk_CONF_VALUE_value(attr_sk, i);
1454296465Sdelphij            if (!X509_REQ_add1_attr_by_txt(req, v->name, chtype,
1455296465Sdelphij                                           (unsigned char *)v->value, -1))
1456296465Sdelphij                return 0;
1457296465Sdelphij        }
1458296465Sdelphij    }
1459296465Sdelphij    return 1;
1460296465Sdelphij}
146159191Skris
1462296465Sdelphijstatic int add_DN_object(X509_NAME *n, char *text, const char *def,
1463296465Sdelphij                         char *value, int nid, int n_min, int n_max,
1464296465Sdelphij                         unsigned long chtype, int mval)
1465296465Sdelphij{
1466296465Sdelphij    int i, ret = 0;
1467296465Sdelphij    MS_STATIC char buf[1024];
1468296465Sdelphij start:
1469296465Sdelphij    if (!batch)
1470296465Sdelphij        BIO_printf(bio_err, "%s [%s]:", text, def);
1471296465Sdelphij    (void)BIO_flush(bio_err);
1472296465Sdelphij    if (value != NULL) {
1473296465Sdelphij        BUF_strlcpy(buf, value, sizeof buf);
1474296465Sdelphij        BUF_strlcat(buf, "\n", sizeof buf);
1475296465Sdelphij        BIO_printf(bio_err, "%s\n", value);
1476296465Sdelphij    } else {
1477296465Sdelphij        buf[0] = '\0';
1478296465Sdelphij        if (!batch) {
1479296465Sdelphij            if (!fgets(buf, sizeof buf, stdin))
1480296465Sdelphij                return 0;
1481296465Sdelphij        } else {
1482296465Sdelphij            buf[0] = '\n';
1483296465Sdelphij            buf[1] = '\0';
1484296465Sdelphij        }
1485296465Sdelphij    }
148659191Skris
1487296465Sdelphij    if (buf[0] == '\0')
1488296465Sdelphij        return (0);
1489296465Sdelphij    else if (buf[0] == '\n') {
1490296465Sdelphij        if ((def == NULL) || (def[0] == '\0'))
1491296465Sdelphij            return (1);
1492296465Sdelphij        BUF_strlcpy(buf, def, sizeof buf);
1493296465Sdelphij        BUF_strlcat(buf, "\n", sizeof buf);
1494296465Sdelphij    } else if ((buf[0] == '.') && (buf[1] == '\n'))
1495296465Sdelphij        return (1);
149655714Skris
1497296465Sdelphij    i = strlen(buf);
1498296465Sdelphij    if (buf[i - 1] != '\n') {
1499296465Sdelphij        BIO_printf(bio_err, "weird input :-(\n");
1500296465Sdelphij        return (0);
1501296465Sdelphij    }
1502296465Sdelphij    buf[--i] = '\0';
150355714Skris#ifdef CHARSET_EBCDIC
1504296465Sdelphij    ebcdic2ascii(buf, buf, i);
150555714Skris#endif
1506296465Sdelphij    if (!req_check_len(i, n_min, n_max)) {
1507296465Sdelphij        if (batch || value)
1508296465Sdelphij            return 0;
1509296465Sdelphij        goto start;
1510296465Sdelphij    }
1511267285Sjkim
1512296465Sdelphij    if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
1513296465Sdelphij                                    (unsigned char *)buf, -1, -1, mval))
1514296465Sdelphij        goto err;
1515296465Sdelphij    ret = 1;
1516296465Sdelphij err:
1517296465Sdelphij    return (ret);
1518296465Sdelphij}
151955714Skris
1520160814Ssimonstatic int add_attribute_object(X509_REQ *req, char *text, const char *def,
1521296465Sdelphij                                char *value, int nid, int n_min,
1522296465Sdelphij                                int n_max, unsigned long chtype)
1523296465Sdelphij{
1524296465Sdelphij    int i;
1525296465Sdelphij    static char buf[1024];
152655714Skris
1527296465Sdelphij start:
1528296465Sdelphij    if (!batch)
1529296465Sdelphij        BIO_printf(bio_err, "%s [%s]:", text, def);
1530296465Sdelphij    (void)BIO_flush(bio_err);
1531296465Sdelphij    if (value != NULL) {
1532296465Sdelphij        BUF_strlcpy(buf, value, sizeof buf);
1533296465Sdelphij        BUF_strlcat(buf, "\n", sizeof buf);
1534296465Sdelphij        BIO_printf(bio_err, "%s\n", value);
1535296465Sdelphij    } else {
1536296465Sdelphij        buf[0] = '\0';
1537296465Sdelphij        if (!batch) {
1538296465Sdelphij            if (!fgets(buf, sizeof buf, stdin))
1539296465Sdelphij                return 0;
1540296465Sdelphij        } else {
1541296465Sdelphij            buf[0] = '\n';
1542296465Sdelphij            buf[1] = '\0';
1543296465Sdelphij        }
1544296465Sdelphij    }
154555714Skris
1546296465Sdelphij    if (buf[0] == '\0')
1547296465Sdelphij        return (0);
1548296465Sdelphij    else if (buf[0] == '\n') {
1549296465Sdelphij        if ((def == NULL) || (def[0] == '\0'))
1550296465Sdelphij            return (1);
1551296465Sdelphij        BUF_strlcpy(buf, def, sizeof buf);
1552296465Sdelphij        BUF_strlcat(buf, "\n", sizeof buf);
1553296465Sdelphij    } else if ((buf[0] == '.') && (buf[1] == '\n'))
1554296465Sdelphij        return (1);
155555714Skris
1556296465Sdelphij    i = strlen(buf);
1557296465Sdelphij    if (buf[i - 1] != '\n') {
1558296465Sdelphij        BIO_printf(bio_err, "weird input :-(\n");
1559296465Sdelphij        return (0);
1560296465Sdelphij    }
1561296465Sdelphij    buf[--i] = '\0';
156268651Skris#ifdef CHARSET_EBCDIC
1563296465Sdelphij    ebcdic2ascii(buf, buf, i);
156468651Skris#endif
1565296465Sdelphij    if (!req_check_len(i, n_min, n_max)) {
1566296465Sdelphij        if (batch || value)
1567296465Sdelphij            return 0;
1568296465Sdelphij        goto start;
1569296465Sdelphij    }
157055714Skris
1571296465Sdelphij    if (!X509_REQ_add1_attr_by_NID(req, nid, chtype,
1572296465Sdelphij                                   (unsigned char *)buf, -1)) {
1573296465Sdelphij        BIO_printf(bio_err, "Error adding attribute\n");
1574296465Sdelphij        ERR_print_errors(bio_err);
1575296465Sdelphij        goto err;
1576296465Sdelphij    }
157755714Skris
1578296465Sdelphij    return (1);
1579296465Sdelphij err:
1580296465Sdelphij    return (0);
1581296465Sdelphij}
158255714Skris
1583109998Smarkm#ifndef OPENSSL_NO_RSA
1584160814Ssimonstatic int MS_CALLBACK req_cb(int p, int n, BN_GENCB *cb)
1585296465Sdelphij{
1586296465Sdelphij    char c = '*';
158755714Skris
1588296465Sdelphij    if (p == 0)
1589296465Sdelphij        c = '.';
1590296465Sdelphij    if (p == 1)
1591296465Sdelphij        c = '+';
1592296465Sdelphij    if (p == 2)
1593296465Sdelphij        c = '*';
1594296465Sdelphij    if (p == 3)
1595296465Sdelphij        c = '\n';
1596296465Sdelphij    BIO_write(cb->arg, &c, 1);
1597296465Sdelphij    (void)BIO_flush(cb->arg);
1598296465Sdelphij# ifdef LINT
1599296465Sdelphij    p = n;
1600296465Sdelphij# endif
1601296465Sdelphij    return 1;
1602296465Sdelphij}
160355714Skris#endif
160455714Skris
1605109998Smarkmstatic int req_check_len(int len, int n_min, int n_max)
1606296465Sdelphij{
1607296465Sdelphij    if ((n_min > 0) && (len < n_min)) {
1608296465Sdelphij        BIO_printf(bio_err,
1609296465Sdelphij                   "string is too short, it needs to be at least %d bytes long\n",
1610296465Sdelphij                   n_min);
1611296465Sdelphij        return (0);
1612296465Sdelphij    }
1613296465Sdelphij    if ((n_max >= 0) && (len > n_max)) {
1614296465Sdelphij        BIO_printf(bio_err,
1615296465Sdelphij                   "string is too long, it needs to be less than  %d bytes long\n",
1616296465Sdelphij                   n_max);
1617296465Sdelphij        return (0);
1618296465Sdelphij    }
1619296465Sdelphij    return (1);
1620296465Sdelphij}
162155714Skris
162255714Skris/* Check if the end of a string matches 'end' */
1623160814Ssimonstatic int check_end(const char *str, const char *end)
162455714Skris{
1625296465Sdelphij    int elen, slen;
1626296465Sdelphij    const char *tmp;
1627296465Sdelphij    elen = strlen(end);
1628296465Sdelphij    slen = strlen(str);
1629296465Sdelphij    if (elen > slen)
1630296465Sdelphij        return 1;
1631296465Sdelphij    tmp = str + slen - elen;
1632296465Sdelphij    return strcmp(tmp, end);
163355714Skris}
1634