@@ -433,28 +433,34 @@ * Session Callback for Clients -- * * Called when a new session is added to the cache. In TLS 1.3 * this may be received multiple times after the handshake. For * earlier versions, this will be received during the handshake. + * This is the preferred way to obtain a resumable session. * * Results: * None * * Side effects: * Calls callback (if defined) + * + * Return codes: + * 0 = error where session will be immediately removed from the internal cache. + * 1 = success where app retains session in session cache, and must call SSL_SESSION_free() when done. + * *------------------------------------------------------------------- */ static int SessionCallback(const SSL *ssl, SSL_SESSION *session) { State *statePtr = (State*)SSL_get_app_data((SSL *)ssl); Tcl_Interp *interp = statePtr->interp; Tcl_Obj *cmdPtr; const unsigned char *ticket; const unsigned char *session_id; - int len; int code; size_t len2; + unsigned int ulen; dprintf("Called"); if (statePtr->callback == (Tcl_Obj*)NULL) { return SSL_TLSEXT_ERR_OK; @@ -464,12 +470,12 @@ cmdPtr = Tcl_DuplicateObj(statePtr->callback); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj("session", -1)); /* Session id */ - session_id = SSL_SESSION_get0_id_context(session, &len); - Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(session_id, len)); + session_id = SSL_SESSION_get_id(session, &ulen); + Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewByteArrayObj(session_id, (int) ulen)); /* Session ticket */ SSL_SESSION_get0_ticket(session, &ticket, &len2); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(ticket, (int)len2)); @@ -490,22 +496,20 @@ #endif } Tcl_DecrRefCount(cmdPtr); Tcl_Release((ClientData) statePtr); - Tcl_Release((ClientData) interp); - /* If return non-zero, caller will have to do a SSL_SESSION_free() on the structure. */ - return 0; + Tcl_Release((ClientData) interp); return 0; } /* *------------------------------------------------------------------- * * ALPN Callback for Servers -- * - * Select which protocol (http/1.1, h2, h3, etc.) to use for the - * incoming connection. + * Perform server-side protocol (http/1.1, h2, h3, etc.) selection for the + * incoming connection. Called after Hello and server callbacks * * Results: * None * * Side effects: @@ -524,11 +528,11 @@ ALPNCallback(const SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) { State *statePtr = (State*)arg; Tcl_Interp *interp = statePtr->interp; Tcl_Obj *cmdPtr; - int code; + int code, res; dprintf("Called"); if (statePtr->callback == (Tcl_Obj*)NULL) { return SSL_TLSEXT_ERR_OK; @@ -535,11 +539,17 @@ } else if (ssl == NULL) { return SSL_TLSEXT_ERR_NOACK; } /* Select protocol */ - SSL_select_next_proto(out, outlen, statePtr->protos, statePtr->protos_len, in, inlen); + if (SSL_select_next_proto(out, outlen, statePtr->protos, statePtr->protos_len, + in, inlen) == OPENSSL_NPN_NEGOTIATED) { + res = SSL_TLSEXT_ERR_OK; + } else { + /* No overlap, so first client protocol used */ + res = SSL_TLSEXT_ERR_NOACK; + } cmdPtr = Tcl_DuplicateObj(statePtr->callback); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj("alpn", -1)); Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj(*out, -1)); @@ -557,19 +567,20 @@ } Tcl_DecrRefCount(cmdPtr); Tcl_Release((ClientData) statePtr); Tcl_Release((ClientData) interp); - return SSL_TLSEXT_ERR_OK; + return res; } /* *------------------------------------------------------------------- * * SNI Callback for Servers -- * - * Perform server name selection + * Perform server-side SNI hostname selection after receiving SNI header. + * Called after hello callback but before ALPN callback. * * Results: * None * * Side effects: @@ -631,18 +642,18 @@ } /* *------------------------------------------------------------------- * - * Hello Callback for Servers -- + * Hello Handshake Callback for Servers -- * * Used by server to examine the server name indication (SNI) extension * provided by the client in order to select an appropriate certificate to * present, and make other configuration adjustments relevant to that server * name and its configuration. This includes swapping out the associated * SSL_CTX pointer, modifying the server's list of permitted TLS versions, -* changing the server's cipher list in response to the client's cipher list, etc. + * changing the server's cipher list in response to the client's cipher list, etc. * * Results: * None * * Side effects: @@ -1299,11 +1310,11 @@ /* Determine the memory required for the protocol-list */ for (i = 0; i < cnt; i++) { Tcl_GetStringFromObj(list[i], &len); if (len > 255) { - Tcl_AppendResult(interp, "alpn protocol name too long", (char *) NULL); + Tcl_AppendResult(interp, "ALPN protocol name too long", (char *) NULL); Tls_Free((char *) statePtr); return TCL_ERROR; } protos_len += 1 + len; } @@ -1319,11 +1330,11 @@ } /* SSL_set_alpn_protos makes a copy of the protocol-list */ /* Note: This functions reverses the return value convention */ if (SSL_set_alpn_protos(statePtr->ssl, protos, protos_len)) { - Tcl_AppendResult(interp, "failed to set alpn protocols", (char *) NULL); + Tcl_AppendResult(interp, "failed to set ALPN protocols", (char *) NULL); Tls_Free((char *) statePtr); ckfree(protos); return TCL_ERROR; }