int SSL_SOCKET :: ClientOff() { // Client wants to disconnect SECURITY_STATUS ss; Z<SecBuffer> OutBuffers(100); DWORD dwType = SCHANNEL_SHUTDOWN; OutBuffers[0].pvBuffer = &dwType; OutBuffers[0].BufferType = SECBUFFER_TOKEN; OutBuffers[0].cbBuffer = sizeof(dwType); sbout.cBuffers = 1; sbout.pBuffers = OutBuffers; sbout.ulVersion = SECBUFFER_VERSION; for(;;) { ss = ApplyControlToken(&hCtx, &sbout); if (FAILED(ss)) return -1; DWORD dwSSPIFlags; DWORD dwSSPIOutFlags; dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM; OutBuffers[0].pvBuffer = NULL; OutBuffers[0].BufferType = SECBUFFER_TOKEN; OutBuffers[0].cbBuffer = 0; sbout.cBuffers = 1; sbout.pBuffers = OutBuffers; sbout.ulVersion = SECBUFFER_VERSION; ss = InitializeSecurityContext(&hCred,&hCtx,NULL,dwSSPIFlags,0,SECURITY_NATIVE_DREP, NULL,0,&hCtx,&sbout,&dwSSPIOutFlags,0); if (FAILED(ss)) return -1; PBYTE pbMessage; DWORD cbMessage; pbMessage = (BYTE *)(OutBuffers[0].pvBuffer); cbMessage = OutBuffers[0].cbBuffer; if (pbMessage != NULL && cbMessage != 0) { int rval = ssend_p((char*)pbMessage, cbMessage); FreeContextBuffer(pbMessage); return rval; } break; } return 1; }
static int tls_shutdown_client(URLContext *h) { TLSContext *c = h->priv_data; TLSShared *s = &c->tls_shared; int ret; if (c->connected) { SecBufferDesc BuffDesc; SecBuffer Buffer; SECURITY_STATUS sspi_ret; SecBuffer outbuf; SecBufferDesc outbuf_desc; DWORD dwshut = SCHANNEL_SHUTDOWN; init_sec_buffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut)); init_sec_buffer_desc(&BuffDesc, &Buffer, 1); sspi_ret = ApplyControlToken(&c->ctxt_handle, &BuffDesc); if (sspi_ret != SEC_E_OK) av_log(h, AV_LOG_ERROR, "ApplyControlToken failed\n"); init_sec_buffer(&outbuf, SECBUFFER_EMPTY, NULL, 0); init_sec_buffer_desc(&outbuf_desc, &outbuf, 1); sspi_ret = InitializeSecurityContext(&c->cred_handle, &c->ctxt_handle, s->host, c->request_flags, 0, 0, NULL, 0, &c->ctxt_handle, &outbuf_desc, &c->context_flags, &c->ctxt_timestamp); if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_CONTEXT_EXPIRED) { ret = ffurl_write(s->tcp, outbuf.pvBuffer, outbuf.cbBuffer); FreeContextBuffer(outbuf.pvBuffer); if (ret < 0 || ret != outbuf.cbBuffer) av_log(h, AV_LOG_ERROR, "Failed to send close message\n"); } c->connected = 0; } return 0; }
/* * '_sspiFree()' - Close a connection and free resources */ void _sspiFree(_sspi_struct_t *conn) /* I - Client connection */ { if (!conn) return; if (conn->contextInitialized) { SecBufferDesc message; /* Array of SecBuffer struct */ SecBuffer buffers[1] = { 0 }; /* Security package buffer */ DWORD dwType; /* Type */ DWORD status; /* Status */ /* * Notify schannel that we are about to close the connection. */ dwType = SCHANNEL_SHUTDOWN; buffers[0].pvBuffer = &dwType; buffers[0].BufferType = SECBUFFER_TOKEN; buffers[0].cbBuffer = sizeof(dwType); message.cBuffers = 1; message.pBuffers = buffers; message.ulVersion = SECBUFFER_VERSION; status = ApplyControlToken(&conn->context, &message); if (SUCCEEDED(status)) { PBYTE pbMessage; /* Message buffer */ DWORD cbMessage; /* Message buffer count */ DWORD cbData; /* Data count */ DWORD dwSSPIFlags; /* SSL attributes we requested */ DWORD dwSSPIOutFlags; /* SSL attributes we received */ TimeStamp tsExpiry; /* Time stamp */ dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT | ASC_REQ_CONFIDENTIALITY | ASC_REQ_EXTENDED_ERROR | ASC_REQ_ALLOCATE_MEMORY | ASC_REQ_STREAM; buffers[0].pvBuffer = NULL; buffers[0].BufferType = SECBUFFER_TOKEN; buffers[0].cbBuffer = 0; message.cBuffers = 1; message.pBuffers = buffers; message.ulVersion = SECBUFFER_VERSION; status = AcceptSecurityContext(&conn->creds, &conn->context, NULL, dwSSPIFlags, SECURITY_NATIVE_DREP, NULL, &message, &dwSSPIOutFlags, &tsExpiry); if (SUCCEEDED(status)) { pbMessage = buffers[0].pvBuffer; cbMessage = buffers[0].cbBuffer; /* * Send the close notify message to the client. */ if (pbMessage && cbMessage) { cbData = send(conn->sock, pbMessage, cbMessage, 0); if ((cbData == SOCKET_ERROR) || (cbData == 0)) { status = WSAGetLastError(); DEBUG_printf(("_sspiFree: sending close notify failed: %d", status)); } else { FreeContextBuffer(pbMessage); } } } else { DEBUG_printf(("_sspiFree: AcceptSecurityContext failed: %x", status)); } } else { DEBUG_printf(("_sspiFree: ApplyControlToken failed: %x", status)); } DeleteSecurityContext(&conn->context); conn->contextInitialized = FALSE; } if (conn->decryptBuffer) { free(conn->decryptBuffer); conn->decryptBuffer = NULL; } if (conn->readBuffer) { free(conn->readBuffer); conn->readBuffer = NULL; } if (conn->sock != INVALID_SOCKET) { closesocket(conn->sock); conn->sock = INVALID_SOCKET; } free(conn); }