Index: doc/tls.html
==================================================================
--- doc/tls.html
+++ doc/tls.html
@@ -131,10 +131,15 @@
environment variable.
-cafile filename
Specifies the file with the Certificate Authority (CA) certificates
to use. The default is cert.pem, in the OpenSSL directory. This can
also be overridden via the SSL_CERT_FILE environment variable.
+ -castore URI
+ URI for a store, which may be a single container or a catalog of
+ containers. On Windows, set to "org.openssl.winstore://" to use the
+ built-in Windows Cert Store. The Windows cert store only supports
+ root certificate stores.
-certfile filename
Specifies the file with the certificate to use in PEM format.
This also contains the public key.
-cert binary_string
Specifies the certificate to use as a DER encoded string (X.509 DER).
Index: generic/tls.c
==================================================================
--- generic/tls.c
+++ generic/tls.c
@@ -47,12 +47,12 @@
(((key) == NULL) ? (char *) NULL : \
Tcl_TranslateFileName(interp, (key), (dsp)))
static SSL_CTX *CTX_Init(State *statePtr, int isServer, int proto, char *key,
char *certfile, unsigned char *key_asn1, unsigned char *cert_asn1,
- Tcl_Size key_asn1_len, Tcl_Size cert_asn1_len, char *CApath, char *CAfile,
- char *ciphers, char *ciphersuites, int level, char *DHparams);
+ Tcl_Size key_asn1_len, Tcl_Size cert_asn1_len, char *CApath, char *CAstore,
+ char *CAfile, char *ciphers, char *ciphersuites, int level, char *DHparams);
#define TLS_PROTO_SSL2 0x01
#define TLS_PROTO_SSL3 0x02
#define TLS_PROTO_TLS1 0x04
#define TLS_PROTO_TLS1_1 0x08
@@ -1255,10 +1255,11 @@
Tcl_Size cert_len = 0;
char *ciphers = NULL;
char *ciphersuites = NULL;
char *CAfile = NULL;
char *CApath = NULL;
+ char *CAstore = NULL;
char *DHparams = NULL;
char *model = NULL;
char *servername = NULL; /* hostname for Server Name Indication */
char *session_id = NULL;
Tcl_Obj *alpn = NULL;
@@ -1305,10 +1306,11 @@
break;
OPTOBJ("-alpn", alpn);
OPTSTR("-cadir", CApath);
OPTSTR("-cafile", CAfile);
+ OPTSTR("-castore", CAstore);
OPTBYTE("-cert", cert, cert_len);
OPTSTR("-certfile", certfile);
OPTSTR("-cipher", ciphers);
OPTSTR("-ciphers", ciphers);
OPTSTR("-ciphersuites", ciphersuites);
@@ -1332,11 +1334,11 @@
OPTBOOL("-tls1.2", tls1_2);
OPTBOOL("-tls1.3", tls1_3);
OPTOBJ("-validatecommand", vcmd);
OPTOBJ("-vcmd", vcmd);
- OPTBAD("option", "-alpn, -cadir, -cafile, -cert, -certfile, -cipher, -ciphersuites, -command, -dhparams, -key, -keyfile, -model, -password, -post_handshake, -request, -require, -security_level, -server, -servername, -session_id, -ssl2, -ssl3, -tls1, -tls1.1, -tls1.2, -tls1.3, or -validatecommand");
+ OPTBAD("option", "-alpn, -cadir, -cafile, -castore, -cert, -certfile, -cipher, -ciphersuites, -command, -dhparams, -key, -keyfile, -model, -password, -post_handshake, -request, -require, -security_level, -server, -servername, -session_id, -ssl2, -ssl3, -tls1, -tls1.1, -tls1.2, -tls1.3, or -validatecommand");
return TCL_ERROR;
}
if (request) verify |= SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_PEER;
if (request && require) verify |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
@@ -1357,10 +1359,11 @@
if (keyfile && !*keyfile) keyfile = NULL;
if (ciphers && !*ciphers) ciphers = NULL;
if (ciphersuites && !*ciphersuites) ciphersuites = NULL;
if (CAfile && !*CAfile) CAfile = NULL;
if (CApath && !*CApath) CApath = NULL;
+ if (CAstore && !*CAstore) CAstore = NULL;
if (DHparams && !*DHparams) DHparams = NULL;
/* new SSL state */
statePtr = (State *) ckalloc((unsigned) sizeof(State));
memset(statePtr, 0, sizeof(State));
@@ -1418,11 +1421,11 @@
return TCL_ERROR;
}
ctx = ((State *)Tcl_GetChannelInstanceData(chan))->ctx;
} else {
if ((ctx = CTX_Init(statePtr, server, proto, keyfile, certfile, key, cert, key_len,
- cert_len, CApath, CAfile, ciphers, ciphersuites, level, DHparams)) == NULL) {
+ cert_len, CApath, CAstore, CAfile, ciphers, ciphersuites, level, DHparams)) == NULL) {
Tls_Free((tls_free_type *) statePtr);
return TCL_ERROR;
}
}
@@ -1570,10 +1573,11 @@
/*
* SSL Callbacks
*/
SSL_set_app_data(statePtr->ssl, (void *)statePtr); /* point back to us */
SSL_set_verify(statePtr->ssl, verify, VerifyCallback);
+ /*SSL_set_verify_depth(SSL_set_verify_depth, 0);*/
SSL_set_info_callback(statePtr->ssl, InfoCallback);
/* Callback for observing protocol messages */
#ifndef OPENSSL_NO_SSL_TRACE
/* void SSL_CTX_set_msg_callback_arg(statePtr->ctx, (void *)statePtr);
@@ -1740,11 +1744,11 @@
*-------------------------------------------------------------------
*/
static SSL_CTX *
CTX_Init(State *statePtr, int isServer, int proto, char *keyfile, char *certfile,
unsigned char *key, unsigned char *cert, Tcl_Size key_len, Tcl_Size cert_len, char *CApath,
- char *CAfile, char *ciphers, char *ciphersuites, int level, char *DHparams) {
+ char *CAstore, char *CAfile, char *ciphers, char *ciphersuites, int level, char *DHparams) {
Tcl_Interp *interp = statePtr->interp;
SSL_CTX *ctx = NULL;
Tcl_DString ds;
int off = 0, abort = 0;
int load_private_key;
@@ -2033,13 +2037,16 @@
SSL_CTX_free(ctx);
return NULL;
}
}
- /* Set to use default location and file for Certificate Authority (CA) certificates. The
- * verify path and store can be overridden by the SSL_CERT_DIR env var. The verify file can
- * be overridden by the SSL_CERT_FILE env var. */
+ /* Set to use the default location and file for Certificate Authority (CA) certificates.
+ * The default CA certificates directory is called certs in the default OpenSSL
+ * directory. It contains the CA certificates in PEM format, with one certificate per
+ * file. The verify path and store can be overridden by the SSL_CERT_DIR env var. The
+ * default CA certificates file is called cert.pem in the default OpenSSL directory.
+ * The verify file can be overridden by the SSL_CERT_FILE env var. */
if (!SSL_CTX_set_default_verify_paths(ctx)) {
abort++;
}
/* Overrides for the CA verify path and file */
@@ -2064,16 +2071,27 @@
}
Tcl_DStringFree(&ds);
}
#else
+ /* Directory containing CA certificates in PEM format. */
if (CApath != NULL) {
if (!SSL_CTX_load_verify_dir(ctx, F2N(CApath, &ds))) {
abort++;
}
Tcl_DStringFree(&ds);
}
+
+ /* URI for to a store, which may be a single container or a catalog of containers. */
+ if (CAstore != NULL) {
+ if (!SSL_CTX_load_verify_store(ctx, F2N(CAstore, &ds))) {
+ abort++;
+ }
+ Tcl_DStringFree(&ds);
+ }
+
+ /* File of CA certificates in PEM format. */
if (CAfile != NULL) {
if (!SSL_CTX_load_verify_file(ctx, F2N(CAfile, &ds))) {
abort++;
}
Tcl_DStringFree(&ds);
@@ -2782,10 +2800,13 @@
dprintf("Called");
if (statePtr->ssl) {
/* Send close_notify message */
dprintf("SSL_shutdown(%p)", statePtr->ssl);
+ /* Will return return 0 while shutdown in process, then 1 when complete */
+ /* closes the write direction of the connection; the read direction is closed by the peer. */
+ /* Does not affect socket */
SSL_shutdown(statePtr->ssl);
}
/*
* we're assuming here that we're single-threaded
Index: library/tls.tcl
==================================================================
--- library/tls.tcl
+++ library/tls.tcl
@@ -33,10 +33,11 @@
{0 -myport sopts 1}
{* -type sopts 1}
{* -alpn iopts 1}
{* -cadir iopts 1}
{* -cafile iopts 1}
+ {* -castore iopts 1}
{* -cert iopts 1}
{* -certfile iopts 1}
{* -cipher iopts 1}
{* -ciphersuites iopts 1}
{* -command iopts 1}