void NETCON_unload(void) { if(cred_handle_initialized) FreeCredentialsHandle(&cred_handle); if(have_compat_cred_handle) FreeCredentialsHandle(&compat_cred_handle); DeleteCriticalSection(&init_sechandle_cs); }
SSL_SOCKET :: ~SSL_SOCKET() { if (Type == 0) ClientOff(); else ServerOff(); if (hCtx.dwLower || hCtx.dwLower) { DeleteSecurityContext(&hCtx); } if (hCred.dwLower || hCred.dwLower) { FreeCredentialsHandle(&hCred); } if (OurCertificate && !IsExternalCert) { CertFreeCertificateContext(OurCertificate); OurCertificate = 0; } if (hCS) CertCloseStore(hCS,0); hCS = 0; }
void netconn_unload( void ) { if(cred_handle_initialized) FreeCredentialsHandle(&cred_handle); DeleteCriticalSection(&init_sechandle_cs); #ifndef HAVE_GETADDRINFO DeleteCriticalSection(&cs_gethostbyname); #endif }
/* sqAuthDestroy: Destroys the authentication session. Arguments: handle - the authentication handle Returns: Zero if successful, an error code otherwise. */ int sqAuthDestroy(int handle) { sqAuthData *auth = (sqAuthData*)handle; if(auth == NULL) return -1; DeleteSecurityContext(&auth->ctxt); FreeCredentialsHandle(&auth->cred); free(auth); return 0; }
LSSLContext::~LSSLContext() { BYTE stub1[sizeof(m_hContext)]; memset(stub1, 0, sizeof(stub1)); if(0!=memcmp(&m_hContext, stub1, sizeof(m_hContext))){//возможно глупость так проверять на инициализированность /*VERIFY(SEC_E_OK==*/DeleteSecurityContext(GetContextHandle())/*)*/; memset(&m_hContext, 0, sizeof(m_hContext)); } BYTE stub2[sizeof(m_hUserCred)]; memset(stub2, 0, sizeof(stub2)); if(0!=memcmp(&m_hUserCred, stub2, sizeof(m_hUserCred))){//возможно глупость так проверять на инициализированность /*VERIFY(SEC_E_OK==*/FreeCredentialsHandle(&m_hUserCred)/*)*/; memset(&m_hUserCred, 0, sizeof(m_hUserCred)); } }
/* sqDestroySSL: Destroys an SSL instance. Arguments: handle - the SSL handle Returns: Non-zero if successful. */ sqInt sqDestroySSL(sqInt handle) { sqSSL *ssl = sslFromHandle(handle); if(ssl == NULL) return 0; FreeCredentialsHandle(&ssl->sslCred); DeleteSecurityContext(&ssl->sslCtxt); if(ssl->certName) free(ssl->certName); if(ssl->peerName) free(ssl->peerName); if(ssl->dataBuf) free(ssl->dataBuf); free(ssl); handleBuf[handle] = NULL; return 1; }
/* Cleans the SSPI context object, when the pool used to create it gets cleared or destroyed. */ static apr_status_t cleanup_ctx(void *data) { serf__kerb_context_t *ctx = data; if (SecIsValidHandle(&ctx->sspi_context)) { DeleteSecurityContext(&ctx->sspi_context); SecInvalidateHandle(&ctx->sspi_context); } if (SecIsValidHandle(&ctx->sspi_credentials)) { FreeCredentialsHandle(&ctx->sspi_context); SecInvalidateHandle(&ctx->sspi_context); } return APR_SUCCESS; }
static int tls_close(URLContext *h) { TLSContext *c = h->priv_data; tls_shutdown_client(h); DeleteSecurityContext(&c->ctxt_handle); FreeCredentialsHandle(&c->cred_handle); av_freep(&c->enc_buf); c->enc_buf_size = c->enc_buf_offset = 0; av_freep(&c->dec_buf); c->dec_buf_size = c->dec_buf_offset = 0; if (c->tls_shared.tcp) ffurl_close(c->tls_shared.tcp); return 0; }
void NetlibDestroySecurityProvider(HANDLE hSecurity) { if (hSecurity == NULL) return; mir_cslock lck(csSec); if (ntlmCnt != 0) { NtlmHandleType* hNtlm = (NtlmHandleType*)hSecurity; if (hNtlm != NULL) { if (SecIsValidHandle(&hNtlm->hClientContext)) DeleteSecurityContext(&hNtlm->hClientContext); if (SecIsValidHandle(&hNtlm->hClientCredential)) FreeCredentialsHandle(&hNtlm->hClientCredential); mir_free(hNtlm->szProvider); mir_free(hNtlm->szPrincipal); mir_free(hNtlm); } --ntlmCnt; } }
VOID destroy_sspi_client_state(sspi_client_state* state) { if (state->haveCtx) { DeleteSecurityContext(&state->ctx); state->haveCtx = 0; } if (state->haveCred) { FreeCredentialsHandle(&state->cred); state->haveCred = 0; } if (state->spn != NULL) { free(state->spn); state->spn = NULL; } if (state->response != NULL) { free(state->response); state->response = NULL; } if (state->username != NULL) { free(state->username); state->username = NULL; } }
static void GetNewSchannelClientCredentials( CredHandle *phCreds, CtxtHandle *phContext) { SCHANNEL_CRED SchannelCred; CredHandle hCreds; SecPkgContext_IssuerListInfoEx IssuerListInfo; PCCERT_CHAIN_CONTEXT pChainContext; CERT_CHAIN_FIND_BY_ISSUER_PARA FindByIssuerPara; PCCERT_CONTEXT pCertContext; TimeStamp tsExpiry; SECURITY_STATUS Status; /* * Read list of trusted issuers from schannel. */ Status = QueryContextAttributes(phContext, SECPKG_ATTR_ISSUER_LIST_EX, (PVOID)&IssuerListInfo); if (Status != SEC_E_OK) { mylog("Error 0x%p querying issuer list info\n", Status); return; } /* * Enumerate the client certificates. */ ZeroMemory(&FindByIssuerPara, sizeof(FindByIssuerPara)); FindByIssuerPara.cbSize = sizeof(FindByIssuerPara); FindByIssuerPara.pszUsageIdentifier = szOID_PKIX_KP_CLIENT_AUTH; FindByIssuerPara.dwKeySpec = 0; FindByIssuerPara.cIssuer = IssuerListInfo.cIssuers; FindByIssuerPara.rgIssuer = IssuerListInfo.aIssuers; pChainContext = NULL; while (TRUE) { /* Find a certificate chain. */ pChainContext = CertFindChainInStore(hMyCertStore, X509_ASN_ENCODING, 0, CERT_CHAIN_FIND_BY_ISSUER, &FindByIssuerPara, pChainContext); if (pChainContext == NULL) { mylog("Error 0x%p finding cert chain\n", GetLastError()); break; } mylog("\ncertificate chain found\n"); /* Get pointer to leaf certificate context. */ pCertContext = pChainContext->rgpChain[0]->rgpElement[0]->pCertContext; ZeroMemory(&SchannelCred, sizeof(SchannelCred)); /* Create schannel credential. */ SchannelCred.dwVersion = SCHANNEL_CRED_VERSION; SchannelCred.cCreds = 1; SchannelCred.paCred = &pCertContext; Status = AcquireCredentialsHandle( NULL, /* Name of principal */ UNI_SCHANNEL, /* Name of package */ SECPKG_CRED_OUTBOUND, /* Flags indicating use */ NULL, /* Pointer to logon ID */ &SchannelCred, /* Package specific data */ NULL, /* Pointer to GetKey() func */ NULL, /* Value to pass to GetKey() */ &hCreds, /* (out) Cred Handle */ &tsExpiry); /* (out) Lifetime (optional) */ if (Status != SEC_E_OK) { mylog("**** Error 0x%p returned by AcquireCredentialsHandle\n", Status); continue; } mylog("\nnew schannel credential created\n"); /* Destroy the old credentials. */ FreeCredentialsHandle(phCreds); *phCreds = hCreds; /* * As you can see, this sample code maintains a single credential * handle, replacing it as necessary. This is a little unusual. * * Many applications maintain a global credential handle that's * anonymous (that is, it doesn't contain a client certificate), * which is used to connect to all servers. If a particular server * should require client authentication, then a new credential * is created for use when connecting to that server. The global * anonymous credential is retained for future connections to * other servers. * * Maintaining a single anonymous credential that's used whenever * possible is most efficient, since creating new credentials all * the time is rather expensive. */ break; } }
int credssp_client_authenticate(rdpCredssp* credssp) { uint32 cbMaxToken; uint32 fContextReq; uint32 pfContextAttr; SECURITY_STATUS status; CredHandle credentials; TimeStamp expiration; SecPkgInfo* pPackageInfo; PSecBuffer p_buffer; SecBuffer input_buffer; SecBuffer output_buffer; SecBufferDesc input_buffer_desc; SecBufferDesc output_buffer_desc; boolean have_context; boolean have_input_buffer; boolean have_pub_key_auth; sspi_GlobalInit(); if (credssp_ntlm_client_init(credssp) == 0) return 0; credssp->table = InitSecurityInterface(); status = QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &pPackageInfo); if (status != SEC_E_OK) { printf("QuerySecurityPackageInfo status: 0x%08X\n", status); return 0; } cbMaxToken = pPackageInfo->cbMaxToken; status = credssp->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME, SECPKG_CRED_OUTBOUND, NULL, &credssp->identity, NULL, NULL, &credentials, &expiration); if (status != SEC_E_OK) { printf("AcquireCredentialsHandle status: 0x%08X\n", status); return 0; } have_context = false; have_input_buffer = false; have_pub_key_auth = false; memset(&input_buffer, 0, sizeof(SecBuffer)); memset(&output_buffer, 0, sizeof(SecBuffer)); memset(&credssp->ContextSizes, 0, sizeof(SecPkgContext_Sizes)); fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_DELEGATE; while (true) { output_buffer_desc.ulVersion = SECBUFFER_VERSION; output_buffer_desc.cBuffers = 1; output_buffer_desc.pBuffers = &output_buffer; output_buffer.BufferType = SECBUFFER_TOKEN; output_buffer.cbBuffer = cbMaxToken; output_buffer.pvBuffer = xmalloc(output_buffer.cbBuffer); status = credssp->table->InitializeSecurityContext(&credentials, (have_context) ? &credssp->context : NULL, NULL, fContextReq, 0, SECURITY_NATIVE_DREP, (have_input_buffer) ? &input_buffer_desc : NULL, 0, &credssp->context, &output_buffer_desc, &pfContextAttr, &expiration); if (input_buffer.pvBuffer != NULL) { xfree(input_buffer.pvBuffer); input_buffer.pvBuffer = NULL; } if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED) || (status == SEC_E_OK)) { if (credssp->table->CompleteAuthToken != NULL) credssp->table->CompleteAuthToken(&credssp->context, &output_buffer_desc); have_pub_key_auth = true; if (credssp->table->QueryContextAttributes(&credssp->context, SECPKG_ATTR_SIZES, &credssp->ContextSizes) != SEC_E_OK) { printf("QueryContextAttributes SECPKG_ATTR_SIZES failure\n"); return 0; } if (have_pub_key_auth) { uint8* p; SecBuffer Buffers[2]; SecBufferDesc Message; SECURITY_STATUS encrypt_status; Buffers[0].BufferType = SECBUFFER_DATA; /* TLS Public Key */ Buffers[1].BufferType = SECBUFFER_TOKEN; /* Signature */ Buffers[0].cbBuffer = credssp->PublicKey.cbBuffer; Buffers[0].pvBuffer = xmalloc(Buffers[0].cbBuffer); memcpy(Buffers[0].pvBuffer, credssp->PublicKey.pvBuffer, Buffers[0].cbBuffer); Buffers[1].cbBuffer = credssp->ContextSizes.cbMaxSignature; Buffers[1].pvBuffer = xzalloc(Buffers[1].cbBuffer); Message.cBuffers = 2; Message.ulVersion = SECBUFFER_VERSION; Message.pBuffers = (PSecBuffer) &Buffers; sspi_SecBufferAlloc(&credssp->pubKeyAuth, Buffers[0].cbBuffer + Buffers[1].cbBuffer); encrypt_status = credssp->table->EncryptMessage(&credssp->context, 0, &Message, 0); if (encrypt_status != SEC_E_OK) { printf("EncryptMessage status: 0x%08X\n", encrypt_status); return 0; } p = (uint8*) credssp->pubKeyAuth.pvBuffer; memcpy(p, Buffers[1].pvBuffer, Buffers[1].cbBuffer); /* Message Signature */ memcpy(&p[Buffers[1].cbBuffer], Buffers[0].pvBuffer, Buffers[0].cbBuffer); /* Encrypted Public Key */ xfree(Buffers[0].pvBuffer); xfree(Buffers[1].pvBuffer); } if (status == SEC_I_COMPLETE_NEEDED) status = SEC_E_OK; else if (status == SEC_I_COMPLETE_AND_CONTINUE) status = SEC_I_CONTINUE_NEEDED; } /* send authentication token to server */ if (output_buffer.cbBuffer > 0) { p_buffer = &output_buffer_desc.pBuffers[0]; credssp->negoToken.pvBuffer = p_buffer->pvBuffer; credssp->negoToken.cbBuffer = p_buffer->cbBuffer; #ifdef WITH_DEBUG_CREDSSP printf("Sending Authentication Token\n"); freerdp_hexdump(credssp->negoToken.pvBuffer, credssp->negoToken.cbBuffer); #endif credssp_send(credssp); credssp_buffer_free(credssp); } if (status != SEC_I_CONTINUE_NEEDED) break; /* receive server response and place in input buffer */ input_buffer_desc.ulVersion = SECBUFFER_VERSION; input_buffer_desc.cBuffers = 1; input_buffer_desc.pBuffers = &input_buffer; input_buffer.BufferType = SECBUFFER_TOKEN; if (credssp_recv(credssp) < 0) return -1; #ifdef WITH_DEBUG_CREDSSP printf("Receiving Authentication Token\n"); freerdp_hexdump(credssp->negoToken.pvBuffer, credssp->negoToken.cbBuffer); #endif p_buffer = &input_buffer_desc.pBuffers[0]; p_buffer->pvBuffer = credssp->negoToken.pvBuffer; p_buffer->cbBuffer = credssp->negoToken.cbBuffer; have_input_buffer = true; have_context = true; } /* Encrypted Public Key +1 */ if (credssp_recv(credssp) < 0) return -1; /* Verify Server Public Key Echo */ status = credssp_verify_public_key_echo(credssp); credssp_buffer_free(credssp); if (status != SEC_E_OK) return 0; /* Send encrypted credentials */ status = credssp_encrypt_ts_credentials(credssp); if (status != SEC_E_OK) { printf("credssp_encrypt_ts_credentials status: 0x%08X\n", status); return 0; } credssp_send(credssp); credssp_buffer_free(credssp); /* Free resources */ FreeCredentialsHandle(&credentials); FreeContextBuffer(pPackageInfo); return 1; }
static int pg_SSPI_recvauth(Port *port) { int mtype; StringInfoData buf; SECURITY_STATUS r; CredHandle sspicred; CtxtHandle *sspictx = NULL, newctx; TimeStamp expiry; ULONG contextattr; SecBufferDesc inbuf; SecBufferDesc outbuf; SecBuffer OutBuffers[1]; SecBuffer InBuffers[1]; HANDLE token; TOKEN_USER *tokenuser; DWORD retlen; char accountname[MAXPGPATH]; char domainname[MAXPGPATH]; DWORD accountnamesize = sizeof(accountname); DWORD domainnamesize = sizeof(domainname); SID_NAME_USE accountnameuse; HMODULE secur32; QUERY_SECURITY_CONTEXT_TOKEN_FN _QuerySecurityContextToken; /* * SSPI auth is not supported for protocol versions before 3, because it * relies on the overall message length word to determine the SSPI payload * size in AuthenticationGSSContinue and PasswordMessage messages. * (This is, in fact, a design error in our SSPI support, because protocol * messages are supposed to be parsable without relying on the length * word; but it's not worth changing it now.) */ if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3) ereport(FATAL, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("SSPI is not supported in protocol version 2"))); /* * Acquire a handle to the server credentials. */ r = AcquireCredentialsHandle(NULL, "negotiate", SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &sspicred, &expiry); if (r != SEC_E_OK) pg_SSPI_error(ERROR, gettext_noop("could not acquire SSPI credentials handle"), r); /* * Loop through SSPI message exchange. This exchange can consist of * multiple messags sent in both directions. First message is always from * the client. All messages from client to server are password packets * (type 'p'). */ do { mtype = pq_getbyte(); if (mtype != 'p') { /* Only log error if client didn't disconnect. */ if (mtype != EOF) ereport(COMMERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("expected SSPI response, got message type %d", mtype))); return STATUS_ERROR; } /* Get the actual SSPI token */ initStringInfo(&buf); if (pq_getmessage(&buf, 2000)) { /* EOF - pq_getmessage already logged error */ pfree(buf.data); return STATUS_ERROR; } /* Map to SSPI style buffer */ inbuf.ulVersion = SECBUFFER_VERSION; inbuf.cBuffers = 1; inbuf.pBuffers = InBuffers; InBuffers[0].pvBuffer = buf.data; InBuffers[0].cbBuffer = buf.len; InBuffers[0].BufferType = SECBUFFER_TOKEN; /* Prepare output buffer */ OutBuffers[0].pvBuffer = NULL; OutBuffers[0].BufferType = SECBUFFER_TOKEN; OutBuffers[0].cbBuffer = 0; outbuf.cBuffers = 1; outbuf.pBuffers = OutBuffers; outbuf.ulVersion = SECBUFFER_VERSION; elog(DEBUG4, "Processing received SSPI token of length %u", (unsigned int) buf.len); r = AcceptSecurityContext(&sspicred, sspictx, &inbuf, ASC_REQ_ALLOCATE_MEMORY, SECURITY_NETWORK_DREP, &newctx, &outbuf, &contextattr, NULL); /* input buffer no longer used */ pfree(buf.data); if (outbuf.cBuffers > 0 && outbuf.pBuffers[0].cbBuffer > 0) { /* * Negotiation generated data to be sent to the client. */ elog(DEBUG4, "sending SSPI response token of length %u", (unsigned int) outbuf.pBuffers[0].cbBuffer); port->gss->outbuf.length = outbuf.pBuffers[0].cbBuffer; port->gss->outbuf.value = outbuf.pBuffers[0].pvBuffer; sendAuthRequest(port, AUTH_REQ_GSS_CONT); FreeContextBuffer(outbuf.pBuffers[0].pvBuffer); } if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED) { if (sspictx != NULL) { DeleteSecurityContext(sspictx); free(sspictx); } FreeCredentialsHandle(&sspicred); pg_SSPI_error(ERROR, gettext_noop("could not accept SSPI security context"), r); } if (sspictx == NULL) { sspictx = malloc(sizeof(CtxtHandle)); if (sspictx == NULL) ereport(ERROR, (errmsg("out of memory"))); memcpy(sspictx, &newctx, sizeof(CtxtHandle)); } if (r == SEC_I_CONTINUE_NEEDED) elog(DEBUG4, "SSPI continue needed"); } while (r == SEC_I_CONTINUE_NEEDED); /* * Release service principal credentials */ FreeCredentialsHandle(&sspicred); /* * SEC_E_OK indicates that authentication is now complete. * * Get the name of the user that authenticated, and compare it to the pg * username that was specified for the connection. * * MingW is missing the export for QuerySecurityContextToken in the * secur32 library, so we have to load it dynamically. */ secur32 = LoadLibrary("SECUR32.DLL"); if (secur32 == NULL) ereport(ERROR, (errmsg_internal("could not load secur32.dll: %d", (int) GetLastError()))); _QuerySecurityContextToken = (QUERY_SECURITY_CONTEXT_TOKEN_FN) GetProcAddress(secur32, "QuerySecurityContextToken"); if (_QuerySecurityContextToken == NULL) { FreeLibrary(secur32); ereport(ERROR, (errmsg_internal("could not locate QuerySecurityContextToken in secur32.dll: %d", (int) GetLastError()))); } r = (_QuerySecurityContextToken) (sspictx, &token); if (r != SEC_E_OK) { FreeLibrary(secur32); pg_SSPI_error(ERROR, gettext_noop("could not get security token from context"), r); } FreeLibrary(secur32); /* * No longer need the security context, everything from here on uses the * token instead. */ DeleteSecurityContext(sspictx); free(sspictx); if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122) ereport(ERROR, (errmsg_internal("could not get token user size: error code %d", (int) GetLastError()))); tokenuser = malloc(retlen); if (tokenuser == NULL) ereport(ERROR, (errmsg("out of memory"))); if (!GetTokenInformation(token, TokenUser, tokenuser, retlen, &retlen)) ereport(ERROR, (errmsg_internal("could not get user token: error code %d", (int) GetLastError()))); if (!LookupAccountSid(NULL, tokenuser->User.Sid, accountname, &accountnamesize, domainname, &domainnamesize, &accountnameuse)) ereport(ERROR, (errmsg_internal("could not lookup acconut sid: error code %d", (int) GetLastError()))); free(tokenuser); /* * Compare realm/domain if requested. In SSPI, always compare case * insensitive. */ if (pg_krb_realm && strlen(pg_krb_realm)) { if (pg_strcasecmp(pg_krb_realm, domainname)) { elog(DEBUG2, "SSPI domain (%s) and configured domain (%s) don't match", domainname, pg_krb_realm); return STATUS_ERROR; } } /* * We have the username (without domain/realm) in accountname, compare to * the supplied value. In SSPI, always compare case insensitive. */ if (pg_strcasecmp(port->user_name, accountname)) { /* GSS name and PGUSER are not equivalent */ elog(DEBUG2, "provided username (%s) and SSPI username (%s) don't match", port->user_name, accountname); return STATUS_ERROR; } return STATUS_OK; }
int credssp_client_authenticate(rdpCredssp* credssp) { uint32 cbMaxLen; uint32 fContextReq; uint32 pfContextAttr; SECURITY_STATUS status; CRED_HANDLE credentials; SEC_TIMESTAMP expiration; SEC_PKG_INFO* pPackageInfo; SEC_AUTH_IDENTITY identity; SEC_BUFFER* p_sec_buffer; SEC_BUFFER input_sec_buffer; SEC_BUFFER output_sec_buffer; SEC_BUFFER_DESC input_sec_buffer_desc; SEC_BUFFER_DESC output_sec_buffer_desc; boolean have_context; boolean have_input_buffer; boolean have_pub_key_auth; rdpSettings* settings = credssp->settings; sspi_GlobalInit(); if (credssp_ntlmssp_client_init(credssp) == 0) return 0; credssp->table = InitSecurityInterface(); status = QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &pPackageInfo); if (status != SEC_E_OK) { printf("QuerySecurityPackageInfo status: 0x%08X\n", status); return 0; } cbMaxLen = pPackageInfo->cbMaxToken; identity.User = (uint16*) xstrdup(settings->username); identity.UserLength = strlen(settings->username); if (settings->domain) { identity.Domain = (uint16*) xstrdup(settings->domain); identity.DomainLength = strlen(settings->domain); } else { identity.Domain = (uint16*) NULL; identity.DomainLength = 0; } identity.Password = (uint16*) xstrdup(settings->password); identity.PasswordLength = strlen(settings->password); identity.Flags = SEC_AUTH_IDENTITY_ANSI; status = credssp->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME, SECPKG_CRED_OUTBOUND, NULL, &identity, NULL, NULL, &credentials, &expiration); if (status != SEC_E_OK) { printf("AcquireCredentialsHandle status: 0x%08X\n", status); return 0; } have_context = false; have_input_buffer = false; have_pub_key_auth = false; memset(&input_sec_buffer, 0, sizeof(SEC_BUFFER)); memset(&output_sec_buffer, 0, sizeof(SEC_BUFFER)); memset(&credssp->ContextSizes, 0, sizeof(SEC_PKG_CONTEXT_SIZES)); fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_DELEGATE; while (true) { output_sec_buffer_desc.ulVersion = SECBUFFER_VERSION; output_sec_buffer_desc.cBuffers = 1; output_sec_buffer_desc.pBuffers = &output_sec_buffer; output_sec_buffer.BufferType = SECBUFFER_TOKEN; output_sec_buffer.cbBuffer = cbMaxLen; output_sec_buffer.pvBuffer = xmalloc(output_sec_buffer.cbBuffer); status = credssp->table->InitializeSecurityContext(&credentials, (have_context) ? &credssp->context : NULL, NULL, fContextReq, 0, SECURITY_NATIVE_DREP, (have_input_buffer) ? &input_sec_buffer_desc : NULL, 0, &credssp->context, &output_sec_buffer_desc, &pfContextAttr, &expiration); if (input_sec_buffer.pvBuffer != NULL) { xfree(input_sec_buffer.pvBuffer); input_sec_buffer.pvBuffer = NULL; } if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED)) { if (credssp->table->CompleteAuthToken != NULL) credssp->table->CompleteAuthToken(&credssp->context, &output_sec_buffer_desc); have_pub_key_auth = true; if (credssp->table->QueryContextAttributes(&credssp->context, SECPKG_ATTR_SIZES, &credssp->ContextSizes) != SEC_E_OK) { printf("QueryContextAttributes SECPKG_ATTR_SIZES failure\n"); return 0; } if (have_pub_key_auth) { uint8* p; SEC_BUFFER Buffers[2]; SEC_BUFFER_DESC Message; Buffers[0].BufferType = SECBUFFER_DATA; /* TLS Public Key */ Buffers[1].BufferType = SECBUFFER_PADDING; /* Signature */ Buffers[0].cbBuffer = credssp->PublicKey.cbBuffer; Buffers[0].pvBuffer = xmalloc(Buffers[0].cbBuffer); memcpy(Buffers[0].pvBuffer, credssp->PublicKey.pvBuffer, Buffers[0].cbBuffer); Buffers[1].cbBuffer = credssp->ContextSizes.cbMaxSignature; Buffers[1].pvBuffer = xzalloc(Buffers[1].cbBuffer); Message.cBuffers = 2; Message.ulVersion = SECBUFFER_VERSION; Message.pBuffers = (SEC_BUFFER*) &Buffers; sspi_SecBufferAlloc(&credssp->pubKeyAuth, Buffers[0].cbBuffer + Buffers[1].cbBuffer); credssp->table->EncryptMessage(&credssp->context, 0, &Message, 0); p = (uint8*) credssp->pubKeyAuth.pvBuffer; memcpy(p, Buffers[1].pvBuffer, Buffers[1].cbBuffer); /* Message Signature */ memcpy(&p[Buffers[1].cbBuffer], Buffers[0].pvBuffer, Buffers[0].cbBuffer); /* Encrypted Public Key */ } if (status == SEC_I_COMPLETE_NEEDED) status = SEC_E_OK; else if (status == SEC_I_COMPLETE_AND_CONTINUE) status = SEC_I_CONTINUE_NEEDED; } /* send authentication token to server */ if (output_sec_buffer.cbBuffer > 0) { p_sec_buffer = &output_sec_buffer_desc.pBuffers[0]; credssp->negoToken.pvBuffer = p_sec_buffer->pvBuffer; credssp->negoToken.cbBuffer = p_sec_buffer->cbBuffer; #ifdef WITH_DEBUG_CREDSSP printf("Sending Authentication Token\n"); freerdp_hexdump(credssp->negoToken.data, credssp->negoToken.length); #endif credssp_send(credssp, &credssp->negoToken, NULL, (have_pub_key_auth) ? &credssp->pubKeyAuth : NULL); if (have_pub_key_auth) { have_pub_key_auth = false; sspi_SecBufferFree(&credssp->pubKeyAuth); } xfree(output_sec_buffer.pvBuffer); output_sec_buffer.pvBuffer = NULL; } if (status != SEC_I_CONTINUE_NEEDED) break; /* receive server response and place in input buffer */ input_sec_buffer_desc.ulVersion = SECBUFFER_VERSION; input_sec_buffer_desc.cBuffers = 1; input_sec_buffer_desc.pBuffers = &input_sec_buffer; input_sec_buffer.BufferType = SECBUFFER_TOKEN; if (credssp_recv(credssp, &credssp->negoToken, NULL, NULL) < 0) return -1; #ifdef WITH_DEBUG_CREDSSP printf("Receiving Authentication Token\n"); freerdp_hexdump(credssp->negoToken.data, credssp->negoToken.length); #endif p_sec_buffer = &input_sec_buffer_desc.pBuffers[0]; p_sec_buffer->pvBuffer = credssp->negoToken.pvBuffer; p_sec_buffer->cbBuffer = credssp->negoToken.cbBuffer; have_input_buffer = true; have_context = true; } /* Encrypted Public Key +1 */ if (credssp_recv(credssp, &credssp->negoToken, NULL, &credssp->pubKeyAuth) < 0) return -1; /* Verify Server Public Key Echo */ status = credssp_verify_public_key_echo(credssp); if (status != SEC_E_OK) return 0; /* Send encrypted credentials */ status = credssp_encrypt_ts_credentials(credssp); if (status != SEC_E_OK) return 0; credssp_send(credssp, NULL, &credssp->authInfo, NULL); /* Free resources */ //sspi_SecBufferFree(&credssp->negoToken); sspi_SecBufferFree(&credssp->authInfo); FreeCredentialsHandle(&credentials); FreeContextBuffer(pPackageInfo); return 1; }
INT _cdecl main( IN INT argc, IN PCHAR* argv ) { DWORD dwError = ERROR_SUCCESS; INT nListenSocket = INVALID_SOCKET; INT nAcceptSocket = INVALID_SOCKET; USHORT usVersionRequired = 0x0101; USHORT usPort = 4444; INT nOnce = 0; PCHAR pServiceName = NULL; PCHAR pServicePassword = NULL; PCHAR pServiceRealm = NULL; WSADATA SocketData; CredHandle ServerCreds; INT nServerCredsAcquired = 0; INT nSocketsStarted = 0; ULONG AscFlags = //ASC_REQ_MUTUAL_AUTH | //ASC_REQ_CONFIDENTIALITY | ASC_REQ_INTEGRITY | ASC_REQ_ALLOCATE_MEMORY; PCHAR pSecPkgName = NTLMSP_NAME_A; FLAGMAPPING FlagMappings[] = { INIT_FLAGMAPPING( CONFIDENTIALITY ), INIT_FLAGMAPPING( DELEGATE ), INIT_FLAGMAPPING( INTEGRITY ), INIT_FLAGMAPPING( USE_SESSION_KEY ), INIT_FLAGMAPPING( REPLAY_DETECT ), INIT_FLAGMAPPING( SEQUENCE_DETECT ) }; memset(&SocketData, 0, sizeof(WSADATA)); memset(&ServerCreds, 0, sizeof(CredHandle)); argc--; argv++; while (argc) { if (strcmp(*argv, "-port") == 0) { argc--; argv++; if (!argc) { dwError = Usage(); BAIL_ON_ERROR(dwError); } usPort = (u_short)atoi(*argv); } else if (strcmp(*argv, "-once") == 0) { nOnce = 1; } else if (strcmp(*argv, "-k") == 0) { pSecPkgName = MICROSOFT_KERBEROS_NAME_A; } else if (strcmp(*argv, "-spnego") == 0) { pSecPkgName = NEGOSSP_NAME; } else if (strcmp(*argv, "-c") == 0) { argv++; argc--; if (argc < 3) { dwError = Usage(); BAIL_ON_ERROR(dwError); } pServiceName = *argv; argv++; argc--; pServicePassword = *argv; argv++; argc--; pServiceRealm = *argv; } else { int i; BOOLEAN bFound = FALSE; for (i = 0; i < (sizeof(FlagMappings)/sizeof(FLAGMAPPING)); i++) { if (_strcmpi( *argv, FlagMappings[ i ].name ) == 0) { bFound = TRUE; AscFlags |= FlagMappings[ i ].value ; break; } } if (!bFound) { break; } } argc--; argv++; } dwError = WSAStartup(usVersionRequired, &SocketData); if (0 != dwError) { dwError = WSAGetLastError(); BAIL_ON_ERROR(dwError); } nSocketsStarted = 1; dwError = CreateSocket(usPort, &nListenSocket); BAIL_ON_ERROR(dwError); do { dwError = ServerAcquireCreds( pServiceName, pServicePassword, pServiceRealm, pSecPkgName, &ServerCreds ); BAIL_ON_ERROR(dwError); nServerCredsAcquired = 1; /* Accept a TCP connection */ printf("Listening...\n"); nAcceptSocket = (int)accept(nListenSocket, NULL, 0); if (INVALID_SOCKET == nAcceptSocket) { dwError = WSAGetLastError(); BAIL_ON_ERROR(dwError); } dwError = SignServer( nAcceptSocket, &ServerCreds, AscFlags ); if (dwError) { printf("Finished with error code: %d\n", dwError); } if (nServerCredsAcquired) { FreeCredentialsHandle(&ServerCreds); nServerCredsAcquired = 0; } closesocket(nAcceptSocket); } while (!nOnce); closesocket(nListenSocket); FreeCredentialsHandle(&ServerCreds); WSACleanup(); finish: return dwError; error: if (nServerCredsAcquired) { FreeCredentialsHandle(&ServerCreds); } if (INVALID_SOCKET != nListenSocket) { closesocket(nListenSocket); } if (INVALID_SOCKET != nAcceptSocket) { closesocket(nAcceptSocket); } if (nSocketsStarted) { WSACleanup(); } goto finish; }
SECURITY_STATUS getToken(char **negotiateToken, WCHAR *targetName, WCHAR *hostName) { //---------------------------------------------------------------------- unsigned long cPackages; PSecPkgInfo PackageInfo; SECURITY_STATUS stat; // Get the name of the package stat = EnumerateSecurityPackages( &cPackages, &PackageInfo); if (stat != SEC_E_OK) { wprintf( L"Security function failed with error: %i\n", stat); return stat; } SEC_WCHAR *szPackage = PackageInfo->Name; unsigned long m_cbMaxToken = PackageInfo->cbMaxToken; PBYTE m_pOutBuf = (PBYTE)malloc(m_cbMaxToken); //-------------------------------------------------------------------- CredHandle hCredential; TimeStamp tsExpiry; PSEC_WINNT_AUTH_IDENTITY_OPAQUE pAuthIdentity = NULL; // The structure for storing user data entered stat = AcquireCredentialsHandle( NULL, szPackage, SECPKG_CRED_OUTBOUND, NULL, pAuthIdentity, NULL, NULL, &hCredential, &tsExpiry); if (stat != SEC_E_OK) { wprintf( L"Credentials function failed with error: %i\n", stat); return stat; } //-------------------------------------------------------------------- CtxtHandle m_hCtxt; SecBufferDesc outSecBufDesc; SecBuffer outSecBuf; unsigned long fContextAttr; // prepare output buffer outSecBufDesc.ulVersion = 0; outSecBufDesc.cBuffers = 1; outSecBufDesc.pBuffers = &outSecBuf; outSecBuf.cbBuffer = m_cbMaxToken; outSecBuf.BufferType = SECBUFFER_TOKEN; outSecBuf.pvBuffer = m_pOutBuf; stat = InitializeSecurityContext( &hCredential, NULL, targetName, ISC_REQ_CONFIDENTIALITY, 0, // reserved1 SECURITY_NATIVE_DREP, NULL, 0, // reserved2 &m_hCtxt, &outSecBufDesc, &fContextAttr, &tsExpiry); FreeCredentialsHandle(&hCredential); switch (stat) { case SEC_I_CONTINUE_NEEDED: case SEC_I_COMPLETE_AND_CONTINUE: CompleteAuthToken(&m_hCtxt, &outSecBufDesc); break; case SEC_E_OK: break; default: return stat; } DeleteSecurityContext(&m_hCtxt); FreeContextBuffer(PackageInfo); if (outSecBuf.cbBuffer) { base64_encode(reinterpret_cast < char* > (m_pOutBuf), outSecBuf.cbBuffer, negotiateToken); } else { return -1; } if (strlen(*negotiateToken) < 500) { CREDUI_INFO creduiInfo = { 0 }; creduiInfo.cbSize = sizeof(creduiInfo); // Change the message text and caption to the actual text for your dialog. SEC_WCHAR message[NI_MAXHOST]; _snwprintf_s( message, NI_MAXHOST, _TRUNCATE, L"Enter your username and password to connect to %s", hostName); creduiInfo.pszCaptionText = L"Connect to the proxy-server"; creduiInfo.pszMessageText = message; BOOL fSave = TRUE; // Checkmark "Remember user" stat = SspiPromptForCredentials( targetName, &creduiInfo, 0, szPackage, NULL, &pAuthIdentity, &fSave, 0); } return SEC_E_OK; }
static DWORD ClientEstablishContext( IN PCSTR pSPN, IN INT nSocket, IN PCSTR pServiceName, IN PCSTR pServicePassword, IN PCSTR pServiceRealm, IN ULONG DelegFlag, OUT CtxtHandle *pSspiContext, IN PCSTR pSecPkgName, OUT ULONG *pRetFlags ) { DWORD dwError = ERROR_SUCCESS; DWORD dwLoopError = ERROR_SUCCESS; PCtxtHandle pContextHandle = NULL; INT nCredentialsAcquired = 0; INT nContextAcquired = 0; SecBuffer SendTokenBuffer; SecBuffer RecvTokenBuffer; SecBufferDesc InputDesc; SecBufferDesc OutputDesc; CredHandle CredHandle; TimeStamp Expiry; SEC_WINNT_AUTH_IDENTITY AuthIdentity; PSEC_WINNT_AUTH_IDENTITY pAuthId = NULL; memset(&SendTokenBuffer, 0, sizeof(SecBuffer)); memset(&RecvTokenBuffer, 0, sizeof(SecBuffer)); memset(&InputDesc, 0, sizeof(SecBufferDesc)); memset(&OutputDesc, 0, sizeof(SecBufferDesc)); memset(&CredHandle, 0, sizeof(CredHandle)); memset(&Expiry, 0, sizeof(TimeStamp)); memset(&AuthIdentity, 0, sizeof(AuthIdentity)); memset(pSspiContext, 0, sizeof(CtxtHandle)); *pRetFlags = 0; InputDesc.cBuffers = 1; InputDesc.pBuffers = &RecvTokenBuffer; InputDesc.ulVersion = SECBUFFER_VERSION; RecvTokenBuffer.BufferType = SECBUFFER_TOKEN; RecvTokenBuffer.cbBuffer = 0; RecvTokenBuffer.pvBuffer = NULL; OutputDesc.cBuffers = 1; OutputDesc.pBuffers = &SendTokenBuffer; OutputDesc.ulVersion = SECBUFFER_VERSION; SendTokenBuffer.BufferType = SECBUFFER_TOKEN; SendTokenBuffer.cbBuffer = 0; SendTokenBuffer.pvBuffer = NULL; CredHandle.dwLower = 0; CredHandle.dwUpper = 0; if (pServiceName) { AuthIdentity.User = (PBYTE) pServiceName; AuthIdentity.UserLength = (DWORD)strlen(pServiceName); pAuthId = &AuthIdentity; } if (pServicePassword) { AuthIdentity.Password = (PBYTE) pServicePassword; AuthIdentity.PasswordLength = (DWORD)strlen(pServicePassword); pAuthId = &AuthIdentity; } if (pServiceRealm) { AuthIdentity.Domain = (PBYTE) pServiceRealm; AuthIdentity.DomainLength = (DWORD)strlen(pServiceRealm); pAuthId = &AuthIdentity; } AuthIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; dwError = AcquireCredentialsHandle( NULL, // no principal name (PSTR) pSecPkgName, // package name SECPKG_CRED_OUTBOUND, NULL, // no logon id pAuthId, NULL, // no get key fn NULL, // noget key arg &CredHandle, &Expiry ); BAIL_ON_ERROR(dwError); nCredentialsAcquired = 1; /* * Perform the context-establishement loop. */ pSspiContext->dwLower = 0; pSspiContext->dwUpper = 0; do { // we need to use dwLoopErr in this case because we may get // back a "continue" command. In those cases, we still // need dwError to be used and set seperatly based on other // calls. dwLoopError = InitializeSecurityContext( &CredHandle, pContextHandle, (PSTR) pSPN, DelegFlag, 0, // reserved SECURITY_NATIVE_DREP, &InputDesc, 0, // reserved pSspiContext, &OutputDesc, pRetFlags, &Expiry ); if (SEC_E_OK != dwLoopError && SEC_I_CONTINUE_NEEDED != dwLoopError) { dwError = dwLoopError; BAIL_ON_ERROR(dwError); } nContextAcquired = 1; if (SEC_I_CONTINUE_NEEDED == dwLoopError) { PNTLM_NEGOTIATE_MESSAGE pMsg = (PNTLM_NEGOTIATE_MESSAGE) SendTokenBuffer.pvBuffer; // Adjust any flags for debugging // pMsg->NtlmFlags |= NTLM_FLAG_SEAL; printf("Context partially initialized...\n"); DumpBuffer(SendTokenBuffer.pvBuffer, SendTokenBuffer.cbBuffer); DumpNtlmMessage(SendTokenBuffer.pvBuffer, SendTokenBuffer.cbBuffer); printf("\n"); printf("Flags returned:\n"); DumpIscRetFlags(*pRetFlags); printf("\n"); } else { PNTLM_RESPONSE_MESSAGE pMsg = (PNTLM_RESPONSE_MESSAGE) SendTokenBuffer.pvBuffer; // Adjust any flags for debugging //pMsg->NtlmFlags |= NTLM_FLAG_SEAL; printf("Context FULLY initialized!\n"); DumpBuffer(SendTokenBuffer.pvBuffer, SendTokenBuffer.cbBuffer); DumpNtlmMessage(SendTokenBuffer.pvBuffer, SendTokenBuffer.cbBuffer); printf("\n"); printf("Flags returned:\n"); DumpIscRetFlags(*pRetFlags); printf("\n"); } pContextHandle = pSspiContext; if (RecvTokenBuffer.pvBuffer) { free(RecvTokenBuffer.pvBuffer); RecvTokenBuffer.pvBuffer = NULL; RecvTokenBuffer.cbBuffer = 0; } if (SendTokenBuffer.cbBuffer != 0) { dwError = SendToken(nSocket, &SendTokenBuffer); BAIL_ON_ERROR(dwError); } FreeContextBuffer(SendTokenBuffer.pvBuffer); SendTokenBuffer.pvBuffer = NULL; SendTokenBuffer.cbBuffer = 0; if (SEC_I_CONTINUE_NEEDED == dwLoopError) { dwError = RecvToken(nSocket, &RecvTokenBuffer); BAIL_ON_ERROR(dwError); printf("RECEIVED:\n"); DumpBuffer(RecvTokenBuffer.pvBuffer, RecvTokenBuffer.cbBuffer); DumpNtlmMessage(RecvTokenBuffer.pvBuffer, RecvTokenBuffer.cbBuffer); printf("\n"); } } while (dwLoopError == SEC_I_CONTINUE_NEEDED); FreeCredentialsHandle(&CredHandle); finish: return dwError; error: if (nCredentialsAcquired) { FreeCredentialsHandle(&CredHandle); } if (nContextAcquired) { DeleteSecurityContext(pSspiContext); memset(pSspiContext, 0, sizeof(CtxtHandle)); } if (RecvTokenBuffer.pvBuffer) { free(RecvTokenBuffer.pvBuffer); } if (SendTokenBuffer.cbBuffer) { FreeContextBuffer(SendTokenBuffer.pvBuffer); } goto finish; }
char* NtlmCreateResponseFromChallenge(HANDLE hSecurity, const char *szChallenge, const TCHAR* login, const TCHAR* psw, bool http, unsigned& complete) { if (hSecurity == NULL || ntlmCnt == 0) return NULL; SecBufferDesc outputBufferDescriptor, inputBufferDescriptor; SecBuffer outputSecurityToken, inputSecurityToken; TimeStamp tokenExpiration; ULONG contextAttributes; char *szOutputToken; NtlmHandleType* hNtlm = (NtlmHandleType*)hSecurity; if (mir_tstrcmpi(hNtlm->szProvider, _T("Basic"))) { bool isGSSAPI = mir_tstrcmpi(hNtlm->szProvider, _T("GSSAPI")) == 0; TCHAR *szProvider = isGSSAPI ? (TCHAR*)_T("Kerberos") : hNtlm->szProvider; bool hasChallenge = szChallenge != NULL && szChallenge[0] != '\0'; if (hasChallenge) { unsigned tokenLen; BYTE *token = (BYTE*)mir_base64_decode(szChallenge, &tokenLen); if (token == NULL) return NULL; if (isGSSAPI && complete) return CompleteGssapi(hSecurity, token, tokenLen); inputBufferDescriptor.cBuffers = 1; inputBufferDescriptor.pBuffers = &inputSecurityToken; inputBufferDescriptor.ulVersion = SECBUFFER_VERSION; inputSecurityToken.BufferType = SECBUFFER_TOKEN; inputSecurityToken.cbBuffer = tokenLen; inputSecurityToken.pvBuffer = token; // try to decode the domain name from the NTLM challenge if (login != NULL && login[0] != '\0' && !hNtlm->hasDomain) { NtlmType2packet* pkt = (NtlmType2packet*)token; if (!strncmp(pkt->sign, "NTLMSSP", 8) && pkt->type == 2) { wchar_t* domainName = (wchar_t*)&token[pkt->targetName.offset]; int domainLen = pkt->targetName.len; // Negotiate ANSI? if yes, convert the ANSI name to unicode if ((pkt->flags & 1) == 0) { int bufsz = MultiByteToWideChar(CP_ACP, 0, (char*)domainName, domainLen, NULL, 0); wchar_t* buf = (wchar_t*)alloca(bufsz * sizeof(wchar_t)); domainLen = MultiByteToWideChar(CP_ACP, 0, (char*)domainName, domainLen, buf, bufsz) - 1; domainName = buf; } else domainLen /= sizeof(wchar_t); if (domainLen) { size_t newLoginLen = mir_tstrlen(login) + domainLen + 1; TCHAR *newLogin = (TCHAR*)alloca(newLoginLen * sizeof(TCHAR)); _tcsncpy(newLogin, domainName, domainLen); newLogin[domainLen] = '\\'; mir_tstrcpy(newLogin + domainLen + 1, login); char* szChl = NtlmCreateResponseFromChallenge(hSecurity, NULL, newLogin, psw, http, complete); mir_free(szChl); } } } } else { if (SecIsValidHandle(&hNtlm->hClientContext)) DeleteSecurityContext(&hNtlm->hClientContext); if (SecIsValidHandle(&hNtlm->hClientCredential)) FreeCredentialsHandle(&hNtlm->hClientCredential); SEC_WINNT_AUTH_IDENTITY auth; if (login != NULL && login[0] != '\0') { memset(&auth, 0, sizeof(auth)); NetlibLogf(NULL, "Security login requested, user: %S pssw: %s", login, psw ? "(exist)" : "(no psw)"); const TCHAR* loginName = login; const TCHAR* domainName = _tcschr(login, '\\'); size_t domainLen = 0; size_t loginLen = mir_tstrlen(loginName); if (domainName != NULL) { loginName = domainName + 1; loginLen = mir_tstrlen(loginName); domainLen = domainName - login; domainName = login; } else if ((domainName = _tcschr(login, '@')) != NULL) { loginName = login; loginLen = domainName - login; domainLen = mir_tstrlen(++domainName); } auth.User = (PWORD)loginName; auth.UserLength = (ULONG)loginLen; auth.Password = (PWORD)psw; auth.PasswordLength = (ULONG)mir_tstrlen(psw); auth.Domain = (PWORD)domainName; auth.DomainLength = (ULONG)domainLen; auth.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; hNtlm->hasDomain = domainLen != 0; } SECURITY_STATUS sc = AcquireCredentialsHandle(NULL, szProvider, SECPKG_CRED_OUTBOUND, NULL, hNtlm->hasDomain ? &auth : NULL, NULL, NULL, &hNtlm->hClientCredential, &tokenExpiration); if (sc != SEC_E_OK) { ReportSecError(sc, __LINE__); return NULL; } } outputBufferDescriptor.cBuffers = 1; outputBufferDescriptor.pBuffers = &outputSecurityToken; outputBufferDescriptor.ulVersion = SECBUFFER_VERSION; outputSecurityToken.BufferType = SECBUFFER_TOKEN; outputSecurityToken.cbBuffer = hNtlm->cbMaxToken; outputSecurityToken.pvBuffer = alloca(outputSecurityToken.cbBuffer); SECURITY_STATUS sc = InitializeSecurityContext(&hNtlm->hClientCredential, hasChallenge ? &hNtlm->hClientContext : NULL, hNtlm->szPrincipal, isGSSAPI ? ISC_REQ_MUTUAL_AUTH | ISC_REQ_STREAM : 0, 0, SECURITY_NATIVE_DREP, hasChallenge ? &inputBufferDescriptor : NULL, 0, &hNtlm->hClientContext, &outputBufferDescriptor, &contextAttributes, &tokenExpiration); complete = (sc != SEC_I_COMPLETE_AND_CONTINUE && sc != SEC_I_CONTINUE_NEEDED); if (sc == SEC_I_COMPLETE_NEEDED || sc == SEC_I_COMPLETE_AND_CONTINUE) sc = CompleteAuthToken(&hNtlm->hClientContext, &outputBufferDescriptor); if (sc != SEC_E_OK && sc != SEC_I_CONTINUE_NEEDED) { ReportSecError(sc, __LINE__); return NULL; } szOutputToken = mir_base64_encode((PBYTE)outputSecurityToken.pvBuffer, outputSecurityToken.cbBuffer); } else { if (!login || !psw) return NULL; char *szLogin = mir_t2a(login); char *szPassw = mir_t2a(psw); size_t authLen = mir_strlen(szLogin) + mir_strlen(szPassw) + 5; char *szAuth = (char*)alloca(authLen); int len = mir_snprintf(szAuth, authLen, "%s:%s", szLogin, szPassw); szOutputToken = mir_base64_encode((BYTE*)szAuth, len); complete = true; mir_free(szPassw); mir_free(szLogin); } if (szOutputToken == NULL) return NULL; if (!http) return szOutputToken; ptrA szProvider(mir_t2a(hNtlm->szProvider)); size_t resLen = mir_strlen(szOutputToken) + mir_strlen(szProvider) + 10; char *result = (char*)mir_alloc(resLen); mir_snprintf(result, resLen, "%s %s", szProvider, szOutputToken); mir_free(szOutputToken); return result; }