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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
122
apps/verify.c
122
apps/verify.c
@@ -63,22 +63,29 @@
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/pem.h>
|
||||
|
||||
#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<argc; i++)
|
||||
check(cert_ctx,argv[i]);
|
||||
check(cert_ctx,argv[i], untrusted, purpose);
|
||||
ret=0;
|
||||
end:
|
||||
if (ret == 1)
|
||||
if (ret == 1) {
|
||||
BIO_printf(bio_err,"usage: verify [-verbose] [-CApath path] [-CAfile file] cert1 cert2 ...\n");
|
||||
BIO_printf(bio_err,"recognised usages:\n");
|
||||
for(i = 0; i < X509_PURPOSE_get_count(); i++) {
|
||||
X509_PURPOSE *ptmp;
|
||||
ptmp = X509_PURPOSE_iget(i);
|
||||
BIO_printf(bio_err, "\t%-10s\t%s\n", X509_PURPOSE_iget_sname(ptmp),
|
||||
X509_PURPOSE_iget_name(ptmp));
|
||||
}
|
||||
}
|
||||
if (cert_ctx != NULL) X509_STORE_free(cert_ctx);
|
||||
sk_X509_pop_free(untrusted, X509_free);
|
||||
X509V3_EXT_cleanup();
|
||||
X509_PURPOSE_cleanup();
|
||||
EXIT(ret);
|
||||
}
|
||||
|
||||
static int check(X509_STORE *ctx, char *file)
|
||||
static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain, int purpose)
|
||||
{
|
||||
X509 *x=NULL;
|
||||
BIO *in=NULL;
|
||||
int i=0,ret=0;
|
||||
X509_STORE_CTX csc;
|
||||
X509_STORE_CTX *csc;
|
||||
|
||||
in=BIO_new(BIO_s_file());
|
||||
if (in == NULL)
|
||||
@@ -193,9 +237,16 @@ static int check(X509_STORE *ctx, char *file)
|
||||
}
|
||||
fprintf(stdout,"%s: ",(file == NULL)?"stdin":file);
|
||||
|
||||
X509_STORE_CTX_init(&csc,ctx,x,NULL);
|
||||
i=X509_verify_cert(&csc);
|
||||
X509_STORE_CTX_cleanup(&csc);
|
||||
csc = X509_STORE_CTX_new();
|
||||
if (csc == NULL)
|
||||
{
|
||||
ERR_print_errors(bio_err);
|
||||
goto end;
|
||||
}
|
||||
X509_STORE_CTX_init(csc,ctx,x,uchain);
|
||||
if(purpose >= 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();
|
||||
|
||||
34
apps/x509.c
34
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user