From d4cec6a13dfb2c1d1ddf66dff499aaf21bbbf002 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Fri, 26 Nov 1999 00:27:07 +0000 Subject: [PATCH] New options to the -verify program which can be used for chain verification. Extend the X509_PURPOSE structure to include shortnames for purposed and default trust ids. Still need some extendable trust checking code and integration with the SSL and S/MIME code. --- CHANGES | 16 +++-- apps/Makefile.ssl | 15 ++--- apps/pkcs12.c | 5 +- apps/verify.c | 122 +++++++++++++++++++++++++++++++++++---- apps/x509.c | 34 +++++------ crypto/asn1/t_x509a.c | 10 ++-- crypto/objects/obj_dat.h | 12 ++-- crypto/objects/objects.h | 5 ++ crypto/pem/pem.h | 2 +- crypto/pem/pem_all.c | 2 +- crypto/stack/stack.h | 4 +- crypto/x509/Makefile.ssl | 18 +++--- crypto/x509/x509.h | 29 ++++++++-- crypto/x509/x509_lu.c | 5 +- crypto/x509v3/v3_purp.c | 80 +++++++++++++++---------- crypto/x509v3/x509v3.h | 23 ++++++-- util/libeay.num | 16 ++++- 17 files changed, 288 insertions(+), 110 deletions(-) diff --git a/CHANGES b/CHANGES index 493f7e626b..5aaed4a82b 100644 --- a/CHANGES +++ b/CHANGES @@ -7,15 +7,21 @@ *) Very preliminary certificate chain verify code. Currently just tests the untrusted certificates for consistency with the verify purpose (which is set when the X509_STORE_CTX structure is set up) and checks - the pathlength. Totally untested at present: needs some extra - functionality in the verify program first. There is a - NO_CHAIN_VERIFY compilation option to keep the old behaviour: this is - because when it is finally working it will reject chains with - invalid extensions whereas before it made no checks at all. + the pathlength. There is a NO_CHAIN_VERIFY compilation option to keep + the old behaviour: this is because when it is finally working it will + reject chains with invalid extensions whereas before it made no checks + at all. + + Still needs some trust checking code. Also added X509_STORE_CTX_new() and X509_STORE_CTX_free() functions which should be used for version portability: especially since the verify structure is likely to change more often now. + + Two new options to the verify program: -untrusted allows a set of + untrusted certificates to be passed in and -purpose which sets the + intended purpose of the certificate. If a purpose is set then the + new chain verify code is used to check extension consistency. [Steve Henson] *) Support for the authority information access extension. diff --git a/apps/Makefile.ssl b/apps/Makefile.ssl index 747cd84609..439f50dcb5 100644 --- a/apps/Makefile.ssl +++ b/apps/Makefile.ssl @@ -727,11 +727,12 @@ spkac.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h apps.h progs.h verify.o: ../include/openssl/asn1.h ../include/openssl/bio.h verify.o: ../include/openssl/blowfish.h ../include/openssl/bn.h verify.o: ../include/openssl/buffer.h ../include/openssl/cast.h -verify.o: ../include/openssl/crypto.h ../include/openssl/des.h -verify.o: ../include/openssl/dh.h ../include/openssl/dsa.h -verify.o: ../include/openssl/e_os.h ../include/openssl/e_os2.h -verify.o: ../include/openssl/err.h ../include/openssl/evp.h -verify.o: ../include/openssl/idea.h ../include/openssl/md2.h +verify.o: ../include/openssl/conf.h ../include/openssl/crypto.h +verify.o: ../include/openssl/des.h ../include/openssl/dh.h +verify.o: ../include/openssl/dsa.h ../include/openssl/e_os.h +verify.o: ../include/openssl/e_os2.h ../include/openssl/err.h +verify.o: ../include/openssl/evp.h ../include/openssl/idea.h +verify.o: ../include/openssl/lhash.h ../include/openssl/md2.h verify.o: ../include/openssl/md5.h ../include/openssl/mdc2.h verify.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h verify.o: ../include/openssl/opensslv.h ../include/openssl/pem.h @@ -740,8 +741,8 @@ verify.o: ../include/openssl/rc2.h ../include/openssl/rc4.h verify.o: ../include/openssl/rc5.h ../include/openssl/ripemd.h verify.o: ../include/openssl/rsa.h ../include/openssl/safestack.h verify.o: ../include/openssl/sha.h ../include/openssl/stack.h -verify.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h apps.h -verify.o: progs.h +verify.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h +verify.o: ../include/openssl/x509v3.h apps.h progs.h version.o: ../include/openssl/asn1.h ../include/openssl/bio.h version.o: ../include/openssl/blowfish.h ../include/openssl/bn.h version.o: ../include/openssl/buffer.h ../include/openssl/cast.h diff --git a/apps/pkcs12.c b/apps/pkcs12.c index 5523622625..9fb290d7f5 100644 --- a/apps/pkcs12.c +++ b/apps/pkcs12.c @@ -287,13 +287,14 @@ int MAIN(int argc, char **argv) PKCS8_PRIV_KEY_INFO *p8; PKCS7 *authsafe; X509 *ucert = NULL; - STACK_OF(X509) *certs; + STACK_OF(X509) *certs=NULL; char *catmp; int i; unsigned char keyid[EVP_MAX_MD_SIZE]; unsigned int keyidlen = 0; key = PEM_read_bio_PrivateKey(inkey ? inkey : in, NULL, NULL, NULL); if (!inkey) (void) BIO_reset(in); + else BIO_free(inkey); if (!key) { BIO_printf (bio_err, "Error loading private key\n"); ERR_print_errors(bio_err); @@ -364,7 +365,7 @@ int MAIN(int argc, char **argv) PKCS12_add_friendlyname(bag, catmp, -1); sk_push(bags, (char *)bag); } - + sk_X509_pop_free(certs, X509_free); if (canames) sk_free(canames); if(!noprompt && diff --git a/apps/verify.c b/apps/verify.c index 4166b92fb4..579d4ea184 100644 --- a/apps/verify.c +++ b/apps/verify.c @@ -63,22 +63,29 @@ #include #include #include +#include #include #undef PROG #define PROG verify_main static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx); -static int check(X509_STORE *ctx,char *file); +static int check(X509_STORE *ctx,char *file, STACK_OF(X509)*other, int purpose); +static STACK_OF(X509) *load_untrusted(char *file); static int v_verbose=0; int MAIN(int argc, char **argv) { int i,ret=1; + int purpose = -1; char *CApath=NULL,*CAfile=NULL; + char *untfile = NULL; + STACK_OF(X509) *untrusted = NULL; X509_STORE *cert_ctx=NULL; X509_LOOKUP *lookup=NULL; + X509_PURPOSE_add_standard(); + X509V3_add_standard_extensions(); cert_ctx=X509_STORE_new(); if (cert_ctx == NULL) goto end; X509_STORE_set_verify_cb_func(cert_ctx,cb); @@ -107,6 +114,24 @@ int MAIN(int argc, char **argv) if (argc-- < 1) goto end; CAfile= *(++argv); } + else if (strcmp(*argv,"-purpose") == 0) + { + X509_PURPOSE *xptmp; + if (argc-- < 1) goto end; + i = X509_PURPOSE_get_by_sname(*(++argv)); + if(i < 0) + { + BIO_printf(bio_err, "unrecognised purpose\n"); + goto end; + } + xptmp = X509_PURPOSE_iget(i); + purpose = X509_PURPOSE_get_id(xptmp); + } + else if (strcmp(*argv,"-untrusted") == 0) + { + if (argc-- < 1) goto end; + untfile= *(++argv); + } else if (strcmp(*argv,"-help") == 0) goto end; else if (strcmp(*argv,"-verbose") == 0) @@ -144,26 +169,45 @@ int MAIN(int argc, char **argv) } } else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT); - ERR_clear_error(); - if (argc < 1) check(cert_ctx,NULL); + + if(untfile) { + if(!(untrusted = load_untrusted(untfile))) { + BIO_printf(bio_err, "Error loading untrusted file %s\n", untfile); + ERR_print_errors(bio_err); + goto end; + } + } + + if (argc < 1) check(cert_ctx, NULL, untrusted, purpose); else for (i=0; i= 0) X509_STORE_CTX_chain_purpose(csc, purpose); + i=X509_verify_cert(csc); + X509_STORE_CTX_free(csc); ret=0; end: @@ -212,6 +263,52 @@ end: return(ret); } +static STACK_OF(X509) *load_untrusted(char *certfile) +{ + STACK_OF(X509_INFO) *sk=NULL; + STACK_OF(X509) *stack=NULL, *ret=NULL; + BIO *in=NULL; + X509_INFO *xi; + + if(!(stack = sk_X509_new_null())) { + BIO_printf(bio_err,"memory allocation failure\n"); + goto end; + } + + if(!(in=BIO_new_file(certfile, "r"))) { + BIO_printf(bio_err,"error opening the file, %s\n",certfile); + goto end; + } + + /* This loads from a file, a stack of x509/crl/pkey sets */ + if(!(sk=PEM_X509_INFO_read_bio(in,NULL,NULL,NULL))) { + BIO_printf(bio_err,"error reading the file, %s\n",certfile); + goto end; + } + + /* scan over it and pull out the certs */ + while (sk_X509_INFO_num(sk)) + { + xi=sk_X509_INFO_shift(sk); + if (xi->x509 != NULL) + { + sk_X509_push(stack,xi->x509); + xi->x509=NULL; + } + X509_INFO_free(xi); + } + if(!sk_X509_num(stack)) { + BIO_printf(bio_err,"no certificates in file, %s\n",certfile); + sk_X509_free(stack); + goto end; + } + ret=stack; +end: + BIO_free(in); + sk_X509_INFO_free(sk); + return(ret); + } + static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx) { char buf[256]; @@ -230,6 +327,11 @@ static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx) * the user. */ if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1; + /* Continue after extension errors too */ + if (ctx->error == X509_V_ERR_INVALID_CA) ok=1; + if (ctx->error == X509_V_ERR_PATH_LENGTH_EXCEEDED) ok=1; + if (ctx->error == X509_V_ERR_INVALID_PURPOSE) ok=1; + if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1; } if (!v_verbose) ERR_clear_error(); diff --git a/apps/x509.c b/apps/x509.c index a6b5deb114..6469761f9e 100644 --- a/apps/x509.c +++ b/apps/x509.c @@ -136,14 +136,9 @@ static int sign (X509 *x, EVP_PKEY *pkey,int days,const EVP_MD *digest, 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, LHASH *conf, char *section); -static int efunc(X509_PURPOSE *pt, void *arg); +static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt); static int reqfile=0; -typedef struct { -BIO *bio; -X509 *cert; -} X509_PPRINT; - int MAIN(int argc, char **argv) { int ret=1; @@ -609,11 +604,14 @@ bad: } else if (pprint == i) { - X509_PPRINT ptmp; - ptmp.bio = STDout; - ptmp.cert = x; + X509_PURPOSE *ptmp; + int j; BIO_printf(STDout, "Certificate purposes:\n"); - X509_PURPOSE_enum(efunc, &ptmp); + for(j = 0; j < X509_PURPOSE_get_count(); j++) + { + ptmp = X509_PURPOSE_iget(j); + purpose_print(STDout, x, ptmp); + } } else if (modulus == i) @@ -1227,20 +1225,18 @@ err: return(0); } -static int efunc(X509_PURPOSE *pt, void *arg) +static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt) { - X509_PPRINT *ptmp; int id, i, idret; char *pname; - ptmp = arg; id = X509_PURPOSE_get_id(pt); - pname = X509_PURPOSE_get_name(pt); + pname = X509_PURPOSE_iget_name(pt); for(i = 0; i < 2; i++) { - idret = X509_check_purpose(ptmp->cert, id, i); - BIO_printf(ptmp->bio, "%s%s : ", pname, i ? " CA" : ""); - if(idret == 1) BIO_printf(ptmp->bio, "Yes\n"); - else if (idret == 0) BIO_printf(ptmp->bio, "No\n"); - else BIO_printf(ptmp->bio, "Yes (WARNING code=%d)\n", idret); + idret = X509_check_purpose(cert, id, i); + BIO_printf(bio, "%s%s : ", pname, i ? " CA" : ""); + if(idret == 1) BIO_printf(bio, "Yes\n"); + else if (idret == 0) BIO_printf(bio, "No\n"); + else BIO_printf(bio, "Yes (WARNING code=%d)\n", idret); } return 1; } diff --git a/crypto/asn1/t_x509a.c b/crypto/asn1/t_x509a.c index 26d03f5f9b..ebd62f6989 100644 --- a/crypto/asn1/t_x509a.c +++ b/crypto/asn1/t_x509a.c @@ -66,11 +66,11 @@ */ static BIT_STRING_BITNAME tbits[] = { -{X509_TRUST_ALL, "All Purposes", "all"}, -{X509_TRUST_SSL_CLIENT, "SSL client", "sslclient"}, -{X509_TRUST_SSL_SERVER, "SSL server", "sslserver"}, -{X509_TRUST_EMAIL, "S/MIME email", "email"}, -{X509_TRUST_OBJECT_SIGN, "Object Signing", "objsign"}, +{X509_TRUST_BIT_ALL, "All Purposes", "all"}, +{X509_TRUST_BIT_SSL_CLIENT, "SSL client", "sslclient"}, +{X509_TRUST_BIT_SSL_SERVER, "SSL server", "sslserver"}, +{X509_TRUST_BIT_EMAIL, "S/MIME email", "email"}, +{X509_TRUST_BIT_OBJECT_SIGN, "Object Signing", "objsign"}, {-1, NULL, NULL} }; diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h index 89b134ffd3..2272192500 100644 --- a/crypto/objects/obj_dat.h +++ b/crypto/objects/obj_dat.h @@ -61,12 +61,12 @@ * perl obj_dat.pl objects.h obj_dat.h */ -#define NUM_NID 180 +#define NUM_NID 181 #define NUM_SN 128 -#define NUM_LN 174 -#define NUM_OBJ 151 +#define NUM_LN 175 +#define NUM_OBJ 152 -static unsigned char lvalues[1049]={ +static unsigned char lvalues[1057]={ 0x00, /* [ 0] OBJ_undef */ 0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 1] OBJ_rsadsi */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 7] OBJ_pkcs */ @@ -218,6 +218,7 @@ static unsigned char lvalues[1049]={ 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01, /* [1024] OBJ_info_access */ 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01, /* [1032] OBJ_ad_OCSP */ 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02, /* [1040] OBJ_ad_ca_issuers */ +0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x09, /* [1048] OBJ_OCSP_sign */ }; static ASN1_OBJECT nid_objs[NUM_NID]={ @@ -471,6 +472,7 @@ static ASN1_OBJECT nid_objs[NUM_NID]={ 8,&(lvalues[1024]),0}, {"OCSP","OCSP",NID_ad_OCSP,8,&(lvalues[1032]),0}, {"caIssuers","CA Issuers",NID_ad_ca_issuers,8,&(lvalues[1040]),0}, +{"OCSP Signing","OCSP Signing",NID_OCSP_sign,8,&(lvalues[1048]),0}, }; static ASN1_OBJECT *sn_objs[NUM_SN]={ @@ -631,6 +633,7 @@ static ASN1_OBJECT *ln_objs[NUM_LN]={ &(nid_objs[73]),/* "Netscape Revocation Url" */ &(nid_objs[77]),/* "Netscape SSL Server Name" */ &(nid_objs[139]),/* "Netscape Server Gated Crypto" */ +&(nid_objs[180]),/* "OCSP Signing" */ &(nid_objs[178]),/* "OCSP" */ &(nid_objs[161]),/* "PBES2" */ &(nid_objs[69]),/* "PBKDF2" */ @@ -864,6 +867,7 @@ static ASN1_OBJECT *obj_objs[NUM_OBJ]={ &(nid_objs[131]),/* OBJ_code_sign 1 3 6 1 5 5 7 3 3 */ &(nid_objs[132]),/* OBJ_email_protect 1 3 6 1 5 5 7 3 4 */ &(nid_objs[133]),/* OBJ_time_stamp 1 3 6 1 5 5 7 3 8 */ +&(nid_objs[180]),/* OBJ_OCSP_sign 1 3 6 1 5 5 7 3 9 */ &(nid_objs[178]),/* OBJ_ad_OCSP 1 3 6 1 5 5 7 48 1 */ &(nid_objs[179]),/* OBJ_ad_ca_issuers 1 3 6 1 5 5 7 48 2 */ &(nid_objs[58]),/* OBJ_netscape_cert_extension 2 16 840 1 113730 1 */ diff --git a/crypto/objects/objects.h b/crypto/objects/objects.h index d7d1c533ab..ecdfd3e56b 100644 --- a/crypto/objects/objects.h +++ b/crypto/objects/objects.h @@ -935,6 +935,11 @@ extern "C" { #define NID_ad_ca_issuers 179 #define OBJ_ad_ca_issuers OBJ_id_ad,2L +#define SN_OSCP_sign "OCSPSigning" +#define LN_OCSP_sign "OCSP Signing" +#define NID_OCSP_sign 180 +#define OBJ_OCSP_sign OBJ_id_kp,9L + #include #include diff --git a/crypto/pem/pem.h b/crypto/pem/pem.h index 9260a11b8a..8ae1e9acc7 100644 --- a/crypto/pem/pem.h +++ b/crypto/pem/pem.h @@ -572,7 +572,7 @@ DECLARE_PEM_rw(DHparams, DH) DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY) -DECLARE_PEM_rw(PUBKEY, EVP_PKEY); +DECLARE_PEM_rw(PUBKEY, EVP_PKEY) int PEM_write_bio_PKCS8PrivateKey(BIO *, EVP_PKEY *, const EVP_CIPHER *, char *, int, pem_password_cb *, void *); diff --git a/crypto/pem/pem_all.c b/crypto/pem/pem_all.c index 93f5d7ba79..c6d8835bf9 100644 --- a/crypto/pem/pem_all.c +++ b/crypto/pem/pem_all.c @@ -194,4 +194,4 @@ IMPLEMENT_PEM_rw(DHparams, DH, PEM_STRING_DHPARAMS, DHparams) IMPLEMENT_PEM_read(PrivateKey, EVP_PKEY, PEM_STRING_EVP_PKEY, PrivateKey) IMPLEMENT_PEM_write_cb(PrivateKey, EVP_PKEY, ((x->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA), PrivateKey) -IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY); +IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY) diff --git a/crypto/stack/stack.h b/crypto/stack/stack.h index 0f825cc0c4..a615d9b4c9 100644 --- a/crypto/stack/stack.h +++ b/crypto/stack/stack.h @@ -76,8 +76,8 @@ typedef struct stack_st #define sk_new_null() sk_new(NULL) -#define M_sk_num(sk) ((sk)->num) -#define M_sk_value(sk,n) ((sk)->data[n]) +#define M_sk_num(sk) ((sk) ? (sk)->num:-1) +#define M_sk_value(sk,n) ((sk) ? (sk)->data[n] : NULL) int sk_num(STACK *); char *sk_value(STACK *, int); diff --git a/crypto/x509/Makefile.ssl b/crypto/x509/Makefile.ssl index 4fd06af15f..f29efbaf9a 100644 --- a/crypto/x509/Makefile.ssl +++ b/crypto/x509/Makefile.ssl @@ -332,21 +332,21 @@ x509_v3.o: ../cryptlib.h x509_vfy.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h x509_vfy.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h x509_vfy.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h -x509_vfy.o: ../../include/openssl/crypto.h ../../include/openssl/des.h -x509_vfy.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h -x509_vfy.o: ../../include/openssl/e_os.h ../../include/openssl/e_os2.h -x509_vfy.o: ../../include/openssl/err.h ../../include/openssl/evp.h -x509_vfy.o: ../../include/openssl/idea.h ../../include/openssl/lhash.h -x509_vfy.o: ../../include/openssl/md2.h ../../include/openssl/md5.h -x509_vfy.o: ../../include/openssl/mdc2.h ../../include/openssl/objects.h -x509_vfy.o: ../../include/openssl/opensslconf.h +x509_vfy.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h +x509_vfy.o: ../../include/openssl/des.h ../../include/openssl/dh.h +x509_vfy.o: ../../include/openssl/dsa.h ../../include/openssl/e_os.h +x509_vfy.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h +x509_vfy.o: ../../include/openssl/evp.h ../../include/openssl/idea.h +x509_vfy.o: ../../include/openssl/lhash.h ../../include/openssl/md2.h +x509_vfy.o: ../../include/openssl/md5.h ../../include/openssl/mdc2.h +x509_vfy.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h x509_vfy.o: ../../include/openssl/opensslv.h ../../include/openssl/pkcs7.h x509_vfy.o: ../../include/openssl/rc2.h ../../include/openssl/rc4.h x509_vfy.o: ../../include/openssl/rc5.h ../../include/openssl/ripemd.h x509_vfy.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h x509_vfy.o: ../../include/openssl/sha.h ../../include/openssl/stack.h x509_vfy.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h -x509_vfy.o: ../cryptlib.h +x509_vfy.o: ../../include/openssl/x509v3.h ../cryptlib.h x509name.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h x509name.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h x509name.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h index f35a61476f..ed08dfb74a 100644 --- a/crypto/x509/x509.h +++ b/crypto/x509/x509.h @@ -238,11 +238,12 @@ typedef struct x509_cinf_st /* Bit values for trust/notrust */ -#define X509_TRUST_ALL 0 -#define X509_TRUST_SSL_CLIENT 1 -#define X509_TRUST_SSL_SERVER 2 -#define X509_TRUST_EMAIL 3 -#define X509_TRUST_OBJECT_SIGN 4 +#define X509_TRUST_BIT_ALL 0 +#define X509_TRUST_BIT_SSL_CLIENT 1 +#define X509_TRUST_BIT_SSL_SERVER 2 +#define X509_TRUST_BIT_EMAIL 3 +#define X509_TRUST_BIT_OBJECT_SIGN 4 + typedef struct x509_cert_aux_st { @@ -276,6 +277,24 @@ typedef struct x509_st DECLARE_STACK_OF(X509) DECLARE_ASN1_SET_OF(X509) +/* This is used for a table of trust checking functions */ + +typedef struct x509_trust_st { + int trust_id; + int trust_flags; + int (*check_trust)(struct x509_trust_st *, X509 *, int); + char *trust_name; + int trust_bit; + void *usr_data; +} X509_TRUST; + +/* X509 trust ids */ + +#define X509_TRUST_ANY 1 +#define X509_TRUST_SSL_CLIENT 2 +#define X509_TRUST_SSL_SERVER 3 +#define X509_TRUST_EMAIL 4 + typedef struct X509_revoked_st { ASN1_INTEGER *serialNumber; diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c index 82e7fa50a7..837b81f154 100644 --- a/crypto/x509/x509_lu.c +++ b/crypto/x509/x509_lu.c @@ -383,7 +383,10 @@ X509_OBJECT *X509_OBJECT_retrieve_by_subject(LHASH *h, int type, X509_STORE_CTX *X509_STORE_CTX_new(void) { - return (X509_STORE_CTX *)Malloc(sizeof(X509_STORE_CTX)); + X509_STORE_CTX *ctx; + ctx = (X509_STORE_CTX *)Malloc(sizeof(X509_STORE_CTX)); + if(ctx) memset(ctx, 0, sizeof(X509_STORE_CTX)); + return ctx; } void X509_STORE_CTX_free(X509_STORE_CTX *ctx) diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c index 6ec5f957e9..13120ca516 100644 --- a/crypto/x509v3/v3_purp.c +++ b/crypto/x509v3/v3_purp.c @@ -61,7 +61,6 @@ #include -static int x509_purpose_get_idx(int id); static void x509v3_cache_extensions(X509 *x); static int ca_check(X509 *x); @@ -74,15 +73,16 @@ static int check_purpose_smime_encrypt(X509_PURPOSE *xp, X509 *x, int ca); static int check_purpose_crl_sign(X509_PURPOSE *xp, X509 *x, int ca); static int xp_cmp(X509_PURPOSE **a, X509_PURPOSE **b); +static void xptable_free(X509_PURPOSE *p); static X509_PURPOSE xstandard[] = { - {1, 0, check_purpose_ssl_client, "SSL client", /* NULL */}, - {2, 0, check_purpose_ssl_server, "SSL server", /* NULL */}, - {3, 0, check_purpose_ns_ssl_server, "Netscape SSL server", /* NULL */}, - {4, 0, check_purpose_smime_sign, "S/MIME signing", /* NULL */}, - {5, 0, check_purpose_smime_encrypt, "S/MIME encryption", /* NULL */}, - {6, 0, check_purpose_crl_sign, "CRL signing", /* NULL */}, - {-1, 0, NULL, NULL, /* NULL */} + {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0, check_purpose_ssl_client, "SSL client", "sslclient", NULL}, + {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ssl_server, "SSL server", "sslserver", NULL}, + {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ns_ssl_server, "Netscape SSL server", "nssslserver", NULL}, + {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign, "S/MIME signing", "smimesign", NULL}, + {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0, check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL}, + {X509_PURPOSE_CRL_SIGN, X509_TRUST_ANY, 0, check_purpose_crl_sign, "CRL signing", "crlsign", NULL}, + {-1, 0, 0, NULL, NULL, NULL, NULL} }; IMPLEMENT_STACK_OF(X509_PURPOSE) @@ -104,16 +104,35 @@ int X509_check_purpose(X509 *x, int id, int ca) CRYPTO_w_unlock(CRYPTO_LOCK_X509); } if(id == -1) return 1; - idx = x509_purpose_get_idx(id); + idx = X509_PURPOSE_get_by_id(id); if(idx == -1) return -1; pt = sk_X509_PURPOSE_value(xptable, idx); return pt->check_purpose(pt, x,ca); } +int X509_PURPOSE_get_count(void) +{ + return sk_X509_PURPOSE_num(xptable); +} +X509_PURPOSE * X509_PURPOSE_iget(int idx) +{ + return sk_X509_PURPOSE_value(xptable, idx); +} + +int X509_PURPOSE_get_by_sname(char *sname) +{ + int i; + X509_PURPOSE *xptmp; + for(i = 0; i < sk_X509_PURPOSE_num(xptable); i++) { + xptmp = sk_X509_PURPOSE_value(xptable, i); + if(!strcmp(xptmp->purpose_sname, sname)) return i; + } + return -1; +} -static int x509_purpose_get_idx(int id) +int X509_PURPOSE_get_by_id(int id) { X509_PURPOSE tmp; tmp.purpose_id = id; @@ -134,24 +153,28 @@ int X509_PURPOSE_add(X509_PURPOSE *xp) } } - idx = x509_purpose_get_idx(xp->purpose_id); - if(idx != -1) + idx = X509_PURPOSE_get_by_id(xp->purpose_id); + if(idx != -1) { + xptable_free(sk_X509_PURPOSE_value(xptable, idx)); sk_X509_PURPOSE_set(xptable, idx, xp); - else - if (!sk_X509_PURPOSE_push(xptable, xp)) - { + } else { + if (!sk_X509_PURPOSE_push(xptable, xp)) { X509V3err(X509V3_F_X509_PURPOSE_ADD,ERR_R_MALLOC_FAILURE); return 0; - } + } + } return 1; } static void xptable_free(X509_PURPOSE *p) { + if(!p) return; if (p->purpose_flags & X509_PURPOSE_DYNAMIC) { - if (p->purpose_flags & X509_PURPOSE_DYNAMIC_NAME) + if (p->purpose_flags & X509_PURPOSE_DYNAMIC_NAME) { Free(p->purpose_name); + Free(p->purpose_sname); + } Free(p); } } @@ -169,27 +192,24 @@ void X509_PURPOSE_add_standard(void) X509_PURPOSE_add(xp); } -int X509_PURPOSE_enum(int (*efunc)(X509_PURPOSE *, void *), void *usr) +int X509_PURPOSE_get_id(X509_PURPOSE *xp) { - int i; - X509_PURPOSE *xp; - if(!xptable) return 0; - for(i = 0; i < sk_X509_PURPOSE_num(xptable); i++) { - xp = sk_X509_PURPOSE_value(xptable, i); - if(!efunc(xp, usr)) return i; - } - return i; + return xp->purpose_id; } +char *X509_PURPOSE_iget_name(X509_PURPOSE *xp) +{ + return xp->purpose_name; +} -int X509_PURPOSE_get_id(X509_PURPOSE *xp) +char *X509_PURPOSE_iget_sname(X509_PURPOSE *xp) { - return xp->purpose_id; + return xp->purpose_sname; } -char *X509_PURPOSE_get_name(X509_PURPOSE *xp) +int X509_PURPOSE_get_trust(X509_PURPOSE *xp) { - return xp->purpose_name; + return xp->trust_id; } static void x509v3_cache_extensions(X509 *x) diff --git a/crypto/x509v3/x509v3.h b/crypto/x509v3/x509v3.h index 988cdb8d95..5a97e09612 100644 --- a/crypto/x509v3/x509v3.h +++ b/crypto/x509v3/x509v3.h @@ -330,16 +330,22 @@ DECLARE_ASN1_SET_OF(POLICYINFO) typedef struct x509_purpose_st { int purpose_id; + int trust_id; /* Default trust ID */ int purpose_flags; int (*check_purpose)(struct x509_purpose_st *, X509 *, int); char *purpose_name; - /* void *usr_data; */ /* if we enable this it needs a free function */ + char *purpose_sname; + void *usr_data; } X509_PURPOSE; -DECLARE_STACK_OF(X509_PURPOSE) - - +#define X509_PURPOSE_SSL_CLIENT 1 +#define X509_PURPOSE_SSL_SERVER 2 +#define X509_PURPOSE_NS_SSL_SERVER 3 +#define X509_PURPOSE_SMIME_SIGN 4 +#define X509_PURPOSE_SMIME_ENCRYPT 5 +#define X509_PURPOSE_CRL_SIGN 6 +DECLARE_STACK_OF(X509_PURPOSE) void ERR_load_X509V3_strings(void); int i2d_BASIC_CONSTRAINTS(BASIC_CONSTRAINTS *a, unsigned char **pp); @@ -522,12 +528,17 @@ int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, int flag, int indent); int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent); int X509_check_purpose(X509 *x, int id, int ca); +int X509_PURPOSE_get_count(void); +X509_PURPOSE * X509_PURPOSE_iget(int idx); +int X509_PURPOSE_get_by_sname(char *sname); +int X509_PURPOSE_get_by_id(int id); int X509_PURPOSE_add(X509_PURPOSE *xp); +char *X509_PURPOSE_iget_name(X509_PURPOSE *xp); +char *X509_PURPOSE_iget_sname(X509_PURPOSE *xp); +int X509_PURPOSE_get_trust(X509_PURPOSE *xp); void X509_PURPOSE_cleanup(void); void X509_PURPOSE_add_standard(void); -int X509_PURPOSE_enum(int (*efunc)(X509_PURPOSE *, void *), void *usr); int X509_PURPOSE_get_id(X509_PURPOSE *); -char * X509_PURPOSE_get_name(X509_PURPOSE *); /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes diff --git a/util/libeay.num b/util/libeay.num index 399165d0bf..811f6ec10e 100755 --- a/util/libeay.num +++ b/util/libeay.num @@ -1914,7 +1914,7 @@ ASN1_UTCTIME_free 1938 DSA_set_default_method 1939 sk_X509_PURPOSE_set_cmp_func 1940 PEM_write_bio_DSA_PUBKEY 1941 -X509_PURPOSE_get_id 1942 +X509_PURPOSE_get_by_id 1942 DISPLAYTEXT_free 1943 X509V3_CRL_get_d2i 1944 ASN1_OCTET_STRING_free 1945 @@ -1937,12 +1937,12 @@ ASN1_T61STRING_new 1961 ASN1_UTCTIME_new 1962 ASN1_IA5STRING_free 1963 ASN1_STRING_data 1964 -X509_PURPOSE_get_name 1965 +X509_PURPOSE_iget_name 1965 sk_X509_PURPOSE_delete_ptr 1966 ASN1_BIT_STRING_free 1967 X509_PURPOSE_add 1968 ASN1_UTF8STRING_free 1969 -X509_PURPOSE_enum 1970 +X509_PURPOSE_get 1970 sk_X509_PURPOSE_pop_free 1971 i2d_DSA_PUBKEY_fp 1972 sk_X509_PURPOSE_free 1973 @@ -2076,3 +2076,13 @@ sk_ACCESS_DESCRIPTION_delete_ptr 2100 sk_ACCESS_DESCRIPTION_insert 2101 sk_ACCESS_DESCRIPTION_sort 2102 sk_ACCESS_DESCRIPTION_set_cmp_func 2103 +X509_STORE_CTX_chain_purpose 2104 +X509_STORE_CTX_free 2105 +X509_STORE_CTX_trust_purpose 2106 +X509_STORE_CTX_new 2107 +X509_PURPOSE_iget 2108 +X509_PURPOSE_get_by_sname 2109 +X509_PURPOSE_get_id 2110 +X509_PURPOSE_get_trust 2111 +X509_PURPOSE_get_count 2112 +X509_PURPOSE_iget_sname 2113 -- 2.34.1