30 #define SECURITY_WIN32
35 #define SCHANNEL_INITIAL_BUFFER_SIZE 4096
36 #define SCHANNEL_FREE_BUFFER_SIZE 1024
39 #ifndef SECBUFFER_ALERT
40 #define SECBUFFER_ALERT 17
64 SecPkgContext_StreamSizes
sizes;
80 unsigned long buffer_count)
82 desc->ulVersion = SECBUFFER_VERSION;
83 desc->pBuffers = buffers;
84 desc->cBuffers = buffer_count;
94 SecBufferDesc BuffDesc;
96 SECURITY_STATUS sspi_ret;
98 SecBufferDesc outbuf_desc;
100 DWORD dwshut = SCHANNEL_SHUTDOWN;
104 sspi_ret = ApplyControlToken(&
c->ctxt_handle, &BuffDesc);
105 if (sspi_ret != SEC_E_OK)
111 sspi_ret = InitializeSecurityContext(&
c->cred_handle, &
c->ctxt_handle,
s->host,
112 c->request_flags, 0, 0,
NULL, 0, &
c->ctxt_handle,
113 &outbuf_desc, &
c->context_flags, &
c->ctxt_timestamp);
114 if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_CONTEXT_EXPIRED) {
116 FreeContextBuffer(outbuf.pvBuffer);
117 if (
ret < 0 ||
ret != outbuf.cbBuffer)
132 DeleteSecurityContext(&
c->ctxt_handle);
133 FreeCredentialsHandle(&
c->cred_handle);
136 c->enc_buf_size =
c->enc_buf_offset = 0;
139 c->dec_buf_size =
c->dec_buf_offset = 0;
149 SECURITY_STATUS sspi_ret;
150 SecBuffer outbuf[3] = { 0 };
151 SecBufferDesc outbuf_desc;
153 SecBufferDesc inbuf_desc;
156 if (
c->enc_buf ==
NULL) {
157 c->enc_buf_offset = 0;
164 if (
c->dec_buf ==
NULL) {
165 c->dec_buf_offset = 0;
177 c->enc_buf_size =
c->enc_buf_offset = 0;
184 c->enc_buf_size -
c->enc_buf_offset);
189 c->enc_buf_offset +=
ret;
197 if (inbuf[0].pvBuffer ==
NULL) {
203 memcpy(inbuf[0].pvBuffer,
c->enc_buf,
c->enc_buf_offset);
211 sspi_ret = InitializeSecurityContext(&
c->cred_handle, &
c->ctxt_handle,
s->host,
c->request_flags,
212 0, 0, &inbuf_desc, 0,
NULL, &outbuf_desc, &
c->context_flags,
216 if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
223 if (sspi_ret == SEC_I_INCOMPLETE_CREDENTIALS &&
224 !(
c->request_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
226 c->request_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
232 if (sspi_ret == SEC_I_CONTINUE_NEEDED || sspi_ret == SEC_E_OK) {
233 for (
i = 0;
i < 3;
i++) {
234 if (outbuf[
i].BufferType == SECBUFFER_TOKEN && outbuf[
i].cbBuffer > 0) {
236 if (
ret < 0 ||
ret != outbuf[
i].cbBuffer) {
243 if (outbuf[
i].pvBuffer !=
NULL) {
244 FreeContextBuffer(outbuf[
i].pvBuffer);
245 outbuf[
i].pvBuffer =
NULL;
249 if (sspi_ret == SEC_E_WRONG_PRINCIPAL)
257 if (inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
258 if (
c->enc_buf_offset > inbuf[1].cbBuffer) {
259 memmove(
c->enc_buf, (
c->enc_buf +
c->enc_buf_offset) - inbuf[1].cbBuffer,
261 c->enc_buf_offset = inbuf[1].cbBuffer;
262 if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
268 c->enc_buf_offset = 0;
271 if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
283 for (
i = 0;
i < 3;
i++) {
284 if (outbuf[
i].pvBuffer !=
NULL) {
285 FreeContextBuffer(outbuf[
i].pvBuffer);
286 outbuf[
i].pvBuffer =
NULL;
298 SecBufferDesc outbuf_desc;
299 SECURITY_STATUS sspi_ret;
305 c->request_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
306 ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
309 sspi_ret = InitializeSecurityContext(&
c->cred_handle,
NULL,
s->host,
c->request_flags, 0, 0,
310 NULL, 0, &
c->ctxt_handle, &outbuf_desc, &
c->context_flags,
312 if (sspi_ret != SEC_I_CONTINUE_NEEDED) {
319 FreeContextBuffer(outbuf.pvBuffer);
320 if (
ret < 0 ||
ret != outbuf.cbBuffer) {
329 DeleteSecurityContext(&
c->ctxt_handle);
337 SECURITY_STATUS sspi_ret;
338 SCHANNEL_CRED schannel_cred = { 0 };
351 schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
354 schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION |
355 SCH_CRED_REVOCATION_CHECK_CHAIN;
357 schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
358 SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
359 SCH_CRED_IGNORE_REVOCATION_OFFLINE;
362 sspi_ret = AcquireCredentialsHandle(
NULL, (TCHAR *)UNISP_NAME, SECPKG_CRED_OUTBOUND,
365 if (sspi_ret != SEC_E_OK) {
388 SECURITY_STATUS sspi_ret = SEC_E_OK;
390 SecBufferDesc inbuf_desc;
399 if (
c->dec_buf_offset > 0)
402 if (
c->sspi_close_notify)
405 if (!
c->connection_closed) {
406 size =
c->enc_buf_size -
c->enc_buf_offset;
407 if (size < SCHANNEL_FREE_BUFFER_SIZE || c->enc_buf_size < min_enc_buf_size) {
409 if (
c->enc_buf_size < min_enc_buf_size)
410 c->enc_buf_size = min_enc_buf_size;
413 c->enc_buf_size =
c->enc_buf_offset = 0;
419 c->enc_buf_size -
c->enc_buf_offset);
421 c->connection_closed = 1;
423 }
else if (
ret < 0) {
428 c->enc_buf_offset +=
ret;
431 while (
c->enc_buf_offset > 0 && sspi_ret == SEC_E_OK) {
441 sspi_ret = DecryptMessage(&
c->ctxt_handle, &inbuf_desc, 0,
NULL);
442 if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_RENEGOTIATE ||
443 sspi_ret == SEC_I_CONTEXT_EXPIRED) {
445 if (inbuf[1].BufferType == SECBUFFER_DATA) {
449 if (
c->dec_buf_size -
c->dec_buf_offset <
size ||
c->dec_buf_size <
len) {
450 c->dec_buf_size =
c->dec_buf_offset +
size;
451 if (
c->dec_buf_size <
len)
452 c->dec_buf_size =
len;
455 c->dec_buf_size =
c->dec_buf_offset = 0;
461 size = inbuf[1].cbBuffer;
463 memcpy(
c->dec_buf +
c->dec_buf_offset, inbuf[1].pvBuffer,
size);
464 c->dec_buf_offset +=
size;
467 if (inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) {
468 if (
c->enc_buf_offset > inbuf[3].cbBuffer) {
469 memmove(
c->enc_buf, (
c->enc_buf +
c->enc_buf_offset) - inbuf[3].cbBuffer,
471 c->enc_buf_offset = inbuf[3].cbBuffer;
474 c->enc_buf_offset = 0;
476 if (sspi_ret == SEC_I_RENEGOTIATE) {
477 if (
c->enc_buf_offset) {
490 }
else if (sspi_ret == SEC_I_CONTEXT_EXPIRED) {
491 c->sspi_close_notify = 1;
492 if (!
c->connection_closed) {
493 c->connection_closed = 1;
499 }
else if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
514 memcpy(buf,
c->dec_buf,
size);
515 memmove(
c->dec_buf,
c->dec_buf +
size,
c->dec_buf_offset -
size);
516 c->dec_buf_offset -=
size;
521 if (
ret == 0 && !
c->connection_closed)
531 SECURITY_STATUS sspi_ret;
532 int ret = 0, data_size;
535 SecBufferDesc outbuf_desc;
537 if (
c->sizes.cbMaximumMessage == 0) {
538 sspi_ret = QueryContextAttributes(&
c->ctxt_handle, SECPKG_ATTR_STREAM_SIZES, &
c->sizes);
539 if (sspi_ret != SEC_E_OK)
546 data_size =
c->sizes.cbHeader +
len +
c->sizes.cbTrailer;
552 data,
c->sizes.cbHeader);
561 memcpy(outbuf[1].pvBuffer, buf,
len);
563 sspi_ret = EncryptMessage(&
c->ctxt_handle, 0, &outbuf_desc, 0);
564 if (sspi_ret == SEC_E_OK) {
565 len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
574 if (sspi_ret == SEC_E_INSUFFICIENT_MEMORY)
583 return ret < 0 ?
ret : outbuf[1].cbBuffer;