Index: generic/tls.c ================================================================== --- generic/tls.c +++ generic/tls.c @@ -82,11 +82,11 @@ * Side effects: * Evaluates callback command * *------------------------------------------------------------------- */ - + static int EvalCallback( Tcl_Interp *interp, /* Tcl interpreter */ State *statePtr, /* Client state for TLS socket */ Tcl_Obj *cmdPtr) /* Command to eval as a Tcl object */ @@ -137,11 +137,11 @@ * Side effects: * Calls callback (if defined) * *------------------------------------------------------------------- */ - + static void InfoCallback( const SSL *ssl, /* SSL context */ int where, /* Source of info */ int ret) /* message enum */ @@ -214,11 +214,11 @@ * Side effects: * Calls callback (if defined) * *------------------------------------------------------------------- */ - + #ifndef OPENSSL_NO_SSL_TRACE static void MessageCallback( int write_p, /* Message 0=received, 1=sent */ int version, /* TLS version */ @@ -364,11 +364,11 @@ * The err field of the currently operative State is set * to a string describing the SSL negotiation failure reason * *------------------------------------------------------------------- */ - + static int VerifyCallback( int ok, /* Verify result */ X509_STORE_CTX *ctx) /* CTX context */ { @@ -434,11 +434,11 @@ * The err field of the currently operative State is set to a * string describing the SSL negotiation failure reason * *------------------------------------------------------------------- */ - + void Tls_Error( State *statePtr, /* Client state for TLS socket */ const char *msg) /* Error message */ { @@ -492,11 +492,11 @@ * Side effects: * none * *------------------------------------------------------------------- */ - + void KeyLogCallback( const SSL *ssl, /* Client state for TLS socket */ const char *line) /* Key data to be logged */ { char *str = getenv(SSLKEYLOGFILE); @@ -529,11 +529,11 @@ * Returns: * Password size in bytes or -1 for an error. * *------------------------------------------------------------------- */ - + static int PasswordCallback( char *buf, /* Pointer to buffer to store password in */ int size, /* Buffer length in bytes */ int rwflag, /* Whether password is needed for read or write */ @@ -614,11 +614,11 @@ * 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( SSL *ssl, /* SSL context */ SSL_SESSION *session) /* Session context */ { @@ -687,11 +687,11 @@ * SSL_TLSEXT_ERR_NOACK: ALPN protocol not selected, e.g., because no ALPN * protocols are configured for this connection. The connection continues. * *------------------------------------------------------------------- */ - + static int ALPNCallback( SSL *ssl, /* SSL context */ const unsigned char **out, /* Return buffer to store selected protocol */ unsigned char *outlen, /* Return buffer size */ @@ -762,11 +762,11 @@ * SSL_TLSEXT_ERR_OK: NPN protocol selected. The connection continues. * SSL_TLSEXT_ERR_NOACK: NPN protocol not selected. The connection continues. * *------------------------------------------------------------------- */ - + #ifdef USE_NPN static int NPNCallback( const SSL *ssl, /* SSL context */ const unsigned char **out, /* Return buffer to store selected protocol */ @@ -817,11 +817,11 @@ * SSL_TLSEXT_ERR_NOACK: SNI hostname is not accepted and not acknowledged, * e.g. if SNI has not been configured. The connection continues. * *------------------------------------------------------------------- */ - + static int SNICallback( const SSL *ssl, /* SSL context */ int *alert, /* Returned alert message */ void *arg) /* Client state for TLS socket */ @@ -894,11 +894,11 @@ * SSL_CLIENT_HELLO_ERROR: failure, terminate connection. Set alert to error code. * SSL_CLIENT_HELLO_SUCCESS: success * *------------------------------------------------------------------- */ - + static int HelloCallback( SSL *ssl, /* SSL context */ int *alert, /* Returned alert message */ void *arg) /* Client state for TLS socket */ @@ -995,11 +995,11 @@ * Side effects: * constructs and destroys SSL context (CTX) * *------------------------------------------------------------------- */ - + static const char *protocols[] = { "ssl2", "ssl3", "tls1", "tls1.1", "tls1.2", "tls1.3", NULL }; enum protocol { TLS_SSL2, TLS_SSL3, TLS_TLS1, TLS_TLS1_1, TLS_TLS1_2, TLS_TLS1_3, TLS_NONE @@ -1612,14 +1612,14 @@ /* Enable Application-Layer Protocol Negotiation. Examples are: http/1.0, http/1.1, h2, h3, ftp, imap, pop3, xmpp-client, xmpp-server, mqtt, irc, etc. */ if (alpn) { /* Convert a TCL list into a protocol-list in wire-format */ - unsigned char *protos, *p; + unsigned char *protos = NULL, *p; unsigned int protos_len = 0; Tcl_Size cnt, i; - int j; + int res = TCL_OK; Tcl_Obj **list; if (Tcl_ListObjGetElements(interp, alpn, &cnt, &list) != TCL_OK) { Tls_Free((tls_free_type *) statePtr); return TCL_ERROR; @@ -1629,21 +1629,21 @@ for (i = 0; i < cnt; i++) { Tcl_GetStringFromObj(list[i], &len); if (len > 255) { Tcl_AppendResult(interp, "ALPN protocol names too long", (char *)NULL); Tcl_SetErrorCode(interp, "TLS", "IMPORT", "ALPN", "FAILED", (char *)NULL); - Tls_Free((tls_free_type *) statePtr); - return TCL_ERROR; + res = TCL_ERROR; + goto done; } protos_len += 1 + (int) len; } /* Build the complete protocol-list */ protos = ckalloc(protos_len); /* protocol-lists consist of 8-bit length-prefixed, byte strings */ - for (j = 0, p = protos; j < cnt; j++) { - char *str = Tcl_GetStringFromObj(list[j], &len); + for (i = 0, p = protos; i < cnt; i++) { + char *str = Tcl_GetStringFromObj(list[i], &len); *p++ = (unsigned char) len; memcpy(p, str, (size_t) len); p += len; } @@ -1650,12 +1650,23 @@ /* SSL_set_alpn_protos makes a copy of the protocol-list */ /* Note: This function reverses the return value convention */ if (SSL_set_alpn_protos(statePtr->ssl, protos, protos_len)) { Tcl_AppendResult(interp, "Set ALPN protocols failed: ", GET_ERR_REASON(), (char *)NULL); Tcl_SetErrorCode(interp, "TLS", "IMPORT", "ALPN", "FAILED", (char *)NULL); + res = TCL_ERROR; + } + +done: for (i = 0; i < cnt; i++) { + Tcl_IncrRefCount(list[i]); + Tcl_DecrRefCount(list[i]); + } + + if (res != TCL_OK) { Tls_Free((tls_free_type *) statePtr); - ckfree(protos); + if (protos != NULL) { + ckfree(protos); + } return TCL_ERROR; } /* Store protocols list */ statePtr->protos = protos; @@ -1845,11 +1856,11 @@ * Side effects: * Loads CA certificates * *------------------------------------------------------------------- */ - + static int TlsLoadClientCAFileFromMemory( Tcl_Interp *interp, /* Tcl interpreter */ SSL_CTX *ctx, /* CTX context */ Tcl_Obj *file) /* CA certificates filename */ @@ -2341,14 +2352,15 @@ Tcl_Obj *cafileobj = Tcl_NewStringObj(CAfile, -1); Tcl_IncrRefCount(cafileobj); Tcl_Obj *fsinfo = Tcl_FSFileSystemInfo(cafileobj); if (fsinfo) { + Tcl_Obj *fstype = NULL; Tcl_IncrRefCount(fsinfo); - Tcl_Obj *fstype = NULL; Tcl_ListObjIndex(interp, fsinfo, 0, &fstype); + Tcl_IncrRefCount(fstype); if (Tcl_StringMatch("native", Tcl_GetString(fstype))) { if (!SSL_CTX_load_verify_file(ctx, F2N(CAfile, &ds))) { abort++; } @@ -2365,10 +2377,11 @@ /* Load certificate into memory */ if (!TlsLoadClientCAFileFromMemory(interp, ctx, cafileobj)) { abort++; } } + Tcl_DecrRefCount(fstype); Tcl_DecrRefCount(fsinfo); } else { abort++; /* Path is not recognized */ } @@ -2394,11 +2407,11 @@ * Side effects: * None. * *------------------------------------------------------------------- */ - + static int StatusObjCmd( TCL_UNUSED(ClientData), /* Client data */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Arg count */ @@ -2801,11 +2814,11 @@ * Side effects: * None. * *------------------------------------------------------------------- */ - + static int VersionObjCmd( TCL_UNUSED(ClientData), /* Client data */ Tcl_Interp *interp, /* Tcl interpreter */ TCL_UNUSED(int), /* objc - Arg count */ @@ -2832,11 +2845,11 @@ * Side effects: * None. * *------------------------------------------------------------------- */ - + static int MiscObjCmd( TCL_UNUSED(ClientData), /* Client data */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Arg count */ @@ -2844,10 +2857,11 @@ { static const char *commands [] = { "req", "strreq", NULL }; enum command { C_REQ, C_STRREQ, C_DUMMY }; int cmd, isStr; char buffer[16384]; + int res = TCL_OK; dprintf("Called"); if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?"); @@ -2869,11 +2883,11 @@ Tcl_Obj **listv; Tcl_Size listc, i; BIO *out=NULL; - const char *k_C="",*k_ST="",*k_L="",*k_O="",*k_OU="",*k_CN="",*k_Email=""; + Tcl_Obj *k_C=NULL,*k_ST=NULL,*k_L=NULL,*k_O=NULL,*k_OU=NULL,*k_CN=NULL,*k_Email=NULL; char *keyout,*pemout,*str; int keysize,serial=0,days=365; #if OPENSSL_VERSION_NUMBER < 0x30000000L BIGNUM *bne = NULL; @@ -2902,38 +2916,57 @@ return TCL_ERROR; } if ((listc%2) != 0) { Tcl_SetResult(interp,"Information list must have even number of arguments",NULL); - return TCL_ERROR; + res = TCL_ERROR; } for (i=0; i