mirror of https://github.com/openssl/openssl.git
				
				
				
			Add trust setting support to the verify code. It now checks the
trust settings of the root CA. After a few fixes it seems to work OK. Still need to add support to SSL and S/MIME code though.
This commit is contained in:
		
							parent
							
								
									74ecf9e2bb
								
							
						
					
					
						commit
						51630a3706
					
				
							
								
								
									
										22
									
								
								CHANGES
								
								
								
								
							
							
						
						
									
										22
									
								
								CHANGES
								
								
								
								
							|  | @ -12,15 +12,21 @@ | ||||||
|      DSA key was used because it didn't fix the digest. |      DSA key was used because it didn't fix the digest. | ||||||
|      [Steve Henson] |      [Steve Henson] | ||||||
| 
 | 
 | ||||||
|   *) Very preliminary certificate chain verify code. Currently just tests |   *) Initial certificate chain verify code. Currently tests the untrusted | ||||||
|      the untrusted certificates for consistency with the verify purpose |      certificates for consistency with the verify purpose (which is set | ||||||
|      (which is set when the X509_STORE_CTX structure is set up) and checks |      when the X509_STORE_CTX structure is set up) and checks the pathlength. | ||||||
|      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. |  | ||||||
| 
 | 
 | ||||||
|      Preliminary untested trust code.  |      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 every previous version of OpenSSL and SSLeay | ||||||
|  |      made no checks at all. | ||||||
|  | 
 | ||||||
|  |      Trust code: checks the root CA for the relevant trust settings. Trust | ||||||
|  |      settings have an initial value consistent with the verify purpose: e.g. | ||||||
|  |      if the verify purpose is for SSL client use it expects the CA to be | ||||||
|  |      trusted for SSL client use. However the default value can be changed to | ||||||
|  |      permit custom trust settings: one example of this would be to only trust | ||||||
|  |      certificates from a specific "secure" set of CAs. | ||||||
| 
 | 
 | ||||||
|      Also added X509_STORE_CTX_new() and X509_STORE_CTX_free() functions |      Also added X509_STORE_CTX_new() and X509_STORE_CTX_free() functions | ||||||
|      which should be used for version portability: especially since the |      which should be used for version portability: especially since the | ||||||
|  |  | ||||||
|  | @ -85,6 +85,7 @@ int MAIN(int argc, char **argv) | ||||||
| 	X509_LOOKUP *lookup=NULL; | 	X509_LOOKUP *lookup=NULL; | ||||||
| 
 | 
 | ||||||
