New functions to check a hostname email or IP address against a
[openssl.git] / apps / x509.c
index 7f55cd1acb7a1249874bb89609846c6da0a86805..788eb7b3d0a94ae13b8624f478107874ced073c4 100644 (file)
@@ -157,9 +157,10 @@ static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx);
 static int sign (X509 *x, EVP_PKEY *pkey,int days,int clrext, const EVP_MD *digest,
                                                CONF *conf, char *section);
 static int x509_certify (X509_STORE *ctx,char *CAfile,const EVP_MD *digest,
-                        X509 *x,X509 *xca,EVP_PKEY *pkey,char *serial,
-                        int create,int days, int clrext, CONF *conf, char *section,
-                                               ASN1_INTEGER *sno);
+                        X509 *x,X509 *xca,EVP_PKEY *pkey,
+                        STACK_OF(OPENSSL_STRING) *sigopts,
+                        char *serial, int create ,int days, int clrext,
+                        CONF *conf, char *section, ASN1_INTEGER *sno);
 static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
 static int reqfile=0;
 
@@ -172,7 +173,8 @@ int MAIN(int argc, char **argv)
        X509_REQ *req=NULL;
        X509 *x=NULL,*xca=NULL;
        ASN1_OBJECT *objtmp;
-       EVP_PKEY *Upkey=NULL,*CApkey=NULL;
+       STACK_OF(OPENSSL_STRING) *sigopts = NULL;
+       EVP_PKEY *Upkey=NULL,*CApkey=NULL, *fkey = NULL;
        ASN1_INTEGER *sno = NULL;
        int i,num,badops=0;
        BIO *out=NULL;
@@ -181,6 +183,7 @@ int MAIN(int argc, char **argv)
        int informat,outformat,keyformat,CAformat,CAkeyformat;
        char *infile=NULL,*outfile=NULL,*keyfile=NULL,*CAfile=NULL;
        char *CAkeyfile=NULL,*CAserial=NULL;
+       char *fkeyfile=NULL;
        char *alias=NULL;
        int text=0,serial=0,subject=0,issuer=0,startdate=0,enddate=0;
        int next_serial=0;
@@ -205,6 +208,8 @@ int MAIN(int argc, char **argv)
        int need_rand = 0;
        int checkend=0,checkoffset=0;
        unsigned long nmflag = 0, certflag = 0;
+       unsigned char *checkhost = NULL, *checkemail = NULL;
+       char *checkip = NULL;
 #ifndef OPENSSL_NO_ENGINE
        char *engine=NULL;
 #endif
@@ -271,13 +276,22 @@ int MAIN(int argc, char **argv)
                        if (--argc < 1) goto bad;
                        CAkeyformat=str2fmt(*(++argv));
                        }
+               else if (strcmp(*argv,"-sigopt") == 0)
+                       {
+                       if (--argc < 1)
+                               goto bad;
+                       if (!sigopts)
+                               sigopts = sk_OPENSSL_STRING_new_null();
+                       if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
+                               goto bad;
+                       }
                else if (strcmp(*argv,"-days") == 0)
                        {
                        if (--argc < 1) goto bad;
                        days=atoi(*(++argv));
                        if (days == 0)
                                {
-                               BIO_printf(STDout,"bad number of days\n");
+                               BIO_printf(bio_err,"bad number of days\n");
                                goto bad;
                                }
                        }
@@ -336,6 +350,11 @@ int MAIN(int argc, char **argv)
                        if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv))))
                                goto bad;
                        }
+               else if (strcmp(*argv,"-force_pubkey") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       fkeyfile= *(++argv);
+                       }
                else if (strcmp(*argv,"-addtrust") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -439,6 +458,21 @@ int MAIN(int argc, char **argv)
                        checkoffset=atoi(*(++argv));
                        checkend=1;
                        }
+               else if (strcmp(*argv,"-checkhost") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       checkhost=(unsigned char *)*(++argv);
+                       }
+               else if (strcmp(*argv,"-checkemail") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       checkemail=(unsigned char *)*(++argv);
+                       }
+               else if (strcmp(*argv,"-checkip") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       checkip=*(++argv);
+                       }
                else if (strcmp(*argv,"-noout") == 0)
                        noout= ++num;
                else if (strcmp(*argv,"-trustout") == 0)
