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

SSL_CONF additions.

Add support for loading verify and chain stores in SSL_CONF.

Commands to set verify mode and client CA names.

Add documentation.
Reviewed-by: NViktor Dukhovni <viktor@openssl.org>
上级 7e5363ab
...@@ -195,6 +195,12 @@ context. This option is only supported if certificate operations ...@@ -195,6 +195,12 @@ context. This option is only supported if certificate operations
are permitted. Note: if no B<PrivateKey> option is set then a private key is are permitted. Note: if no B<PrivateKey> option is set then a private key is
not loaded unless the B<SSL_CONF_FLAG_REQUIRE_PRIVATE> is set. not loaded unless the B<SSL_CONF_FLAG_REQUIRE_PRIVATE> is set.
=item B<ChainCAFile>, B<ChainCAPath>, B<VerifyCAFile>, B<VerifyCAPath>
These options indicate a file or directory used for building certificate
chains or verifying certificate chains. These options are only supported
if certificate operations are permitted.
=item B<ServerInfoFile> =item B<ServerInfoFile>
Attempts to use the file B<value> in the "serverinfo" extension using the Attempts to use the file B<value> in the "serverinfo" extension using the
...@@ -306,6 +312,27 @@ B<UnsafeLegacyServerConnect> permits the use of unsafe legacy renegotiation ...@@ -306,6 +312,27 @@ B<UnsafeLegacyServerConnect> permits the use of unsafe legacy renegotiation
for OpenSSL clients only. Equivalent to B<SSL_OP_LEGACY_SERVER_CONNECT>. for OpenSSL clients only. Equivalent to B<SSL_OP_LEGACY_SERVER_CONNECT>.
Set by default. Set by default.
=item B<VerifyMode>
The B<value> argument is a comma separated list of flags to set.
B<Peer> enables peer verification: for clients only.
B<Request> requests but does not require a certificate from the client.
Servers only.
B<Require> requests and requires a certificate from the client: an error
occurs if the client does not present a certificate. Servers only.
B<Once> requests a certificate from a client only on the initial connection:
not when renegotiating. Servers only.
=item B<ClientCAFile>, B<ClientCAPath>
A file or directory of certificates in PEM format whose names are used as the
set of acceptable names for client CAs. Servers only. This option is only
supported if certificate operations are permitted.
=back =back
=head1 SUPPORTED COMMAND TYPES =head1 SUPPORTED COMMAND TYPES
......
...@@ -86,8 +86,14 @@ typedef struct { ...@@ -86,8 +86,14 @@ typedef struct {
/* Sense of name is inverted e.g. "TLSv1" will clear SSL_OP_NO_TLSv1 */ /* Sense of name is inverted e.g. "TLSv1" will clear SSL_OP_NO_TLSv1 */
#define SSL_TFLAG_INV 0x1 #define SSL_TFLAG_INV 0x1
/* Flags refers to cert_flags not options */ /* Mask for type of flag referred to */
#define SSL_TFLAG_CERT 0x2 #define SSL_TFLAG_TYPE_MASK 0xf00
/* Flag is for options */
#define SSL_TFLAG_OPTION 0x000
/* Flag is for cert_flags */
#define SSL_TFLAG_CERT 0x100
/* Flag is for verify mode */
#define SSL_TFLAG_VFY 0x200
/* Option can only be used for clients */ /* Option can only be used for clients */
#define SSL_TFLAG_CLIENT SSL_CONF_FLAG_CLIENT #define SSL_TFLAG_CLIENT SSL_CONF_FLAG_CLIENT
/* Option can only be used for servers */ /* Option can only be used for servers */
...@@ -107,6 +113,11 @@ typedef struct { ...@@ -107,6 +113,11 @@ typedef struct {
#define SSL_FLAG_TBL_CERT(str, flag) \ #define SSL_FLAG_TBL_CERT(str, flag) \
{str, (int)(sizeof(str) - 1), SSL_TFLAG_CERT|SSL_TFLAG_BOTH, flag} {str, (int)(sizeof(str) - 1), SSL_TFLAG_CERT|SSL_TFLAG_BOTH, flag}
#define SSL_FLAG_VFY_CLI(str, flag) \
{str, (int)(sizeof(str) - 1), SSL_TFLAG_VFY | SSL_TFLAG_CLIENT, flag}
#define SSL_FLAG_VFY_SRV(str, flag) \
{str, (int)(sizeof(str) - 1), SSL_TFLAG_VFY | SSL_TFLAG_SERVER, flag}
/* /*
* Opaque structure containing SSL configuration context. * Opaque structure containing SSL configuration context.
*/ */
...@@ -129,30 +140,46 @@ struct ssl_conf_ctx_st { ...@@ -129,30 +140,46 @@ struct ssl_conf_ctx_st {
char *cert_filename[SSL_PKEY_NUM]; char *cert_filename[SSL_PKEY_NUM];
/* Pointer to SSL or SSL_CTX cert_flags or NULL if none */ /* Pointer to SSL or SSL_CTX cert_flags or NULL if none */
uint32_t *pcert_flags; uint32_t *pcert_flags;
/* Pointer to SSL or SSL_CTX verify_mode or NULL if none */
uint32_t *pvfy_flags;
/* Current flag table being worked on */ /* Current flag table being worked on */
const ssl_flag_tbl *tbl; const ssl_flag_tbl *tbl;
/* Size of table */ /* Size of table */
size_t ntbl; size_t ntbl;
/* Client CA names */
STACK_OF(X509_NAME) *canames;
}; };
static void ssl_set_option(SSL_CONF_CTX *cctx, unsigned int name_flags, static void ssl_set_option(SSL_CONF_CTX *cctx, unsigned int name_flags,
unsigned long option_value, int onoff) unsigned long option_value, int onoff)
{ {
unint32_t *pflags;
if (cctx->poptions == NULL) if (cctx->poptions == NULL)
return; return;
if (name_flags & SSL_TFLAG_INV) if (name_flags & SSL_TFLAG_INV)
onoff ^= 1; onoff ^= 1;
if (name_flags & SSL_TFLAG_CERT) { switch (name_flags & SSL_TFLAG_TYPE_MASK) {
if (onoff)
*cctx->pcert_flags |= option_value; case SSL_TFLAG_CERT:
else pflags = cctx->pcert_flags;
*cctx->pcert_flags &= ~option_value; break;
} else {
if (onoff) case SSL_TFLAG_VFY:
*cctx->poptions |= option_value; pflags = cctx->pvfy_flags;
else break;
*cctx->poptions &= ~option_value;
case SSL_TFLAG_OPTION:
pflags = cctx->poptions;
break;
default:
return;
} }
if (onoff)
*pflags |= option_value;
else
*pflags &= ~option_value;
} }
static int ssl_match_option(SSL_CONF_CTX *cctx, const ssl_flag_tbl *tbl, static int ssl_match_option(SSL_CONF_CTX *cctx, const ssl_flag_tbl *tbl,
...@@ -335,6 +362,22 @@ static int cmd_Options(SSL_CONF_CTX *cctx, const char *value) ...@@ -335,6 +362,22 @@ static int cmd_Options(SSL_CONF_CTX *cctx, const char *value)
return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx); return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
} }
static int cmd_VerifyMode(SSL_CONF_CTX *cctx, const char *value)
{
static const ssl_flag_tbl ssl_vfy_list[] = {
SSL_FLAG_VFY_CLI("Peer", SSL_VERIFY_PEER),
SSL_FLAG_VFY_SRV("Request", SSL_VERIFY_PEER),
SSL_FLAG_VFY_SRV("Require",
SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT),
SSL_FLAG_VFY_SRV("Once", SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE)
};
if (value == NULL)
return -3;
cctx->tbl = ssl_vfy_list;
cctx->ntbl = OSSL_NELEM(ssl_vfy_list);
return CONF_parse_list(value, ',', 1, ssl_set_option_list, cctx);
}
static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value) static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value)
{ {
int rv = 1; int rv = 1;
...@@ -378,6 +421,64 @@ static int cmd_ServerInfoFile(SSL_CONF_CTX *cctx, const char *value) ...@@ -378,6 +421,64 @@ static int cmd_ServerInfoFile(SSL_CONF_CTX *cctx, const char *value)
return rv > 0; return rv > 0;
} }
static int do_store(SSL_CONF_CTX *cctx,
const char *CAfile, const char *CApath, int verify_store)
{
CERT *cert;
X509_STORE **st;
if (cctx->ctx)
cert = cctx->ctx->cert;
else if (cctx->ssl)
cert = cctx->ssl->cert;
else
return 1;
st = verify_store ? &cert->verify_store : &cert->chain_store;
if (*st == NULL) {
*st = X509_STORE_new();
if (*st == NULL)
return 0;
}
return X509_STORE_load_locations(*st, CAfile, CApath) > 0;
}
static int cmd_ChainCAPath(SSL_CONF_CTX *cctx, const char *value)
{
return do_store(cctx, NULL, value, 0);
}
static int cmd_ChainCAFile(SSL_CONF_CTX *cctx, const char *value)
{
return do_store(cctx, value, NULL, 0);
}
static int cmd_VerifyCAPath(SSL_CONF_CTX *cctx, const char *value)
{
return do_store(cctx, NULL, value, 1);
}
static int cmd_VerifyCAFile(SSL_CONF_CTX *cctx, const char *value)
{
return do_store(cctx, value, NULL, 1);
}
static int cmd_ClientCAFile(SSL_CONF_CTX *cctx, const char *value)
{
if (cctx->canames == NULL)
cctx->canames = sk_X509_NAME_new_null();
if (cctx->canames == NULL)
return 0;
return SSL_add_file_cert_subjects_to_stack(cctx->canames, value);
}
static int cmd_ClientCAPath(SSL_CONF_CTX *cctx, const char *value)
{
if (cctx->canames == NULL)
cctx->canames = sk_X509_NAME_new_null();
if (cctx->canames == NULL)
return 0;
return SSL_add_dir_cert_subjects_to_stack(cctx->canames, value);
}
#ifndef OPENSSL_NO_DH #ifndef OPENSSL_NO_DH
static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value) static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value)
{ {
...@@ -452,6 +553,7 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = { ...@@ -452,6 +553,7 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
SSL_CONF_CMD_STRING(CipherString, "cipher", 0), SSL_CONF_CMD_STRING(CipherString, "cipher", 0),
SSL_CONF_CMD_STRING(Protocol, NULL, 0), SSL_CONF_CMD_STRING(Protocol, NULL, 0),
SSL_CONF_CMD_STRING(Options, NULL, 0), SSL_CONF_CMD_STRING(Options, NULL, 0),
SSL_CONF_CMD_STRING(VerifyMode, NULL, 0),
SSL_CONF_CMD(Certificate, "cert", SSL_CONF_FLAG_CERTIFICATE, SSL_CONF_CMD(Certificate, "cert", SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_FILE), SSL_CONF_TYPE_FILE),
SSL_CONF_CMD(PrivateKey, "key", SSL_CONF_FLAG_CERTIFICATE, SSL_CONF_CMD(PrivateKey, "key", SSL_CONF_FLAG_CERTIFICATE,
...@@ -459,6 +561,20 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = { ...@@ -459,6 +561,20 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
SSL_CONF_CMD(ServerInfoFile, NULL, SSL_CONF_CMD(ServerInfoFile, NULL,
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE, SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_FILE), SSL_CONF_TYPE_FILE),
SSL_CONF_CMD(ChainCAPath, "chainCApath", SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_DIR),
SSL_CONF_CMD(ChainCAFile, "chainCAfile", SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_FILE),
SSL_CONF_CMD(VerifyCAPath, "verifyCApath", SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_DIR),
SSL_CONF_CMD(VerifyCAFile, "verifyCAfile", SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_FILE),
SSL_CONF_CMD(ClientCAFile, NULL,
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_FILE),
SSL_CONF_CMD(ClientCAPath, NULL,
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_DIR),
#ifndef OPENSSL_NO_DH #ifndef OPENSSL_NO_DH
SSL_CONF_CMD(DHParameters, "dhparam", SSL_CONF_CMD(DHParameters, "dhparam",
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE, SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
...@@ -666,10 +782,12 @@ SSL_CONF_CTX *SSL_CONF_CTX_new(void) ...@@ -666,10 +782,12 @@ SSL_CONF_CTX *SSL_CONF_CTX_new(void)
ret->ctx = NULL; ret->ctx = NULL;
ret->poptions = NULL; ret->poptions = NULL;
ret->pcert_flags = NULL; ret->pcert_flags = NULL;
ret->pvfy_flags = NULL;
ret->tbl = NULL; ret->tbl = NULL;
ret->ntbl = 0; ret->ntbl = 0;
for (i = 0; i < SSL_PKEY_NUM; i++) for (i = 0; i < SSL_PKEY_NUM; i++)
ret->cert_filename[i] = NULL; ret->cert_filename[i] = NULL;
ret->canames = NULL;
} }
return ret; return ret;
} }
...@@ -695,6 +813,15 @@ int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx) ...@@ -695,6 +813,15 @@ int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx)
} }
} }
} }
if (cctx->canames) {
if (cctx->ssl)
SSL_set_client_CA_list(cctx->ssl, cctx->canames);
else if (cctx->ctx)
SSL_CTX_set_client_CA_list(cctx->ctx, cctx->canames);
else
sk_X509_NAME_pop_free(cctx->canames, X509_NAME_free);
cctx->canames = NULL;
}
return 1; return 1;
} }
...@@ -706,6 +833,7 @@ void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx) ...@@ -706,6 +833,7 @@ void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx)
OPENSSL_free(cctx->cert_filename[i]); OPENSSL_free(cctx->cert_filename[i]);
OPENSSL_free(cctx->prefix); OPENSSL_free(cctx->prefix);
OPENSSL_free(cctx); OPENSSL_free(cctx);
sk_X509_NAME_pop_free(cctx->canames, X509_NAME_free);
} }
} }
...@@ -745,9 +873,11 @@ void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl) ...@@ -745,9 +873,11 @@ void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl)
if (ssl) { if (ssl) {
cctx->poptions = &ssl->options; cctx->poptions = &ssl->options;
cctx->pcert_flags = &ssl->cert->cert_flags; cctx->pcert_flags = &ssl->cert->cert_flags;
cctx->pvfy_flags = &ssl->verify_mode;
} else { } else {
cctx->poptions = NULL; cctx->poptions = NULL;
cctx->pcert_flags = NULL; cctx->pcert_flags = NULL;
cctx->pvfy_flags = NULL;
} }
} }
...@@ -758,8 +888,10 @@ void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx) ...@@ -758,8 +888,10 @@ void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx)
if (ctx) { if (ctx) {
cctx->poptions = &ctx->options; cctx->poptions = &ctx->options;
cctx->pcert_flags = &ctx->cert->cert_flags; cctx->pcert_flags = &ctx->cert->cert_flags;
cctx->pvfy_flags = &ctx->verify_mode;
} else { } else {
cctx->poptions = NULL; cctx->poptions = NULL;
cctx->pcert_flags = NULL; cctx->pcert_flags = NULL;
cctx->pvfy_flags = NULL;
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册