提交 a70da5b3 编写于 作者: D Dr. Stephen Henson

New functions to check a hostname email or IP address against a

certificate. Add options to s_client, s_server and x509 utilities
to print results of checks.
上级 c5f6da54
...@@ -4,6 +4,11 @@ ...@@ -4,6 +4,11 @@
Changes between 1.0.x and 1.1.0 [xx XXX xxxx] Changes between 1.0.x and 1.1.0 [xx XXX xxxx]
*) New functions to check a hostname email or IP address against a
certificate. Add options to s_client, s_server and x509 utilities
to print results of checks against a certificate.
[Steve Henson]
*) Add -rev test option to s_server to just reverse order of characters *) Add -rev test option to s_server to just reverse order of characters
received by client and send back to server. Also prints an abbreviated received by client and send back to server. Also prints an abbreviated
summary of the connection parameters. summary of the connection parameters.
......
...@@ -2791,6 +2791,35 @@ unsigned char *next_protos_parse(unsigned short *outlen, const char *in) ...@@ -2791,6 +2791,35 @@ unsigned char *next_protos_parse(unsigned short *outlen, const char *in)
} }
#endif /* !OPENSSL_NO_TLSEXT && !OPENSSL_NO_NEXTPROTONEG */ #endif /* !OPENSSL_NO_TLSEXT && !OPENSSL_NO_NEXTPROTONEG */
void print_cert_checks(BIO *bio, X509 *x,
const unsigned char *checkhost,
const unsigned char *checkemail,
const char *checkip)
{
if (x == NULL)
return;
if (checkhost)
{
BIO_printf(bio, "Hostname %s does%s match certificate\n",
checkhost, X509_check_host(x, checkhost, 0, 0)
? "" : " NOT");
}
if (checkemail)
{
BIO_printf(bio, "Email %s does%s match certificate\n",
checkemail, X509_check_email(x, checkemail, 0,
0) ? "" : " NOT");
}
if (checkip)
{
BIO_printf(bio, "IP %s does%s match certificate\n",
checkip, X509_check_ip_asc(x, checkip,
0) ? "" : " NOT");
}
}
/* /*
* Platform-specific sections * Platform-specific sections
*/ */
......
...@@ -335,6 +335,11 @@ void jpake_server_auth(BIO *out, BIO *conn, const char *secret); ...@@ -335,6 +335,11 @@ void jpake_server_auth(BIO *out, BIO *conn, const char *secret);
unsigned char *next_protos_parse(unsigned short *outlen, const char *in); unsigned char *next_protos_parse(unsigned short *outlen, const char *in);
#endif /* !OPENSSL_NO_TLSEXT && !OPENSSL_NO_NEXTPROTONEG */ #endif /* !OPENSSL_NO_TLSEXT && !OPENSSL_NO_NEXTPROTONEG */
void print_cert_checks(BIO *bio, X509 *x,
const unsigned char *checkhost,
const unsigned char *checkemail,
const char *checkip);
#define FORMAT_UNDEF 0 #define FORMAT_UNDEF 0
#define FORMAT_ASN1 1 #define FORMAT_ASN1 1
#define FORMAT_TEXT 2 #define FORMAT_TEXT 2
......
...@@ -191,3 +191,7 @@ int args_excert(char ***pargs, int *pargc, ...@@ -191,3 +191,7 @@ int args_excert(char ***pargs, int *pargc,
int *badarg, BIO *err, SSL_EXCERT **pexc); int *badarg, BIO *err, SSL_EXCERT **pexc);
int load_excert(SSL_EXCERT **pexc, BIO *err); int load_excert(SSL_EXCERT **pexc, BIO *err);
void print_ssl_summary(BIO *bio, SSL *s); void print_ssl_summary(BIO *bio, SSL *s);
void print_ssl_cert_checks(BIO *bio, SSL *s,
const unsigned char *checkhost,
const unsigned char *checkemail,
const char *checkip);
...@@ -1533,3 +1533,16 @@ void print_ssl_summary(BIO *bio, SSL *s) ...@@ -1533,3 +1533,16 @@ void print_ssl_summary(BIO *bio, SSL *s)
ssl_print_tmp_key(bio, s); ssl_print_tmp_key(bio, s);
} }
void print_ssl_cert_checks(BIO *bio, SSL *s,
const unsigned char *checkhost,
const unsigned char *checkemail,
const char *checkip)
{
X509 *peer;
peer = SSL_get_peer_certificate(s);
if (peer)
{
print_cert_checks(bio, peer, checkhost, checkemail, checkip);
X509_free(peer);
}
}
...@@ -634,6 +634,9 @@ int MAIN(int argc, char **argv) ...@@ -634,6 +634,9 @@ int MAIN(int argc, char **argv)
#endif #endif
SSL_EXCERT *exc = NULL; SSL_EXCERT *exc = NULL;
unsigned char *checkhost = NULL, *checkemail = NULL;
char *checkip = NULL;
meth=SSLv23_client_method(); meth=SSLv23_client_method();
apps_startup(); apps_startup();
...@@ -993,6 +996,21 @@ int MAIN(int argc, char **argv) ...@@ -993,6 +996,21 @@ int MAIN(int argc, char **argv)
client_sigalgs= *(++argv); client_sigalgs= *(++argv);
} }
#endif #endif
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);
}
#ifndef OPENSSL_NO_JPAKE #ifndef OPENSSL_NO_JPAKE
else if (strcmp(*argv,"-jpake") == 0) else if (strcmp(*argv,"-jpake") == 0)
{ {
...@@ -1628,6 +1646,8 @@ SSL_set_tlsext_status_ids(con, ids); ...@@ -1628,6 +1646,8 @@ SSL_set_tlsext_status_ids(con, ids);
"CONNECTION ESTABLISHED\n"); "CONNECTION ESTABLISHED\n");
print_ssl_summary(bio_err, con); print_ssl_summary(bio_err, con);
} }
print_ssl_cert_checks(bio_err, con, checkhost,
checkemail, checkip);
print_stuff(bio_c_out,con,full_log); print_stuff(bio_c_out,con,full_log);
if (full_log > 0) full_log--; if (full_log > 0) full_log--;
......
...@@ -1003,6 +1003,10 @@ int MAIN(int argc, char *argv[]) ...@@ -1003,6 +1003,10 @@ int MAIN(int argc, char *argv[])
char *srp_verifier_file = NULL; char *srp_verifier_file = NULL;
#endif #endif
SSL_EXCERT *exc = NULL; SSL_EXCERT *exc = NULL;
unsigned char *checkhost = NULL, *checkemail = NULL;
char *checkip = NULL;
meth=SSLv23_server_method(); meth=SSLv23_server_method();
local_argc=argc; local_argc=argc;
...@@ -1260,6 +1264,21 @@ int MAIN(int argc, char *argv[]) ...@@ -1260,6 +1264,21 @@ int MAIN(int argc, char *argv[])
client_sigalgs= *(++argv); client_sigalgs= *(++argv);
} }
#endif #endif
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,"-msg") == 0) else if (strcmp(*argv,"-msg") == 0)
{ s_msg=1; } { s_msg=1; }
else if (strcmp(*argv,"-msgfile") == 0) else if (strcmp(*argv,"-msgfile") == 0)
...@@ -2661,6 +2680,8 @@ static int init_ssl_connection(SSL *con) ...@@ -2661,6 +2680,8 @@ static int init_ssl_connection(SSL *con)
if (s_brief) if (s_brief)
print_ssl_summary(bio_err, con); print_ssl_summary(bio_err, con);
print_ssl_cert_checks(bio_err, con, checkhost, checkemail, checkip);
PEM_write_bio_SSL_SESSION(bio_s_out,SSL_get_session(con)); PEM_write_bio_SSL_SESSION(bio_s_out,SSL_get_session(con));
peer=SSL_get_peer_certificate(con); peer=SSL_get_peer_certificate(con);
......
...@@ -208,6 +208,8 @@ int MAIN(int argc, char **argv) ...@@ -208,6 +208,8 @@ int MAIN(int argc, char **argv)
int need_rand = 0; int need_rand = 0;
int checkend=0,checkoffset=0; int checkend=0,checkoffset=0;
unsigned long nmflag = 0, certflag = 0; unsigned long nmflag = 0, certflag = 0;
unsigned char *checkhost = NULL, *checkemail = NULL;
char *checkip = NULL;
#ifndef OPENSSL_NO_ENGINE #ifndef OPENSSL_NO_ENGINE
char *engine=NULL; char *engine=NULL;
#endif #endif
...@@ -456,6 +458,21 @@ int MAIN(int argc, char **argv) ...@@ -456,6 +458,21 @@ int MAIN(int argc, char **argv)
checkoffset=atoi(*(++argv)); checkoffset=atoi(*(++argv));
checkend=1; 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) else if (strcmp(*argv,"-noout") == 0)
noout= ++num; noout= ++num;
else if (strcmp(*argv,"-trustout") == 0) else if (strcmp(*argv,"-trustout") == 0)
...@@ -1061,6 +1078,8 @@ bad: ...@@ -1061,6 +1078,8 @@ bad:
goto end; goto end;
} }
print_cert_checks(STDout, x, checkhost, checkemail, checkip);
if (noout) if (noout)
{ {
ret=0; ret=0;
......
...@@ -568,6 +568,134 @@ void X509_email_free(STACK_OF(OPENSSL_STRING) *sk) ...@@ -568,6 +568,134 @@ void X509_email_free(STACK_OF(OPENSSL_STRING) *sk)
sk_OPENSSL_STRING_pop_free(sk, str_free); sk_OPENSSL_STRING_pop_free(sk, str_free);
} }
/* Compare an ASN1_STRING to a supplied string. If they match
* return 1. If cmp_type > 0 only compare if string matches the
* type, otherwise convert it to UTF8.
*/
static int do_check_string(ASN1_STRING *a, int cmp_type,
const unsigned char *b, size_t blen)
{
if (!a->data || !a->length)
return 0;
if (cmp_type > 0)
{
if (cmp_type != a->type)
return 0;
if (a->length == (int)blen && !memcmp(a->data, b, blen))
return 1;
else
return 0;
}
else
{
int astrlen, rv;
unsigned char *astr;
astrlen = ASN1_STRING_to_UTF8(&astr, a);
if (astrlen < 0)
return 0;
if (astrlen == (int)blen && !memcmp(astr, b, blen))
rv = 1;
else
rv = 0;
OPENSSL_free(astr);
return rv;
}
}
static int do_x509_check(X509 *x, const unsigned char *chk, size_t chklen,
unsigned int flags, int check_type)
{
GENERAL_NAMES *gens = NULL;
X509_NAME *name = NULL;
int i;
int cnid;
if (check_type == GEN_EMAIL)
cnid = NID_pkcs9_emailAddress;
else if (check_type == GEN_DNS)
cnid = NID_commonName;
else
cnid = 0;
if (chklen == 0)
chklen = strlen((const char *)chk);
gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
if (gens)
{
int rv = 0;
int alt_type;
if (cnid)
alt_type = V_ASN1_IA5STRING;
else
alt_type = V_ASN1_OCTET_STRING;
for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
{
GENERAL_NAME *gen;
ASN1_STRING *cstr;
gen = sk_GENERAL_NAME_value(gens, i);
if(gen->type != check_type)
continue;
if (check_type == GEN_EMAIL)
cstr = gen->d.rfc822Name;
else if (check_type == GEN_DNS)
cstr = gen->d.dNSName;
else
cstr = gen->d.iPAddress;
if (do_check_string(cstr, alt_type, chk, chklen))
{
rv = 1;
break;
}
}
GENERAL_NAMES_free(gens);
if (rv)
return 1;
if (!(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT) || !cnid)
return 0;
}
i = -1;
name = X509_get_subject_name(x);
while((i = X509_NAME_get_index_by_NID(name, cnid, i)) >= 0)
{
X509_NAME_ENTRY *ne;
ASN1_STRING *str;
ne = X509_NAME_get_entry(name, i);
str = X509_NAME_ENTRY_get_data(ne);
if (do_check_string(str, -1, chk, chklen))
return 1;
}
return 0;
}
int X509_check_host(X509 *x, const unsigned char *chk, size_t chklen,
unsigned int flags)
{
return do_x509_check(x, chk, chklen, flags, GEN_DNS);
}
int X509_check_email(X509 *x, const unsigned char *chk, size_t chklen,
unsigned int flags)
{
return do_x509_check(x, chk, chklen, flags, GEN_EMAIL);
}
int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
unsigned int flags)
{
return do_x509_check(x, chk, chklen, flags, GEN_IPADD);
}
int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
{
unsigned char ipout[16];
int iplen;
iplen = a2i_ipadd(ipout, ipasc);
if (iplen == 0)
return 0;
return do_x509_check(x, ipout, (size_t)iplen, flags, GEN_IPADD);
}
/* Convert IP addresses both IPv4 and IPv6 into an /* Convert IP addresses both IPv4 and IPv6 into an
* OCTET STRING compatible with RFC3280. * OCTET STRING compatible with RFC3280.
*/ */
......
...@@ -700,6 +700,18 @@ STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x); ...@@ -700,6 +700,18 @@ STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x);
STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x); STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x);
void X509_email_free(STACK_OF(OPENSSL_STRING) *sk); void X509_email_free(STACK_OF(OPENSSL_STRING) *sk);
STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x); STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x);
/* Flags for X509_check_* functions */
/* Always check subject name for host match even if subject alt names present */
#define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT 0x1
int X509_check_host(X509 *x, const unsigned char *chk, size_t chklen,
unsigned int flags);
int X509_check_email(X509 *x, const unsigned char *chk, size_t chklen,
unsigned int flags);
int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
unsigned int flags);
int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags);
ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc); ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc);
ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc); ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册