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}