@@ -506,6 +540,13 @@ bad:
                goto end;
                }
 
+       if (fkeyfile)
+               {
+               fkey = load_pubkey(bio_err, fkeyfile, keyformat, 0,
+                                               NULL, e, "Forced key");
+               if (fkey == NULL) goto end;
+               }
+
        if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM))
                { CAkeyfile=CAfile; }
        else if ((CA_flag) && (CAkeyfile == NULL))
@@ -556,7 +597,6 @@ bad:
        if (reqfile)
                {
                EVP_PKEY *pkey;
-               X509_CINF *ci;
                BIO *in;
 
                if (!sign_flag && !CA_flag)
@@ -624,7 +664,6 @@ bad:
                print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag);
 
                if ((x=X509_new()) == NULL) goto end;
-               ci=x->cert_info;
 
                if (sno == NULL)
                        {
@@ -644,10 +683,14 @@ bad:
 
                X509_gmtime_adj(X509_get_notBefore(x),0);
                X509_time_adj_ex(X509_get_notAfter(x),days, 0, NULL);
-
-               pkey = X509_REQ_get_pubkey(req);
-               X509_set_pubkey(x,pkey);
-               EVP_PKEY_free(pkey);
+               if (fkey)
+                       X509_set_pubkey(x, fkey);
+               else
+                       {
+                       pkey = X509_REQ_get_pubkey(req);
+                       X509_set_pubkey(x,pkey);
+                       EVP_PKEY_free(pkey);
+                       }
                }
        else
                x=load_cert(bio_err,infile,informat,NULL,e,"Certificate");
@@ -903,8 +946,7 @@ bad:
                                }
                        else if (text == i)
                                {
-                               X509_print_ex(out,x,nmflag, certflag);
-ERR_print_errors_fp(stderr);
+                               X509_print_ex(STDout,x,nmflag, certflag);
                                }
                        else if (startdate == i)
                                {
@@ -973,7 +1015,8 @@ ERR_print_errors_fp(stderr);
                                
                                assert(need_rand);
                                if (!x509_certify(ctx,CAfile,digest,x,xca,
-                                       CApkey, CAserial,CA_createserial,days, clrext,
+                                       CApkey, sigopts,
+                                       CAserial,CA_createserial,days, clrext,
                                        extconf, extsect, sno))
                                        goto end;
                                }
@@ -990,7 +1033,7 @@ ERR_print_errors_fp(stderr);
                                else
                                        {
                                        pk=load_key(bio_err,
-                                               keyfile, FORMAT_PEM, 0,
+                                               keyfile, keyformat, 0,
                                                passin, e, "request key");
                                        if (pk == NULL) goto end;
                                        }
@@ -1035,6 +1078,8 @@ ERR_print_errors_fp(stderr);
                goto end;
                }
 
+       print_cert_checks(STDout, x, checkhost, checkemail, checkip);
+
        if (noout)
                {
                ret=0;
@@ -1084,6 +1129,9 @@ end:
        X509_free(xca);
        EVP_PKEY_free(Upkey);
        EVP_PKEY_free(CApkey);
+       EVP_PKEY_free(fkey);
+       if (sigopts)
+               sk_OPENSSL_STRING_free(sigopts);
        X509_REQ_free(rq);
        ASN1_INTEGER_free(sno);
        sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
@@ -1134,8 +1182,11 @@ static ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile, int create
        }
 
 static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
-            X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create,
-            int days, int clrext, CONF *conf, char *section, ASN1_INTEGER *sno)
+                       X509 *x, X509 *xca, EVP_PKEY *pkey,
+                       STACK_OF(OPENSSL_STRING) *sigopts,
+                       char *serialfile, int create,
+                       int days, int clrext, CONF *conf, char *section,
+                       ASN1_INTEGER *sno)
        {
        int ret=0;
        ASN1_INTEGER *bs=NULL;
@@ -1194,7 +1245,8 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
                 if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end;
                }
 
-       if (!X509_sign(x,pkey,digest)) goto end;
+       if (!do_X509_sign(bio_err, x, pkey, digest, sigopts))
+               goto end;
        ret=1;
 end:
        X509_STORE_CTX_cleanup(&xsc);