@@ -39,11 +39,11 @@ * Sets the device into blocking or nonblocking mode. * *------------------------------------------------------------------- */ static int TlsBlockModeProc(void *instanceData, int mode) { - State *statePtr = (State *) instanceData; + State *statePtr = (State *)instanceData; if (mode == TCL_MODE_NONBLOCKING) { statePtr->flags |= TLS_TCL_ASYNC; } else { statePtr->flags &= ~(TLS_TCL_ASYNC); @@ -231,26 +231,22 @@ *errorCodePtr = ECONNABORTED; } } statePtr->flags |= TLS_TCL_HANDSHAKE_FAILED; - return -1; case SSL_ERROR_SSL: dprintf("Got permanent fatal SSL error, aborting immediately"); Tls_Error(statePtr, (char *)ERR_reason_error_string(ERR_get_error())); statePtr->flags |= TLS_TCL_HANDSHAKE_FAILED; *errorCodePtr = ECONNABORTED; return(-1); - case SSL_ERROR_WANT_CONNECT: - case SSL_ERROR_WANT_ACCEPT: - case SSL_ERROR_WANT_X509_LOOKUP: default: dprintf("We got a confusing reply: %i", rc); *errorCodePtr = Tcl_GetErrno(); dprintf("ERR(%d, %d) ", rc, *errorCodePtr); - return(-1); + return -1; } #if 0 if (statePtr->flags & TLS_TCL_SERVER) { dprintf("This is an TLS server, checking the certificate for the peer"); @@ -298,11 +294,11 @@ char *buf, int bufSize, int *errorCodePtr) { unsigned long backingError; - State *statePtr = (State *) instanceData; + State *statePtr = (State *)instanceData; int bytesRead; int tlsConnect; int err; *errorCodePtr = 0; @@ -430,11 +426,11 @@ const char *buf, int toWrite, int *errorCodePtr) { unsigned long backingError; - State *statePtr = (State *) instanceData; + State *statePtr = (State *)instanceData; int written, err; int tlsConnect; *errorCodePtr = 0; @@ -550,10 +546,53 @@ } /* *------------------------------------------------------------------- * + * TlsSetOptionProc -- + * + * Sets an option value for a SSL socket based channel, or a + * list of all options and their values. + * + * Results: + * TCL_OK if successful or TCL_ERROR if failed. + * + * Side effects: + * Updates channel option to new value. + * + *------------------------------------------------------------------- + */ +static int +TlsSetOptionProc(void *instanceData, /* Socket state. */ + Tcl_Interp *interp, /* For errors - can be NULL. */ + const char *optionName, /* Name of the option to set the value for, or + * NULL to get all options and their values. */ + const char *optionValue) /* Value for option. */ +{ + State *statePtr = (State *)instanceData; + + Tcl_Channel downChan = Tls_GetParent(statePtr, TLS_TCL_FASTPATH); + Tcl_DriverSetOptionProc *setOptionProc; + + setOptionProc = Tcl_ChannelSetOptionProc(Tcl_GetChannelType(downChan)); + if (setOptionProc != NULL) { + return (*setOptionProc)(Tcl_GetChannelInstanceData(downChan), interp, optionName, optionValue); + } else if (optionName == (char*) NULL) { + /* + * Request is query for all options, this is ok. + */ + return TCL_OK; + } + /* + * Request for a specific option has to fail, we don't have any. + */ + return Tcl_BadChannelOption(interp, optionName, ""); +} + +/* + *------------------------------------------------------------------- + * * TlsGetOptionProc -- * * Gets an option value for a SSL socket based channel, or a * list of all options and their values. * @@ -573,11 +612,11 @@ Tcl_Interp *interp, /* For errors - can be NULL. */ const char *optionName, /* Name of the option to retrieve the value for, or * NULL to get all options and their values. */ Tcl_DString *optionValue) /* Where to store the computed value initialized by caller. */ { - State *statePtr = (State *) instanceData; + State *statePtr = (State *)instanceData; Tcl_Channel downChan = Tls_GetParent(statePtr, TLS_TCL_FASTPATH); Tcl_DriverGetOptionProc *getOptionProc; getOptionProc = Tcl_ChannelGetOptionProc(Tcl_GetChannelType(downChan)); @@ -590,11 +629,11 @@ return TCL_OK; } /* * Request for a specific option has to fail, we don't have any. */ - return TCL_ERROR; + return Tcl_BadChannelOption(interp, optionName, ""); } /* *------------------------------------------------------------------- * @@ -617,11 +656,11 @@ void *instanceData, /* The socket state. */ int mask) /* Events of interest; an OR-ed combination of * TCL_READABLE, TCL_WRITABLE and TCL_EXCEPTION. */ { Tcl_Channel downChan; - State *statePtr = (State *) instanceData; + State *statePtr = (State *)instanceData; dprintf("TlsWatchProc(0x%x)", mask); /* Pretend to be dead as long as the verify callback is running. * Otherwise that callback could be invoked recursively. */ @@ -636,11 +675,11 @@ if (statePtr->flags & TLS_TCL_HANDSHAKE_FAILED) { dprintf("Asked to watch a socket with a failed handshake -- nothing can happen here"); dprintf("Unregistering interest in the lower channel"); - (Tcl_GetChannelType(downChan))->watchProc(Tcl_GetChannelInstanceData(downChan), 0); + Tcl_GetChannelType(downChan)->watchProc(Tcl_GetChannelInstanceData(downChan), 0); statePtr->watchMask = 0; return; } statePtr->watchMask = mask; @@ -651,12 +690,11 @@ * We are allowed to add additional 'interest' to the mask if we want * to. But this transformation has no such interest. It just passes * the request down, unchanged. */ dprintf("Registering our interest in the lower channel (chan=%p)", (void *) downChan); - (Tcl_GetChannelType(downChan)) - ->watchProc(Tcl_GetChannelInstanceData(downChan), mask); + Tcl_GetChannelType(downChan)->watchProc(Tcl_GetChannelInstanceData(downChan), mask); /* * Management of the internal timer. */ if (statePtr->timer != (Tcl_TimerToken) NULL) { @@ -842,11 +880,11 @@ TCL_CHANNEL_VERSION_5, /* v5 channel */ TlsCloseProc, /* Close proc */ TlsInputProc, /* Input proc */ TlsOutputProc, /* Output proc */ 0, /* Seek proc */ - 0, /* Set option proc */ + TlsSetOptionProc, /* Set option proc */ TlsGetOptionProc, /* Get option proc */ TlsWatchProc, /* Initialize notifier */ TlsGetHandleProc, /* Get OS handles out of channel */ TlsClose2Proc, /* close2proc */ TlsBlockModeProc, /* Set blocking/nonblocking mode*/