| 	X509_PURPOSE_add_standard(); | 	X509_PURPOSE_add_standard(); | ||||||
|  | 	X509_TRUST_add_standard(); | ||||||
| 	X509V3_add_standard_extensions(); | 	X509V3_add_standard_extensions(); | ||||||
| 	cert_ctx=X509_STORE_new(); | 	cert_ctx=X509_STORE_new(); | ||||||
| 	if (cert_ctx == NULL) goto end; | 	if (cert_ctx == NULL) goto end; | ||||||
|  | @ -199,6 +200,7 @@ end: | ||||||
| 	sk_X509_pop_free(untrusted, X509_free); | 	sk_X509_pop_free(untrusted, X509_free); | ||||||
| 	X509V3_EXT_cleanup(); | 	X509V3_EXT_cleanup(); | ||||||
| 	X509_PURPOSE_cleanup(); | 	X509_PURPOSE_cleanup(); | ||||||
|  | 	X509_TRUST_cleanup(); | ||||||
| 	EXIT(ret); | 	EXIT(ret); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -99,13 +99,13 @@ int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent) | ||||||
| 	int i; | 	int i; | ||||||
| 	if(!aux) return 1; | 	if(!aux) return 1; | ||||||
| 	if(aux->trust) { | 	if(aux->trust) { | ||||||
| 		BIO_printf(out, "%*sTrusted for:\n", indent, ""); | 		BIO_printf(out, "%*sTrusted Uses:\n", indent, ""); | ||||||
| 		ASN1_BIT_STRING_name_print(out, aux->trust, tbits, indent + 2); | 		ASN1_BIT_STRING_name_print(out, aux->trust, tbits, indent + 2); | ||||||
| 	} else BIO_printf(out, "%*sNo Trust Settings\n", indent + 2, ""); | 	} else BIO_printf(out, "%*sNo Trusted Uses.\n", indent, ""); | ||||||
| 	if(aux->reject) { | 	if(aux->reject) { | ||||||
| 		BIO_printf(out, "%*sUntrusted for:\n", indent, ""); | 		BIO_printf(out, "%*sRejected Uses:\n", indent, ""); | ||||||
| 		ASN1_BIT_STRING_name_print(out, aux->reject, tbits, indent + 2); | 		ASN1_BIT_STRING_name_print(out, aux->reject, tbits, indent + 2); | ||||||
| 	} else BIO_printf(out, "%*sNo Untrusted Settings\n", indent + 2, ""); | 	} else BIO_printf(out, "%*sNo Rejected Uses.\n", indent, ""); | ||||||
| 	if(aux->othertrust) { | 	if(aux->othertrust) { | ||||||
| 		first = 1; | 		first = 1; | ||||||
| 		BIO_printf(out, "%*sOther Trusted Uses:\n%*s", | 		BIO_printf(out, "%*sOther Trusted Uses:\n%*s", | ||||||
|  | @ -121,7 +121,7 @@ int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent) | ||||||
| 	} | 	} | ||||||
| 	if(aux->otherreject) { | 	if(aux->otherreject) { | ||||||
| 		first = 1; | 		first = 1; | ||||||
| 		BIO_printf(out, "%*sOther Untrusted Uses:\n%*s", | 		BIO_printf(out, "%*sOther Rejected Uses:\n%*s", | ||||||
| 						indent, "", indent + 2, ""); | 						indent, "", indent + 2, ""); | ||||||
| 		for(i = 0; i < sk_ASN1_OBJECT_num(aux->otherreject); i++) { | 		for(i = 0; i < sk_ASN1_OBJECT_num(aux->otherreject); i++) { | ||||||
| 			if(!first) BIO_puts(out, ", "); | 			if(!first) BIO_puts(out, ", "); | ||||||
|  |  | ||||||
|  | @ -1098,6 +1098,7 @@ int X509_TRUST_get_trust(X509_TRUST *xp); | ||||||
| #define X509_F_X509_REQ_PRINT				 121 | #define X509_F_X509_REQ_PRINT				 121 | ||||||
| #define X509_F_X509_REQ_PRINT_FP			 122 | #define X509_F_X509_REQ_PRINT_FP			 122 | ||||||
| #define X509_F_X509_REQ_TO_X509				 123 | #define X509_F_X509_REQ_TO_X509				 123 | ||||||
|  | #define X509_F_X509_SET_PURPOSE_AND_TRUST		 134 | ||||||
| #define X509_F_X509_STORE_ADD_CERT			 124 | #define X509_F_X509_STORE_ADD_CERT			 124 | ||||||
| #define X509_F_X509_STORE_ADD_CRL			 125 | #define X509_F_X509_STORE_ADD_CRL			 125 | ||||||
| #define X509_F_X509_TO_X509_REQ				 126 | #define X509_F_X509_TO_X509_REQ				 126 | ||||||
|  | @ -1122,6 +1123,7 @@ int X509_TRUST_get_trust(X509_TRUST *xp); | ||||||
| #define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY		 108 | #define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY		 108 | ||||||
| #define X509_R_UNKNOWN_KEY_TYPE				 117 | #define X509_R_UNKNOWN_KEY_TYPE				 117 | ||||||
| #define X509_R_UNKNOWN_NID				 109 | #define X509_R_UNKNOWN_NID				 109 | ||||||
|  | #define X509_R_UNKNOWN_TRUST_ID				 120 | ||||||
| #define X509_R_UNSUPPORTED_ALGORITHM			 111 | #define X509_R_UNSUPPORTED_ALGORITHM			 111 | ||||||
| #define X509_R_WRONG_LOOKUP_TYPE			 112 | #define X509_R_WRONG_LOOKUP_TYPE			 112 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -91,10 +91,11 @@ static ERR_STRING_DATA X509_str_functs[]= | ||||||
| {ERR_PACK(0,X509_F_X509_REQ_PRINT,0),	"X509_REQ_print"}, | {ERR_PACK(0,X509_F_X509_REQ_PRINT,0),	"X509_REQ_print"}, | ||||||
| {ERR_PACK(0,X509_F_X509_REQ_PRINT_FP,0),	"X509_REQ_print_fp"}, | {ERR_PACK(0,X509_F_X509_REQ_PRINT_FP,0),	"X509_REQ_print_fp"}, | ||||||
| {ERR_PACK(0,X509_F_X509_REQ_TO_X509,0),	"X509_REQ_to_X509"}, | {ERR_PACK(0,X509_F_X509_REQ_TO_X509,0),	"X509_REQ_to_X509"}, | ||||||
|  | {ERR_PACK(0,X509_F_X509_SET_PURPOSE_AND_TRUST,0),	"X509_set_purpose_and_trust"}, | ||||||
| {ERR_PACK(0,X509_F_X509_STORE_ADD_CERT,0),	"X509_STORE_add_cert"}, | {ERR_PACK(0,X509_F_X509_STORE_ADD_CERT,0),	"X509_STORE_add_cert"}, | ||||||
| {ERR_PACK(0,X509_F_X509_STORE_ADD_CRL,0),	"X509_STORE_add_crl"}, | {ERR_PACK(0,X509_F_X509_STORE_ADD_CRL,0),	"X509_STORE_add_crl"}, | ||||||
| {ERR_PACK(0,X509_F_X509_TO_X509_REQ,0),	"X509_to_X509_REQ"}, | {ERR_PACK(0,X509_F_X509_TO_X509_REQ,0),	"X509_to_X509_REQ"}, | ||||||
| {ERR_PACK(0,X509_F_X509_TRUST_ADD,0),	"X509_TRUST_ADD"}, | {ERR_PACK(0,X509_F_X509_TRUST_ADD,0),	"X509_TRUST_add"}, | ||||||
| {ERR_PACK(0,X509_F_X509_VERIFY_CERT,0),	"X509_verify_cert"}, | {ERR_PACK(0,X509_F_X509_VERIFY_CERT,0),	"X509_verify_cert"}, | ||||||
| {0,NULL} | {0,NULL} | ||||||
| 	}; | 	}; | ||||||
|  | @ -118,6 +119,7 @@ static ERR_STRING_DATA X509_str_reasons[]= | ||||||
| {X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY   ,"unable to get certs public key"}, | {X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY   ,"unable to get certs public key"}, | ||||||
| {X509_R_UNKNOWN_KEY_TYPE                 ,"unknown key type"}, | {X509_R_UNKNOWN_KEY_TYPE                 ,"unknown key type"}, | ||||||
| {X509_R_UNKNOWN_NID                      ,"unknown nid"}, | {X509_R_UNKNOWN_NID                      ,"unknown nid"}, | ||||||
|  | {X509_R_UNKNOWN_TRUST_ID                 ,"unknown trust id"}, | ||||||
| {X509_R_UNSUPPORTED_ALGORITHM            ,"unsupported algorithm"}, | {X509_R_UNSUPPORTED_ALGORITHM            ,"unsupported algorithm"}, | ||||||
| {X509_R_WRONG_LOOKUP_TYPE                ,"wrong lookup type"}, | {X509_R_WRONG_LOOKUP_TYPE                ,"wrong lookup type"}, | ||||||
| {0,NULL} | {0,NULL} | ||||||
|  |  | ||||||
|  | @ -126,6 +126,10 @@ const char *X509_verify_cert_error_string(long n) | ||||||
| 		return ("path length constraint exceeded"); | 		return ("path length constraint exceeded"); | ||||||
| 	case X509_V_ERR_INVALID_PURPOSE: | 	case X509_V_ERR_INVALID_PURPOSE: | ||||||
| 		return ("unsupported certificate purpose"); | 		return ("unsupported certificate purpose"); | ||||||
|  | 	case X509_V_ERR_CERT_UNTRUSTED: | ||||||
|  | 		return ("certificate not trusted"); | ||||||
|  | 	case X509_V_ERR_CERT_REJECTED: | ||||||
|  | 		return ("certificate rejected"); | ||||||
| 	case X509_V_ERR_APPLICATION_VERIFICATION: | 	case X509_V_ERR_APPLICATION_VERIFICATION: | ||||||
| 		return("application verification failure"); | 		return("application verification failure"); | ||||||
| 	default: | 	default: | ||||||
|  |  | ||||||
|  | @ -72,6 +72,7 @@ | ||||||
| 
 | 
 | ||||||
| static int null_callback(int ok,X509_STORE_CTX *e); | static int null_callback(int ok,X509_STORE_CTX *e); | ||||||
| static int check_chain_purpose(X509_STORE_CTX *ctx); | static int check_chain_purpose(X509_STORE_CTX *ctx); | ||||||
|  | static int check_trust(X509_STORE_CTX *ctx); | ||||||
| static int internal_verify(X509_STORE_CTX *ctx); | static int internal_verify(X509_STORE_CTX *ctx); | ||||||
| const char *X509_version="X.509" OPENSSL_VERSION_PTEXT; | const char *X509_version="X.509" OPENSSL_VERSION_PTEXT; | ||||||
| 
 | 
 | ||||||
|  | @ -297,6 +298,12 @@ int X509_verify_cert(X509_STORE_CTX *ctx) | ||||||
| 
 | 
 | ||||||
| 	if(!ok) goto end; | 	if(!ok) goto end; | ||||||
| 
 | 
 | ||||||
|  | 	/* The chain extensions are OK: check trust */ | ||||||
|  | 
 | ||||||
|  | 	if(ctx->trust_purpose > 0) ok = check_trust(ctx); | ||||||
|  | 
 | ||||||
|  | 	if(!ok) goto end; | ||||||
|  | 
 | ||||||
| 	/* We may as well copy down any DSA parameters that are required */ | 	/* We may as well copy down any DSA parameters that are required */ | ||||||
| 	X509_get_pubkey_parameters(NULL,ctx->chain); | 	X509_get_pubkey_parameters(NULL,ctx->chain); | ||||||
| 
 | 
 | ||||||
|  | @ -356,6 +363,30 @@ static int check_chain_purpose(X509_STORE_CTX *ctx) | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int check_trust(X509_STORE_CTX *ctx) | ||||||
|  | { | ||||||
|  | #ifdef NO_CHAIN_VERIFY | ||||||
|  | 	return 1; | ||||||
|  | #else | ||||||
|  | 	int i, ok; | ||||||
|  | 	X509 *x; | ||||||
|  | 	int (*cb)(); | ||||||
|  | 	cb=ctx->ctx->verify_cb; | ||||||
|  | 	if (cb == NULL) cb=null_callback; | ||||||
|  | /* For now just check the last certificate in the chain */ | ||||||
|  | 	i = sk_X509_num(ctx->chain) - 1; | ||||||
|  | 	x = sk_X509_value(ctx->chain, i); | ||||||
|  | 	ok = X509_check_trust(x, ctx->trust_purpose, 0); | ||||||
|  | 	if(ok == X509_TRUST_TRUSTED) return 1; | ||||||
|  | 	ctx->error_depth = sk_X509_num(ctx->chain) - 1; | ||||||
|  | 	ctx->current_cert = x; | ||||||
|  | 	if(ok == X509_TRUST_REJECTED) ctx->error = X509_V_ERR_CERT_REJECTED; | ||||||
|  | 	else ctx->error = X509_V_ERR_CERT_UNTRUSTED; | ||||||
|  | 	ok = cb(0, ctx); | ||||||
|  | 	return(ok); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int internal_verify(X509_STORE_CTX *ctx) | static int internal_verify(X509_STORE_CTX *ctx) | ||||||
| 	{ | 	{ | ||||||
| 	int i,ok=0,n; | 	int i,ok=0,n; | ||||||
|  | @ -696,9 +727,10 @@ void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) | ||||||
| 	ctx->untrusted=sk; | 	ctx->untrusted=sk; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| void X509_STORE_CTX_chain_purpose(X509_STORE_CTX *ctx, int purpose) | int X509_STORE_CTX_chain_purpose(X509_STORE_CTX *ctx, int purpose) | ||||||
| 	{ | 	{ | ||||||
| 	ctx->chain_purpose = purpose; | 		return X509_set_purpose_and_trust(purpose, | ||||||
|  | 				&ctx->chain_purpose, &ctx->trust_purpose); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| void X509_STORE_CTX_trust_purpose(X509_STORE_CTX *ctx, int purpose) | void X509_STORE_CTX_trust_purpose(X509_STORE_CTX *ctx, int purpose) | ||||||
|  | @ -706,6 +738,22 @@ void X509_STORE_CTX_trust_purpose(X509_STORE_CTX *ctx, int purpose) | ||||||
| 	ctx->trust_purpose = purpose; | 	ctx->trust_purpose = purpose; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | int X509_set_purpose_and_trust(int id, int *purp, int *trust) | ||||||
|  | { | ||||||
|  | 	X509_PURPOSE *ptmp; | ||||||
|  | 	int idx; | ||||||
|  | 	idx = X509_PURPOSE_get_by_id(id); | ||||||
|  | 	if(idx == -1) { | ||||||
|  | 		X509err(X509_F_X509_SET_PURPOSE_AND_TRUST, | ||||||
|  | 					X509_R_UNKNOWN_TRUST_ID); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	ptmp = X509_PURPOSE_iget(idx); | ||||||
|  | 	if(purp) *purp = id; | ||||||
|  | 	if(trust) *trust = ptmp->trust_id; | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| IMPLEMENT_STACK_OF(X509) | IMPLEMENT_STACK_OF(X509) | ||||||
| IMPLEMENT_ASN1_SET_OF(X509) | IMPLEMENT_ASN1_SET_OF(X509) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -263,6 +263,8 @@ struct x509_store_state_st      /* X509_STORE_CTX */ | ||||||
| #define		X509_V_ERR_INVALID_CA				24 | #define		X509_V_ERR_INVALID_CA				24 | ||||||
| #define		X509_V_ERR_PATH_LENGTH_EXCEEDED			25 | #define		X509_V_ERR_PATH_LENGTH_EXCEEDED			25 | ||||||
| #define		X509_V_ERR_INVALID_PURPOSE			26 | #define		X509_V_ERR_INVALID_PURPOSE			26 | ||||||
|  | #define		X509_V_ERR_CERT_UNTRUSTED			27 | ||||||
|  | #define		X509_V_ERR_CERT_REJECTED			28 | ||||||
| 
 | 
 | ||||||
| /* The application is not happy */ | /* The application is not happy */ | ||||||
| #define		X509_V_ERR_APPLICATION_VERIFICATION		50 | #define		X509_V_ERR_APPLICATION_VERIFICATION		50 | ||||||
|  | @ -347,8 +349,9 @@ X509 *	X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); | ||||||
| STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx); | STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx); | ||||||
| void	X509_STORE_CTX_set_cert(X509_STORE_CTX *c,X509 *x); | void	X509_STORE_CTX_set_cert(X509_STORE_CTX *c,X509 *x); | ||||||
| void	X509_STORE_CTX_set_chain(X509_STORE_CTX *c,STACK_OF(X509) *sk); | void	X509_STORE_CTX_set_chain(X509_STORE_CTX *c,STACK_OF(X509) *sk); | ||||||
| void X509_STORE_CTX_chain_purpose(X509_STORE_CTX *ctx, int purpose); | int X509_STORE_CTX_chain_purpose(X509_STORE_CTX *ctx, int purpose); | ||||||
| void X509_STORE_CTX_trust_purpose(X509_STORE_CTX *ctx, int purpose); | void X509_STORE_CTX_trust_purpose(X509_STORE_CTX *ctx, int purpose); | ||||||
|  | int X509_set_purpose_and_trust(int id, int *purp, int *trust); | ||||||
| 
 | 
 | ||||||
| #ifdef  __cplusplus | #ifdef  __cplusplus | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -128,10 +128,13 @@ int X509V3_EXT_add_alias(int nid_to, int nid_from) | ||||||
| 	return 1; | 	return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int added_exts = 0; | ||||||
|  | 
 | ||||||
| void X509V3_EXT_cleanup(void) | void X509V3_EXT_cleanup(void) | ||||||
| { | { | ||||||
| 	sk_pop_free(ext_list, ext_list_free); | 	sk_pop_free(ext_list, ext_list_free); | ||||||
| 	ext_list = NULL; | 	ext_list = NULL; | ||||||
|  | 	added_exts = 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void ext_list_free(X509V3_EXT_METHOD *ext) | static void ext_list_free(X509V3_EXT_METHOD *ext) | ||||||
|  | @ -147,6 +150,7 @@ extern X509V3_EXT_METHOD v3_crl_num, v3_crl_reason, v3_cpols, v3_crld; | ||||||
| 
 | 
 | ||||||
| int X509V3_add_standard_extensions(void) | int X509V3_add_standard_extensions(void) | ||||||
| { | { | ||||||
|  | 	if(added_exts) return 1; | ||||||
| 	X509V3_EXT_add_list(v3_ns_ia5_list); | 	X509V3_EXT_add_list(v3_ns_ia5_list); | ||||||
| 	X509V3_EXT_add_list(v3_alt); | 	X509V3_EXT_add_list(v3_alt); | ||||||
| 	X509V3_EXT_add(&v3_bcons); | 	X509V3_EXT_add(&v3_bcons); | ||||||
|  | @ -162,6 +166,7 @@ int X509V3_add_standard_extensions(void) | ||||||
| 	X509V3_EXT_add(&v3_crl_reason); | 	X509V3_EXT_add(&v3_crl_reason); | ||||||
| 	X509V3_EXT_add(&v3_cpols); | 	X509V3_EXT_add(&v3_cpols); | ||||||
| 	X509V3_EXT_add(&v3_crld); | 	X509V3_EXT_add(&v3_crld); | ||||||
|  | 	added_exts = 1; | ||||||
| 	return 1; | 	return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -222,7 +222,7 @@ static void x509v3_cache_extensions(X509 *x) | ||||||
| 	if(x->ex_flags & EXFLAG_SET) return; | 	if(x->ex_flags & EXFLAG_SET) return; | ||||||
| 	X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); | 	X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); | ||||||
| 	/* Does subject name match issuer ? */ | 	/* Does subject name match issuer ? */ | ||||||
| 	if(X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) | 	if(!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) | ||||||
| 			 x->ex_flags |= EXFLAG_SS; | 			 x->ex_flags |= EXFLAG_SS; | ||||||
| 	/* V1 should mean no extensions ... */ | 	/* V1 should mean no extensions ... */ | ||||||
| 	if(!X509_get_version(x)) x->ex_flags |= EXFLAG_V1; | 	if(!X509_get_version(x)) x->ex_flags |= EXFLAG_V1; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue