Index: generic/tls.c ================================================================== --- generic/tls.c +++ generic/tls.c @@ -33,13 +33,10 @@ /* Min OpenSSL version */ #if OPENSSL_VERSION_NUMBER < 0x10101000L #error "Only OpenSSL v1.1.1 or later is supported" #endif -/* - * External functions - */ /* * Forward declarations */ @@ -332,11 +329,11 @@ * behavior when the SSL_VERIFY_PEER flag is set. This is called * whenever a certificate is inspected or decided invalid. Called for * each certificate in the cert chain. * * Checks: - * certificate chain is checked starting with the deepest nesting level + * The certificate chain is checked starting with the deepest nesting level * (the root CA certificate) and worked upward to the peer's certificate. * All signatures are valid, current time is within first and last validity time. * Check that the certificate is issued by the issuer certificate issuer. * Check the revocation status for each certificate. * Check the validity of the given CRL and the cert revocation status. @@ -404,19 +401,19 @@ Tcl_DecrRefCount(cmdPtr); dprintf("VerifyCallback: command result = %d", ok); /* statePtr->flags &= ~(TLS_TCL_CALLBACK); */ - return(ok); /* By default, leave verification unchanged. */ + return ok; /* By default, leave verification unchanged. */ } /* *------------------------------------------------------------------- * * Tls_Error -- * - * Calls callback with list of errors. + * Calls callback with error message. * * Side effects: * The err field of the currently operative State is set * to a string describing the SSL negotiation failure reason * @@ -487,13 +484,13 @@ /* *------------------------------------------------------------------- * * Password Callback -- * - * 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. + * Called when a password is needed for a private key when loading + * or storing a PEM certificate with encryption. Evals callback + * script and returns the result as the password string in buf. * * Results: * None * * Side effects: @@ -508,19 +505,24 @@ PasswordCallback(char *buf, int size, int rwflag, void *udata) { State *statePtr = (State *) udata; Tcl_Interp *interp = statePtr->interp; Tcl_Obj *cmdPtr; int code; + Tcl_Size len; dprintf("Called"); /* If no callback, use default callback */ if (statePtr->password == NULL) { if (Tcl_EvalEx(interp, "tls::password", -1, TCL_EVAL_GLOBAL) == TCL_OK) { - char *ret = (char *) Tcl_GetStringResult(interp); - strncpy(buf, ret, (size_t) size); - return (int)strlen(ret); + char *ret = (char *) Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &len); + if (len > (Tcl_Size) size-1) { + len = (Tcl_Size) size-1; + } + strncpy(buf, ret, (size_t) len); + buf[len] = '\0'; + return (int) len; } else { return -1; } } @@ -547,19 +549,18 @@ Tcl_Release((void *) statePtr); /* If successful, pass back password string and truncate if too long */ if (code == TCL_OK) { - Tcl_Size len; char *ret = (char *) Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &len); if (len > (Tcl_Size) size-1) { len = (Tcl_Size) size-1; } strncpy(buf, ret, (size_t) len); buf[len] = '\0'; Tcl_Release((void *) interp); - return((int) len); + return (int) len; } Tcl_Release((void *) interp); return -1; } @@ -623,10 +624,12 @@ /* Eval callback command */ Tcl_IncrRefCount(cmdPtr); EvalCallback(interp, statePtr, cmdPtr); Tcl_DecrRefCount(cmdPtr); + + /* Return 0 for now until session handling is complete */ return 0; } /* *------------------------------------------------------------------- @@ -915,10 +918,14 @@ } Tcl_DecrRefCount(cmdPtr); return res; } +/********************/ +/* Commands */ +/********************/ + /* *------------------------------------------------------------------- * * CiphersObjCmd -- list available ciphers * @@ -1013,15 +1020,17 @@ #endif default: method = TLS_method(); break; } + ctx = SSL_CTX_new(method); if (ctx == NULL) { Tcl_AppendResult(interp, GET_ERR_REASON(), (char *)NULL); return TCL_ERROR; } + ssl = SSL_new(ctx); if (ssl == NULL) { Tcl_AppendResult(interp, GET_ERR_REASON(), (char *)NULL); SSL_CTX_free(ctx); return TCL_ERROR; @@ -1157,27 +1166,27 @@ dprintf("Called"); if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channel"); - return(TCL_ERROR); + return TCL_ERROR; } ERR_clear_error(); chan = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), NULL); if (chan == (Tcl_Channel) NULL) { - return(TCL_ERROR); + return TCL_ERROR; } /* Make sure to operate on the topmost channel */ chan = Tcl_GetTopChannel(chan); if (Tcl_GetChannelType(chan) != Tls_ChannelType()) { Tcl_AppendResult(interp, "bad channel \"", Tcl_GetChannelName(chan), "\": not a TLS channel", (char *)NULL); Tcl_SetErrorCode(interp, "TLS", "HANDSHAKE", "CHANNEL", "INVALID", (char *)NULL); - return(TCL_ERROR); + return TCL_ERROR; } statePtr = (State *)Tcl_GetChannelInstanceData(chan); dprintf("Calling Tls_WaitForConnect"); ret = Tls_WaitForConnect(statePtr, &err, 1); @@ -1200,21 +1209,21 @@ if ((result = SSL_get_verify_result(statePtr->ssl)) != X509_V_OK) { Tcl_AppendResult(interp, " due to \"", X509_verify_cert_error_string(result), "\"", (char *)NULL); } Tcl_SetErrorCode(interp, "TLS", "HANDSHAKE", "FAILED", (char *)NULL); dprintf("Returning TCL_ERROR with handshake failed: %s", errStr); - return(TCL_ERROR); + return TCL_ERROR; } else { if (err != 0) { dprintf("Got an error with a completed handshake: err = %i", err); } ret = 1; } dprintf("Returning TCL_OK with data \"%i\"", ret); Tcl_SetObjResult(interp, Tcl_NewIntObj(ret)); - return(TCL_OK); + return TCL_OK; } /* *------------------------------------------------------------------- * @@ -1296,13 +1305,11 @@ chan = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), NULL); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } - /* - * Make sure to operate on the topmost channel - */ + /* Make sure to operate on the topmost channel */ chan = Tcl_GetTopChannel(chan); for (idx = 2; idx < objc; idx++) { char *opt = Tcl_GetString(objv[idx]); @@ -1470,11 +1477,10 @@ Tcl_DStringFree(&upperChannelBlocking); /* * SSL Initialization */ - statePtr->ssl = SSL_new(statePtr->ctx); if (!statePtr->ssl) { /* SSL library error */ Tcl_AppendResult(interp, "couldn't construct ssl session: ", GET_ERR_REASON(), (char *)NULL); Tcl_SetErrorCode(interp, "TLS", "IMPORT", "INIT", "FAILED", (char *)NULL); @@ -1551,11 +1557,11 @@ memcpy(p, str, (size_t) len); p += len; } /* SSL_set_alpn_protos makes a copy of the protocol-list */ - /* Note: This functions reverses the return value convention */ + /* 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); Tls_Free((void *)statePtr); ckfree(protos); @@ -1682,13 +1688,11 @@ chan = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), NULL); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } - /* - * Make sure to operate on the topmost channel - */ + /* Make sure to operate on the topmost channel */ chan = Tcl_GetTopChannel(chan); if (Tcl_GetChannelType(chan) != Tls_ChannelType()) { Tcl_AppendResult(interp, "bad channel \"", Tcl_GetChannelName(chan), "\": not a TLS channel", (char *)NULL); @@ -1756,29 +1760,29 @@ } if (ENABLED(proto, TLS_PROTO_SSL3)) { Tcl_AppendResult(interp, "SSL3 protocol not supported", (char *)NULL); return NULL; } -#if defined(NO_TLS1) || defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD) +#if defined(NO_TLS1) || defined(OPENSSL_NO_TLS1) if (ENABLED(proto, TLS_PROTO_TLS1)) { Tcl_AppendResult(interp, "TLS 1.0 protocol not supported", (char *)NULL); return NULL; } #endif -#if defined(NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD) +#if defined(NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1) if (ENABLED(proto, TLS_PROTO_TLS1_1)) { Tcl_AppendResult(interp, "TLS 1.1 protocol not supported", (char *)NULL); return NULL; } #endif -#if defined(NO_TLS1_2) || defined(OPENSSL_NO_TLS1_2) || defined(OPENSSL_NO_TLS1_2_METHOD) +#if defined(NO_TLS1_2) || defined(OPENSSL_NO_TLS1_2) if (ENABLED(proto, TLS_PROTO_TLS1_2)) { Tcl_AppendResult(interp, "TLS 1.2 protocol not supported", (char *)NULL); return NULL; } #endif -#if defined(NO_TLS1_3) || defined(OPENSSL_NO_TLS1_3) || defined(OPENSSL_NO_TLS1_3_METHOD) +#if defined(NO_TLS1_3) || defined(OPENSSL_NO_TLS1_3) if (ENABLED(proto, TLS_PROTO_TLS1_3)) { Tcl_AppendResult(interp, "TLS 1.3 protocol not supported", (char *)NULL); return NULL; } #endif @@ -1802,39 +1806,39 @@ #if !defined(NO_TLS1_2) && !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_TLS1_2_METHOD) case TLS_PROTO_TLS1_2: method = isServer ? TLSv1_2_server_method() : TLSv1_2_client_method(); break; #endif -#if !defined(NO_TLS1_3) && !defined(OPENSSL_NO_TLS1_3) && !defined(OPENSSL_NO_TLS1_3_METHOD) +#if !defined(NO_TLS1_3) && !defined(OPENSSL_NO_TLS1_3) case TLS_PROTO_TLS1_3: /* Use the generic method and constraint range after context is created */ method = isServer ? TLS_server_method() : TLS_client_method(); break; #endif default: /* Negotiate highest available SSL/TLS version */ method = isServer ? TLS_server_method() : TLS_client_method(); -#if !defined(NO_TLS1) && !defined(OPENSSL_NO_TLS1) && !defined(OPENSSL_NO_TLS1_METHOD) +#if !defined(NO_TLS1) && !defined(OPENSSL_NO_TLS1) off |= (ENABLED(proto, TLS_PROTO_TLS1) ? 0 : SSL_OP_NO_TLSv1); #endif -#if !defined(NO_TLS1_1) && !defined(OPENSSL_NO_TLS1_1) && !defined(OPENSSL_NO_TLS1_1_METHOD) +#if !defined(NO_TLS1_1) && !defined(OPENSSL_NO_TLS1_1) off |= (ENABLED(proto, TLS_PROTO_TLS1_1) ? 0 : SSL_OP_NO_TLSv1_1); #endif -#if !defined(NO_TLS1_2) && !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_TLS1_2_METHOD) +#if !defined(NO_TLS1_2) && !defined(OPENSSL_NO_TLS1_2) off |= (ENABLED(proto, TLS_PROTO_TLS1_2) ? 0 : SSL_OP_NO_TLSv1_2); #endif -#if !defined(NO_TLS1_3) && !defined(OPENSSL_NO_TLS1_3) && !defined(OPENSSL_NO_TLS1_3_METHOD) +#if !defined(NO_TLS1_3) && !defined(OPENSSL_NO_TLS1_3) off |= (ENABLED(proto, TLS_PROTO_TLS1_3) ? 0 : SSL_OP_NO_TLSv1_3); #endif break; } ERR_clear_error(); ctx = SSL_CTX_new(method); if (!ctx) { - return(NULL); + return NULL; } if (getenv(SSLKEYLOGFILE)) { SSL_CTX_set_keylog_callback(ctx, KeyLogCallback); } @@ -1878,10 +1882,11 @@ /* set some callbacks */ SSL_CTX_set_default_passwd_cb(ctx, PasswordCallback); SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)statePtr); /* read a Diffie-Hellman parameters file, or use the built-in one */ + Tcl_DStringInit(&ds); #ifdef OPENSSL_NO_DH if (DHparams != NULL) { Tcl_AppendResult(interp, "DH parameter support not available", (char *)NULL); SSL_CTX_free(ctx); return NULL; @@ -1889,10 +1894,11 @@ #else { DH* dh; if (DHparams != NULL) { BIO *bio; + bio = BIO_new_file(F2N(DHparams, &ds), "r"); if (!bio) { Tcl_DStringFree(&ds); Tcl_AppendResult(interp, "Could not find DH parameters file", (char *)NULL); SSL_CTX_free(ctx); @@ -1987,13 +1993,12 @@ } } /* Now we know that a key and cert have been set against * the SSL context */ if (!SSL_CTX_check_private_key(ctx)) { - Tcl_AppendResult(interp, - "private key does not match the certificate public key", - (char *)NULL); + Tcl_AppendResult(interp, "private key does not match the certificate public key", + (char *)NULL); SSL_CTX_free(ctx); return NULL; } } @@ -2007,10 +2012,12 @@ /* Overrides for the CA verify path and file */ { #if OPENSSL_VERSION_NUMBER < 0x30000000L if (CApath != NULL || CAfile != NULL) { Tcl_DString ds1; + Tcl_DStringInit(&ds1); + if (!SSL_CTX_load_verify_locations(ctx, F2N(CAfile, &ds), F2N(CApath, &ds1))) { abort++; } Tcl_DStringFree(&ds); Tcl_DStringFree(&ds1); @@ -2086,18 +2093,18 @@ if (objc < 2 || objc > 3 || (objc == 3 && !strcmp(Tcl_GetString(objv[1]), "-local"))) { Tcl_WrongNumArgs(interp, 1, objv, "?-local? channel"); return TCL_ERROR; } + /* Get channel Id */ channelName = Tcl_GetString(objv[(objc == 2 ? 1 : 2)]); chan = Tcl_GetChannel(interp, channelName, &mode); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } - /* - * Make sure to operate on the topmost channel - */ + + /* Make sure to operate on the topmost channel */ chan = Tcl_GetTopChannel(chan); if (Tcl_GetChannelType(chan) != Tls_ChannelType()) { Tcl_AppendResult(interp, "bad channel \"", Tcl_GetChannelName(chan), "\": not a TLS channel", (char *)NULL); Tcl_SetErrorCode(interp, "TLS", "STATUS", "CHANNEL", "INVALID", (char *)NULL); @@ -2208,25 +2215,25 @@ const SSL_SESSION *session; const EVP_MD *md; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "channel"); - return(TCL_ERROR); + return TCL_ERROR; } chan = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), NULL); if (chan == (Tcl_Channel) NULL) { - return(TCL_ERROR); + return TCL_ERROR; } /* Make sure to operate on the topmost channel */ chan = Tcl_GetTopChannel(chan); if (Tcl_GetChannelType(chan) != Tls_ChannelType()) { Tcl_AppendResult(interp, "bad channel \"", Tcl_GetChannelName(chan), - "\": not a TLS channel", NULL); + "\": not a TLS channel", (char *)NULL); Tcl_SetErrorCode(interp, "TLS", "CONNECTION", "CHANNEL", "INVALID", (char *)NULL); - return(TCL_ERROR); + return TCL_ERROR; } objPtr = Tcl_NewListObj(0, NULL); /* Connection info */ @@ -2482,12 +2489,11 @@ if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?args?"); return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], commands, - "command", 0,&cmd) != TCL_OK) { + if (Tcl_GetIndexFromObj(interp, objv[1], commands, "command", 0, &cmd) != TCL_OK) { return TCL_ERROR; } ERR_clear_error(); @@ -2608,11 +2614,11 @@ Tcl_SetResult(interp,"Error generating certificate request",NULL); EVP_PKEY_free(pkey); #if OPENSSL_VERSION_NUMBER < 0x30000000L BN_free(bne); #endif - return(TCL_ERROR); + return TCL_ERROR; } X509_set_version(cert,2); ASN1_INTEGER_set(X509_get_serialNumber(cert),serial); X509_gmtime_adj(X509_getm_notBefore(cert),0); @@ -2619,17 +2625,17 @@ X509_gmtime_adj(X509_getm_notAfter(cert),(long)60*60*24*days); X509_set_pubkey(cert,pkey); name=X509_get_subject_name(cert); - X509_NAME_add_entry_by_txt(name,"C", MBSTRING_ASC, (unsigned char *) k_C, -1, -1, 0); - X509_NAME_add_entry_by_txt(name,"ST", MBSTRING_ASC, (unsigned char *) k_ST, -1, -1, 0); - X509_NAME_add_entry_by_txt(name,"L", MBSTRING_ASC, (unsigned char *) k_L, -1, -1, 0); - X509_NAME_add_entry_by_txt(name,"O", MBSTRING_ASC, (unsigned char *) k_O, -1, -1, 0); - X509_NAME_add_entry_by_txt(name,"OU", MBSTRING_ASC, (unsigned char *) k_OU, -1, -1, 0); - X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC, (unsigned char *) k_CN, -1, -1, 0); - X509_NAME_add_entry_by_txt(name,"Email", MBSTRING_ASC, (unsigned char *) k_Email, -1, -1, 0); + X509_NAME_add_entry_by_txt(name,"C", MBSTRING_ASC, (const unsigned char *) k_C, -1, -1, 0); + X509_NAME_add_entry_by_txt(name,"ST", MBSTRING_ASC, (const unsigned char *) k_ST, -1, -1, 0); + X509_NAME_add_entry_by_txt(name,"L", MBSTRING_ASC, (const unsigned char *) k_L, -1, -1, 0); + X509_NAME_add_entry_by_txt(name,"O", MBSTRING_ASC, (const unsigned char *) k_O, -1, -1, 0); + X509_NAME_add_entry_by_txt(name,"OU", MBSTRING_ASC, (const unsigned char *) k_OU, -1, -1, 0); + X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC, (const unsigned char *) k_CN, -1, -1, 0); + X509_NAME_add_entry_by_txt(name,"Email", MBSTRING_ASC, (const unsigned char *) k_Email, -1, -1, 0); X509_set_subject_name(cert,name); if (!X509_sign(cert,pkey,EVP_sha256())) { X509_free(cert); @@ -2907,11 +2913,11 @@ *------------------------------------------------------* */ DLLEXPORT int Tls_SafeInit(Tcl_Interp *interp) { dprintf("Called"); - return(Tls_Init(interp)); + return Tls_Init(interp); } /* *------------------------------------------------------* * @@ -2938,11 +2944,11 @@ if (uninitialize) { if (!initialized) { dprintf("Asked to uninitialize, but we are not initialized"); - return(TCL_OK); + return TCL_OK; } dprintf("Asked to uninitialize"); #if defined(OPENSSL_THREADS) && defined(TCL_THREADS) @@ -2958,16 +2964,16 @@ #if defined(OPENSSL_THREADS) && defined(TCL_THREADS) Tcl_MutexUnlock(&init_mx); #endif - return(TCL_OK); + return TCL_OK; } if (initialized) { dprintf("Called, but using cached value"); - return(status); + return status; } dprintf("Called"); #if defined(OPENSSL_THREADS) && defined(TCL_THREADS) @@ -2990,7 +2996,7 @@ #if defined(OPENSSL_THREADS) && defined(TCL_THREADS) Tcl_MutexUnlock(&init_mx); #endif - return(status); + return status; } Index: generic/tlsBIO.c ================================================================== --- generic/tlsBIO.c +++ generic/tlsBIO.c @@ -25,10 +25,11 @@ #define BIO_meth_set_ctrl(bio, val) (bio)->ctrl = val; #define BIO_meth_set_create(bio, val) (bio)->create = val; #define BIO_meth_set_destroy(bio, val) (bio)->destroy = val; #endif +/* Called by SSL_write() */ static int BioWrite(BIO *bio, const char *buf, int bufLen) { Tcl_Channel chan; Tcl_Size ret; int tclEofChan, tclErrno; @@ -48,22 +49,25 @@ if (tclEofChan && ret <= 0) { dprintf("Got EOF while reading, returning a Connection Reset error which maps to Soft EOF"); Tcl_SetErrno(ECONNRESET); ret = 0; + } else if (ret == 0) { dprintf("Got 0 from Tcl_WriteRaw, and EOF is not set; ret = 0"); dprintf("Setting retry read flag"); BIO_set_retry_read(bio); + } else if (ret < 0) { dprintf("We got some kind of I/O error"); if (tclErrno == EAGAIN) { dprintf("It's EAGAIN"); } else { dprintf("It's an unexpected error: %s/%i", Tcl_ErrnoMsg(tclErrno), tclErrno); } + } else { dprintf("Successfully wrote %" TCL_SIZE_MODIFIER "d bytes of data", ret); } if (ret != -1 || (ret == -1 && tclErrno == EAGAIN)) { @@ -102,22 +106,25 @@ if (tclEofChan && ret <= 0) { dprintf("Got EOF while reading, returning a Connection Reset error which maps to Soft EOF"); Tcl_SetErrno(ECONNRESET); ret = 0; + } else if (ret == 0) { dprintf("Got 0 from Tcl_Read or Tcl_ReadRaw, and EOF is not set; ret = 0"); dprintf("Setting retry read flag"); BIO_set_retry_read(bio); + } else if (ret < 0) { dprintf("We got some kind of I/O error"); if (tclErrno == EAGAIN) { dprintf("It's EAGAIN"); } else { dprintf("It's an unexpected error: %s/%i", Tcl_ErrnoMsg(tclErrno), tclErrno); } + } else { dprintf("Successfully read %" TCL_SIZE_MODIFIER "d bytes of data", ret); } if (ret != -1 || (ret == -1 && tclErrno == EAGAIN)) { @@ -238,11 +245,11 @@ ret = 0; break; #endif default: dprintf("Got unknown control command (%i)", cmd); - ret = -2; + ret = 0; break; } return ret; } @@ -255,11 +262,11 @@ return 1; } static int BioFree(BIO *bio) { if (bio == NULL) { - return(0); + return 0; } dprintf("BioFree(%p) called", bio); if (BIO_get_shutdown(bio)) { @@ -302,11 +309,11 @@ } if (statePtr == NULL) { dprintf("Asked to setup a NULL state, just creating the initial configuration"); - return(NULL); + return NULL; } #ifdef TCLTLS_SSL_USE_FASTPATH /* * If the channel can be mapped back to a file descriptor, just use the file descriptor @@ -333,17 +340,17 @@ if (validParentChannelFd) { dprintf("We found a shortcut, this channel is backed by a socket: %i", parentChannelFdIn); bio = BIO_new_socket(parentChannelFd, flags); statePtr->flags |= TLS_TCL_FASTPATH; - return(bio); + return bio; } dprintf("Falling back to Tcl I/O for this channel"); #endif bio = BIO_new(BioMethods); BIO_set_data(bio, statePtr); BIO_set_shutdown(bio, flags); BIO_set_init(bio, 1); - return(bio); + return bio; } Index: generic/tlsIO.c ================================================================== --- generic/tlsIO.c +++ generic/tlsIO.c @@ -46,11 +46,11 @@ if (mode == TCL_MODE_NONBLOCKING) { statePtr->flags |= TLS_TCL_ASYNC; } else { statePtr->flags &= ~(TLS_TCL_ASYNC); } - return(0); + return 0; } /* *------------------------------------------------------------------- * @@ -126,11 +126,11 @@ dprintf("WaitForConnect(%p)", statePtr); dprintFlags(statePtr); if (!(statePtr->flags & TLS_TCL_INIT)) { dprintf("Tls_WaitForConnect called on already initialized channel -- returning with immediate success"); - return(0); + return 0; } if (statePtr->flags & TLS_TCL_HANDSHAKE_FAILED) { /* * Different types of operations have different requirements @@ -142,20 +142,21 @@ } else { dprintf("Asked to wait for a TLS handshake that has already failed. Returning soft error"); *errorCodePtr = ECONNRESET; } Tls_Error(statePtr, "Wait for failed handshake"); - return(-1); + return -1; } for (;;) { ERR_clear_error(); /* Not initialized yet! Also calls SSL_do_handshake. */ if (statePtr->flags & TLS_TCL_SERVER) { dprintf("Calling SSL_accept()"); err = SSL_accept(statePtr->ssl); + } else { dprintf("Calling SSL_connect()"); err = SSL_connect(statePtr->ssl); } @@ -197,11 +198,11 @@ if (statePtr->flags & TLS_TCL_ASYNC) { dprintf("Returning EAGAIN so that it can be retried later"); *errorCodePtr = EAGAIN; Tls_Error(statePtr, "Handshake not complete, will retry later"); - return(-1); + return -1; } else { dprintf("Doing so now"); continue; } } @@ -214,16 +215,17 @@ case SSL_ERROR_NONE: /* The TLS/SSL I/O operation completed */ dprintf("The connection is good"); *errorCodePtr = 0; break; + case SSL_ERROR_ZERO_RETURN: /* The TLS/SSL peer has closed the connection for writing by sending the close_notify alert */ dprintf("SSL_ERROR_ZERO_RETURN: Connect returned an invalid value..."); *errorCodePtr = EINVAL; Tls_Error(statePtr, "Peer has closed the connection for writing by sending the close_notify alert"); - return(-1); + return -1; case SSL_ERROR_SYSCALL: /* Some non-recoverable, fatal I/O error occurred */ dprintf("SSL_ERROR_SYSCALL"); @@ -249,10 +251,11 @@ Tls_Error(statePtr, (char *) ERR_reason_error_string(backingError)); } statePtr->flags |= TLS_TCL_HANDSHAKE_FAILED; return -1; + case SSL_ERROR_SSL: /* A non-recoverable, fatal error in the SSL library occurred, usually a protocol error */ dprintf("SSL_ERROR_SSL: Got permanent fatal SSL error, aborting immediately"); if (SSL_get_verify_result(statePtr->ssl) != X509_V_OK) { Tls_Error(statePtr, (char *) X509_verify_cert_error_string(SSL_get_verify_result(statePtr->ssl))); @@ -260,18 +263,18 @@ if (backingError != 0) { Tls_Error(statePtr, (char *) ERR_reason_error_string(backingError)); } statePtr->flags |= TLS_TCL_HANDSHAKE_FAILED; *errorCodePtr = ECONNABORTED; - return(-1); + return -1; default: /* The operation did not complete and should be retried later. */ dprintf("Operation did not complete, call function again later: %i", rc); *errorCodePtr = EAGAIN; dprintf("ERR(%d, %d) ", rc, *errorCodePtr); Tls_Error(statePtr, "Operation did not complete, call function again later"); - return(-1); + return -1; } dprintf("Removing the \"TLS_TCL_INIT\" flag since we have completed the handshake"); statePtr->flags &= ~TLS_TCL_INIT; @@ -315,11 +318,11 @@ dprintf("BIO_read(%d)", bufSize); if (statePtr->flags & TLS_TCL_CALLBACK) { /* don't process any bytes while verify callback is running */ dprintf("Callback is running, reading 0 bytes"); - return(0); + return 0; } dprintf("Calling Tls_WaitForConnect"); tlsConnect = Tls_WaitForConnect(statePtr, errorCodePtr, 0); if (tlsConnect < 0) { @@ -331,11 +334,11 @@ dprintf("Got connection reset"); /* Soft EOF */ *errorCodePtr = 0; bytesRead = 0; } - return(bytesRead); + return bytesRead; } /* * We need to clear the SSL error stack now because we sometimes reach * this function with leftover errors in the stack. If BIO_read @@ -365,10 +368,11 @@ switch (err) { case SSL_ERROR_NONE: dprintBuffer(buf, bytesRead); break; + case SSL_ERROR_SSL: /* A non-recoverable, fatal error in the SSL library occurred, usually a protocol error */ dprintf("SSL error, indicating that the connection has been aborted"); if (backingError != 0) { Tls_Error(statePtr, (char *) ERR_reason_error_string(backingError)); @@ -477,11 +481,11 @@ if (statePtr->flags & TLS_TCL_CALLBACK) { dprintf("Don't process output while callbacks are running"); written = -1; *errorCodePtr = EAGAIN; - return(-1); + return -1; } dprintf("Calling Tls_WaitForConnect"); tlsConnect = Tls_WaitForConnect(statePtr, errorCodePtr, 1); if (tlsConnect < 0) { @@ -493,11 +497,11 @@ dprintf("Got connection reset"); /* Soft EOF */ *errorCodePtr = 0; written = 0; } - return(written); + return written; } if (toWrite == 0) { dprintf("zero-write"); err = BIO_flush(statePtr->bio); @@ -506,16 +510,16 @@ dprintf("Flushing failed"); Tls_Error(statePtr, "Flush failed"); *errorCodePtr = EIO; written = 0; - return(-1); + return -1; } written = 0; *errorCodePtr = 0; - return(0); + return 0; } /* * We need to clear the SSL error stack now because we sometimes reach * this function with leftover errors in the stack. If BIO_write @@ -531,36 +535,42 @@ written = BIO_write(statePtr->bio, buf, toWrite); dprintf("BIO_write(%p, %d) -> [%d]", (void *) statePtr, toWrite, written); err = SSL_get_error(statePtr->ssl, written); backingError = ERR_get_error(); + switch (err) { case SSL_ERROR_NONE: if (written < 0) { written = 0; } break; + case SSL_ERROR_WANT_WRITE: dprintf("Got SSL_ERROR_WANT_WRITE, mapping it to EAGAIN"); *errorCodePtr = EAGAIN; written = -1; Tls_Error(statePtr, "SSL_ERROR_WANT_WRITE"); break; + case SSL_ERROR_WANT_READ: dprintf(" write R BLOCK"); Tls_Error(statePtr, "SSL_ERROR_WANT_READ"); break; + case SSL_ERROR_WANT_X509_LOOKUP: dprintf(" write X BLOCK"); Tls_Error(statePtr, "SSL_ERROR_WANT_X509_LOOKUP"); break; + case SSL_ERROR_ZERO_RETURN: dprintf(" closed"); written = 0; *errorCodePtr = 0; Tls_Error(statePtr, "Peer has closed the connection for writing by sending the close_notify alert"); break; + case SSL_ERROR_SYSCALL: /* Some non-recoverable, fatal I/O error occurred */ if (backingError == 0 && written == 0) { dprintf("EOF reached") @@ -579,10 +589,11 @@ *errorCodePtr = Tcl_GetErrno(); written = -1; Tls_Error(statePtr, (char *) ERR_reason_error_string(backingError)); } break; + case SSL_ERROR_SSL: /* A non-recoverable, fatal error in the SSL library occurred, usually a protocol error */ dprintf("SSL error, indicating that the connection has been aborted"); if (backingError != 0) { Tls_Error(statePtr, (char *) ERR_reason_error_string(backingError)); @@ -592,18 +603,19 @@ Tls_Error(statePtr, "Unknown SSL error"); } *errorCodePtr = ECONNABORTED; written = -1; break; + default: dprintf("unknown error: %d", err); Tls_Error(statePtr, "Unknown error"); break; } dprintf("Output(%d) -> %d", toWrite, written); - return(written); + return written; } /* *------------------------------------------------------------------- * @@ -797,11 +809,11 @@ int direction, /* TCL_READABLE or TCL_WRITABLE */ void **handlePtr) /* Handle associated with the channel */ { State *statePtr = (State *)instanceData; - return(Tcl_GetChannelHandle(Tls_GetParent(statePtr, TLS_TCL_FASTPATH), direction, handlePtr)); + return Tcl_GetChannelHandle(Tls_GetParent(statePtr, TLS_TCL_FASTPATH), direction, handlePtr); } /* *------------------------------------------------------------------- * @@ -862,11 +874,11 @@ dprintf("Tls_WaitForConnect returned an error"); } dprintf("Returning %i", mask); - return(mask); + return mask; } /* *------------------------------------------------------* * @@ -916,11 +928,11 @@ Tcl_Channel Tls_GetParent(State *statePtr, int maskFlags) { dprintf("Requested to get parent of channel %p", statePtr->self); if ((statePtr->flags & ~maskFlags) & TLS_TCL_FASTPATH) { dprintf("Asked to get the parent channel while we are using FastPath -- returning NULL"); - return(NULL); + return NULL; } return Tcl_GetStackedChannel(statePtr->self); } /*