Index: doc/tls.html ================================================================== --- doc/tls.html +++ doc/tls.html @@ -120,11 +120,12 @@ <blockquote> <dl> <dt><strong>-alpn</strong> <em>list</em></dt> <dd>List of protocols to offer during Application-Layer - Protocol Negotiation (ALPN). For example: h2, http/1.1, etc.</dd> + Protocol Negotiation (ALPN). For example: <em>h2</em> and + <em>http/1.1</em>, but not <em>h3</em> or <em>quic</em>.</dd> <dt><strong>-cadir</strong> <em>dir</em></dt> <dd>Set the CA certificates path. The default directory is platform specific and can be set at compile time. This can be overridden via the <b>SSL_CERT_DIR</b> environment variable.</dd> <dt><strong>-cafile </strong><em>filename</em></dt> @@ -434,22 +435,23 @@ As indicated above, individual channels can be given their own callbacks to handle intermediate processing by the OpenSSL library, using the <strong>-command</strong>, <strong>-password</strong>, and <strong>-validate_command</strong> options passed to either of <strong>tls::socket</strong> or <strong>tls::import</strong>. +If the callback generates an error, the <b>bgerror</b> command with be +invoked with the error information. </p> <blockquote> <dl> <dt><strong>-command</strong> <em>callback</em></dt> <dd> - Invokes the specified <em>callback</em> script at - several points during the OpenSSL handshake. - Values returned from the callback are ignored. - Arguments appended to the script upon callback take one of the - following forms: + Invokes the specified <em>callback</em> script at several points + during the OpenSSL handshake and use. See below for the possible + arguments passed to the callback script. Values returned from the + callback are ignored. <br> <br> <dl> @@ -477,11 +479,11 @@ <code>handshake, alert, connect, accept</code>.</li> <li>Possible values for <em>minor</em> are: <code>start, done, read, write, loop, exit</code>.</li> <li>The <em>message</em> argument is a descriptive string which may be generated either by <code>SSL_state_string_long()</code> or by - <code>SSL_alert_desc_string_long()</code>, depending on context.</li> + <code>SSL_alert_desc_string_long()</code>, depending on the context.</li> <li>For alerts, the possible values for <em>type</em> are: <code>warning, fatal, and unknown</code>. For others, <code>info</code> is used.</li> </ul> </dd> @@ -517,24 +519,41 @@ <br> <dt><strong>-password</strong> <em>callback</em></dt> <dd> Invokes the specified <em>callback</em> script when OpenSSL needs to - obtain a password. The callback should return the password as a string. - No arguments are appended to the script upon callback. + obtain a password. See below for the possible arguments passed to + the callback script. See below for valid return values. + + <br> + <br> + + <dl> + + <dt> + <strong>password</strong> <em>rwflag size</em> + </dt> + <dd> + Invoked when loading or storing a PEM certificate with encryption. + Where <em>rwflag</em> is 0 for reading/decryption or 1 for + writing/encryption (can prompt user to confirm) and + <em>size</em> is the max password length in bytes. + The callback should return the password as a string. + </dd> </dd> <br> <dt><strong>-validatecommand</strong> <em>callback</em></dt> <dd> Invokes the specified <em>callback</em> script during handshake in - order to validate the provided value(s). + order to validate the provided value(s). See below for the possible + arguments passed to the callback script. To reject the value and abort connection, the callback should return 0. - To accept the value, it should return 1. To reject the value, but - continue the connection, it should return 2. + To accept the value and continue the connection, it should return 1. + To reject the value, but continue the connection, it should return 2. <br> <br> <dl> @@ -545,10 +564,11 @@ <dd> For servers, this form of callback is invoked when the client ALPN extension is received. Where <em>protocol</em> is the first <b>-alpn</b> specified protocol common to the both the client and server. If none, the first client specified protocol is used. + Called after hello and ALPN callbacks. </dd> <br> <dt> Index: generic/tls.c ================================================================== --- generic/tls.c +++ generic/tls.c @@ -489,18 +489,27 @@ /* *------------------------------------------------------------------- * * Password Callback -- * - * Called when a password is needed to unpack RSA and PEM keys. - * Evals any bound password script and returns the result as - * the password string. + * Called when a password for a private key loading/storing a PEM + * certificate with encryption. Evals callback script and returns + * the result as the password string in buf. + * + * Results: + * None + * + * Side effects: + * Calls callback (if defined) + * + * Returns: + * Password size in bytes or -1 for an error. * *------------------------------------------------------------------- */ static int -PasswordCallback(char *buf, int size, int verify, void *udata) { +PasswordCallback(char *buf, int size, int rwflag, void *udata) { State *statePtr = (State *) udata; Tcl_Interp *interp = statePtr->interp; Tcl_Obj *cmdPtr; int code; @@ -517,15 +526,18 @@ } } /* Create command to eval */ cmdPtr = Tcl_DuplicateObj(statePtr->password); + Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj("password", -1)); + Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewIntObj(rwflag)); + Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewIntObj(size)); Tcl_Preserve((ClientData) interp); Tcl_Preserve((ClientData) statePtr); - /* Eval callback and success for ok, abort for error, continue for continue */ + /* Eval callback command */ Tcl_IncrRefCount(cmdPtr); code = Tcl_EvalObjEx(interp, cmdPtr, TCL_EVAL_GLOBAL); if (code != TCL_OK) { #if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION < 6) Tcl_BackgroundError(interp); @@ -535,21 +547,24 @@ } Tcl_DecrRefCount(cmdPtr); Tcl_Release((ClientData) statePtr); + /* If successful, pass back password string and truncate if too long */ if (code == TCL_OK) { - char *ret = (char *) Tcl_GetStringResult(interp); - if (strlen(ret) < size - 1) { - strncpy(buf, ret, (size_t) size); - Tcl_Release((ClientData) interp); - return (int)strlen(ret); + int len; + char *ret = (char *) Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &len); + if (len > size-1) { + len = size-1; } + strncpy(buf, ret, (size_t) len); + buf[len] = '\0'; + Tcl_Release((ClientData) interp); + return(len); } Tcl_Release((ClientData) interp); return -1; - verify = verify; } /* *------------------------------------------------------------------- *