SECURITY_STATUS SEC_ENTRY thunk_AcquireCredentialsHandleW( SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialsUse, PLUID pvLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, PVOID pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { SECURITY_STATUS ret; TRACE("%s %s %d %p %p %p %p %p %p\n", debugstr_w(pszPrincipal), debugstr_w(pszPackage), fCredentialsUse, pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); if (pszPackage) { PSTR principal, package; principal = SECUR32_AllocMultiByteFromWide(pszPrincipal); package = SECUR32_AllocMultiByteFromWide(pszPackage); ret = AcquireCredentialsHandleA(principal, package, fCredentialsUse, pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); HeapFree(GetProcessHeap(), 0, principal); HeapFree(GetProcessHeap(), 0, package); } else ret = SEC_E_SECPKG_NOT_FOUND; return ret; }
bool CSSPIHandler::ClientStart(bool encrypt, bool& more, const char *name, const char *pwd, const char *tokenSource /* = NULL */) { char username[256]; char domain[256]; SECURITY_STATUS rc; TimeStamp useBefore; memset(&m_nameAndPwd,0,sizeof(m_nameAndPwd)); if (name && *name) { strncpy(username,name,sizeof(username)); char *p = strpbrk(username,"\\/"); if(!p) domain[0]='\0'; else { *p='\0'; strcpy(domain,username); strcpy(username,p+1); } m_nameAndPwd.Domain = (BYTE*)domain; m_nameAndPwd.DomainLength = (DWORD)strlen(domain); m_nameAndPwd.User = (BYTE*)username; m_nameAndPwd.UserLength = (DWORD)strlen(username); m_nameAndPwd.Password = (BYTE*)(pwd?pwd:""); m_nameAndPwd.PasswordLength = (DWORD)(pwd?strlen(pwd):0); m_nameAndPwd.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; } else if(m_broken_file_sharing) { m_nameAndPwd.UserLength = sizeof(username); GetUserNameA(username,&m_nameAndPwd.UserLength); m_nameAndPwd.User= (BYTE*)username; m_nameAndPwd.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; } rc = AcquireCredentialsHandleA( NULL, (char*)m_currentProtocol.c_str(), SECPKG_CRED_OUTBOUND, NULL, m_nameAndPwd.UserLength?&m_nameAndPwd:NULL, NULL, NULL, &m_credHandle, &useBefore ); if(rc) { m_rc = rc; return false; } m_haveContext = false; m_tokenSource = tokenSource; m_ctxReq = ISC_REQ_MUTUAL_AUTH | ISC_REQ_DELEGATE | ISC_REQ_STREAM | ISC_REQ_EXTENDED_ERROR; if(encrypt) m_ctxReq |= ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY; return ClientStep(more,NULL,0); }
OM_uint32 gss_acquire_cred ( OM_uint32 *minor_status, gss_name_t desired_name, OM_uint32 time_req, gss_OID_set desired_mechs, int cred_usage, gss_cred_id_t *output_cred_handle, gss_OID_set *actual_mechs, OM_int32 *time_rec) { *minor_status = 0; OM_uint32 ret = AcquireCredentialsHandleA(desired_name,"Kerberos",cred_usage,NULL,NULL,NULL,NULL,output_cred_handle,(TimeStamp*)time_rec); return ret; }
static void test_kerberos(void) { SecPkgInfoA *info; TimeStamp ttl; CredHandle cred; SECURITY_STATUS status; SEC_CHAR provider[] = {'K','e','r','b','e','r','o','s',0}; static const ULONG expected_flags = SECPKG_FLAG_INTEGRITY | SECPKG_FLAG_PRIVACY | SECPKG_FLAG_TOKEN_ONLY | SECPKG_FLAG_DATAGRAM | SECPKG_FLAG_CONNECTION | SECPKG_FLAG_MULTI_REQUIRED | SECPKG_FLAG_EXTENDED_ERROR | SECPKG_FLAG_IMPERSONATION | SECPKG_FLAG_ACCEPT_WIN32_NAME | SECPKG_FLAG_NEGOTIABLE | SECPKG_FLAG_GSS_COMPATIBLE | SECPKG_FLAG_LOGON | SECPKG_FLAG_MUTUAL_AUTH | SECPKG_FLAG_DELEGATION | SECPKG_FLAG_READONLY_WITH_CHECKSUM; static const ULONG optional_mask = SECPKG_FLAG_RESTRICTED_TOKENS | SECPKG_FLAG_APPCONTAINER_CHECKS; status = QuerySecurityPackageInfoA(provider, &info); ok(status == SEC_E_OK, "Kerberos package not installed, skipping test\n"); if(status != SEC_E_OK) return; ok( (info->fCapabilities & ~optional_mask) == expected_flags, "got %08x, expected %08x\n", info->fCapabilities, expected_flags ); ok( info->wVersion == 1, "got %u\n", info->wVersion ); ok( info->wRPCID == RPC_C_AUTHN_GSS_KERBEROS, "got %u\n", info->wRPCID ); ok( info->cbMaxToken >= 12000, "got %u\n", info->cbMaxToken ); ok( !lstrcmpA( info->Name, "Kerberos" ), "got %s\n", info->Name ); ok( !lstrcmpA( info->Comment, "Microsoft Kerberos V1.0" ), "got %s\n", info->Comment ); FreeContextBuffer( info ); status = AcquireCredentialsHandleA( NULL, provider, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &cred, &ttl ); todo_wine ok( status == SEC_E_OK, "AcquireCredentialsHandleA returned %08x\n", status ); if(status == SEC_E_OK) FreeCredentialHandle( &cred ); }
my_bool ma_tls_connect(MARIADB_TLS *ctls) { my_bool blocking; MYSQL *mysql; SCHANNEL_CRED Cred; MARIADB_PVIO *pvio; my_bool rc= 1; SC_CTX *sctx; SECURITY_STATUS sRet; PCCERT_CONTEXT pRemoteCertContext = NULL, pLocalCertContext= NULL; ALG_ID AlgId[MAX_ALG_ID]= {0}; if (!ctls || !ctls->pvio) return 1;; pvio= ctls->pvio; sctx= (SC_CTX *)ctls->ssl; /* Set socket to blocking if not already set */ if (!(blocking= pvio->methods->is_blocking(pvio))) pvio->methods->blocking(pvio, TRUE, 0); mysql= pvio->mysql; if (ma_tls_set_client_certs(ctls)) goto end; ZeroMemory(&Cred, sizeof(SCHANNEL_CRED)); /* Set cipher */ if (mysql->options.ssl_cipher) { WORD validTokens = 0; char *token = strtok(mysql->options.ssl_cipher, ":"); while (token) { struct st_cipher_suite *valid; for (valid = valid_ciphers; valid && valid->aid; valid++) { if (!strcmp(token, valid->cipher)) { AlgId[validTokens++] = valid->aid; break; } } token = strtok(NULL, ":"); } } Cred.palgSupportedAlgs = (ALG_ID *)&AlgId; Cred.dwVersion= SCHANNEL_CRED_VERSION; if (mysql->options.extension) Cred.dwMinimumCipherStrength = MAX(128, mysql->options.extension->tls_cipher_strength); else Cred.dwMinimumCipherStrength = 128; Cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK | SCH_SEND_ROOT_CERT | SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_MANUAL_CRED_VALIDATION; if (sctx->client_cert_ctx) { Cred.cCreds = 1; Cred.paCred = &sctx->client_cert_ctx; } if (mysql->options.extension && mysql->options.extension->tls_version) { Cred.grbitEnabledProtocols= 0; if (strstr("TLSv1.0", mysql->options.extension->tls_version)) Cred.grbitEnabledProtocols|= SP_PROT_TLS1_0; if (strstr("TLSv1.1", mysql->options.extension->tls_version)) Cred.grbitEnabledProtocols|= SP_PROT_TLS1_1; if (strstr("TLSv1.2", mysql->options.extension->tls_version)) Cred.grbitEnabledProtocols|= SP_PROT_TLS1_2; } else Cred.grbitEnabledProtocols = SP_PROT_TLS1_0 | SP_PROT_TLS1_1 | SP_PROT_TLS1_2; if ((sRet= AcquireCredentialsHandleA(NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL, &Cred, NULL, NULL, &sctx->CredHdl, NULL)) != SEC_E_OK) { ma_schannel_set_sec_error(pvio, sRet); goto end; } sctx->FreeCredHdl= 1; if (ma_schannel_client_handshake(ctls) != SEC_E_OK) goto end; sRet= QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pRemoteCertContext); if (sRet != SEC_E_OK) { ma_schannel_set_sec_error(pvio, sRet); goto end; } if (!ma_schannel_verify_certs(sctx, 0)) goto end; return 0; end: if (pRemoteCertContext) CertFreeCertificateContext(pRemoteCertContext); if (rc && sctx->IoBufferSize) LocalFree(sctx->IoBuffer); sctx->IoBufferSize= 0; if (sctx->client_cert_ctx) CertFreeCertificateContext(sctx->client_cert_ctx); sctx->client_cert_ctx= 0; return 1; }
INT auth_sspi_client_init(SEC_CHAR* service, SEC_CHAR* principal, ULONG flags, SEC_CHAR* user, SEC_CHAR* domain, SEC_CHAR* password, sspi_client_state* state) { SECURITY_STATUS status; SEC_WINNT_AUTH_IDENTITY_A authIdentity; TimeStamp ignored; state->response = NULL; state->username = NULL; state->flags = flags; state->haveCred = 0; state->haveCtx = 0; state->spn = _strdup(service); if (state->spn == NULL) { PyErr_SetNone(PyExc_MemoryError); return AUTH_GSS_ERROR; } /* Convert RFC-2078 format to SPN */ if (!strchr(state->spn, '/')) { SEC_CHAR* ptr = strchr(state->spn, '@'); if (ptr) { *ptr = '/'; } } if (user) { authIdentity.User = user; authIdentity.UserLength = (ULONG)strlen(user); authIdentity.Domain = NULL; authIdentity.DomainLength = 0; authIdentity.Password = NULL; authIdentity.PasswordLength = 0; if (domain) { authIdentity.Domain = domain; authIdentity.DomainLength = (ULONG)strlen(domain); } if (password) { authIdentity.Password = password; authIdentity.PasswordLength = (ULONG)strlen(password); } authIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; } status = AcquireCredentialsHandleA(/* Principal (NULL means current user) */ principal, /* Security package name */ "kerberos", /* Credentials Use */ SECPKG_CRED_OUTBOUND, /* LogonID (We don't use this) */ NULL, /* AuthData */ user ? &authIdentity : NULL, /* Always NULL */ NULL, /* Always NULL */ NULL, /* CredHandle */ &state->cred, /* Expiry (Required but unused by us) */ &ignored); if (status != SEC_E_OK) { set_krberror(status, "AcquireCredentialsHandle"); return AUTH_GSS_ERROR; } state->haveCred = 1; return AUTH_GSS_COMPLETE; }
BOOL DoAuthentication (void) { SECURITY_STATUS ss; DWORD cbIn; DWORD cbOut; DWORD g_cbMaxMessage; BOOL done = FALSE; BOOL fDone = FALSE; BOOL fNewConversation = TRUE; TimeStamp Lifetime; PSecPkgInfoA pkgInfo; CredHandle hcred; CredHandle hCcred; struct _SecHandle hctxt; struct _SecHandle hCctxt; PBYTE g_pInBuf = NULL; PBYTE g_pOutBuf = NULL; SEC_CHAR g_lpPackageName[1024]; PBYTE nonce, clientnonce, lmhash, nthash; PCHAR pUserName = NULL; DWORD cbUserName = 0; lstrcpynA (g_lpPackageName, "NTLM",5); ss = QuerySecurityPackageInfoA ( g_lpPackageName, &pkgInfo); if (!SEC_SUCCESS(ss)) MyHandleError("Could not query package"); g_cbMaxMessage = pkgInfo->cbMaxToken; FreeContextBuffer(pkgInfo); g_pInBuf = (PBYTE) malloc (g_cbMaxMessage); g_pOutBuf = (PBYTE) malloc (g_cbMaxMessage); if (NULL == g_pInBuf || NULL == g_pOutBuf) MyHandleError("Memory allocation"); ss = AcquireCredentialsHandleA (NULL, g_lpPackageName, SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &hcred, &Lifetime); if (!SEC_SUCCESS (ss)) MyHandleError("AcquireCreds failed"); cbOut = g_cbMaxMessage; if (!GenClientContext ( NULL, 0, g_pOutBuf, &cbOut, &fDone, "NTLM", &hCcred, &hCctxt)) MyHandleError("Cant't generate client context"); printf ("Type%hhd message (%lu bytes):\n",g_pOutBuf[8], cbOut);//type1 PrintHexDump (cbOut, (PBYTE)g_pOutBuf); memcpy(g_pInBuf,g_pOutBuf, cbOut); cbIn = cbOut; cbOut = g_cbMaxMessage; if (!GenServerContext (g_pInBuf, cbIn, g_pOutBuf, &cbOut, &done, fNewConversation, &hcred, &hctxt)) MyHandleError("GenServerContext failed"); fNewConversation = FALSE; printf ("Type%hhd message (%lu bytes):\n",g_pOutBuf[8], cbOut); //type2 PrintHexDump (cbOut, (PBYTE)g_pOutBuf); memcpy(g_pInBuf,g_pOutBuf, cbOut); cbIn = cbOut; cbOut = g_cbMaxMessage; nonce = (PBYTE) malloc (16); memcpy (nonce, (void *)&g_pOutBuf[24], 8); if (!GenClientContext (g_pInBuf, cbIn, g_pOutBuf, &cbOut, &fDone, "NTLM", &hCcred, &hCctxt)) MyHandleError("GenClientContext failed"); printf ("Type%hhd message (%lu bytes):\n",g_pOutBuf[8], cbOut);//type3 PrintHexDump (cbOut, (PBYTE)g_pOutBuf); GetUserNameExA(NameSamCompatible, pUserName, &cbUserName); pUserName = (PCHAR) malloc (cbUserName); GetUserNameExA(NameSamCompatible, pUserName, &cbUserName); cbUserName = (DWORD)((int)strchr(pUserName,'\\')); *(char *)cbUserName = 0; printf("g_pOutBuf[22]=%d\n",g_pOutBuf[22]); if (g_pOutBuf[22] > 24) { printf("NTLMv2\n"); nthash = (PBYTE) malloc (16); cbIn = g_pOutBuf[24] + (g_pOutBuf[25] << 8); memcpy (nthash, (void *)&g_pOutBuf[cbIn], 16); cbIn += 16; clientnonce = (PBYTE) malloc (cbOut - cbIn - 16); //memcpy (clientnonce, (void *)&g_pOutBuf[cbIn], 84); memcpy (clientnonce, (void *)&g_pOutBuf[cbIn], cbOut - cbIn - 16); printf("Nonce: "); PrintHex (8, nonce); printf("\nClientNonce: "); PrintHex (cbOut - cbIn - 16, clientnonce); printf("\nNThash: "); PrintHex (16, nthash); printf("\n"); printf("\nJTR: %s::%s", (unsigned char *)((int)cbUserName+1), (unsigned char *)pUserName); printf(":"); PrintHex (8, nonce); printf(":"); PrintHex (16, nthash); printf(":"); PrintHex (cbOut - cbIn - 16, clientnonce); printf("\n"); } else if (g_pOutBuf[22] == 24) { printf("NTLM\n"); lmhash = (PBYTE) malloc (24); cbIn = g_pOutBuf[16] + (g_pOutBuf[17] << 8); memcpy (lmhash, (void *)&g_pOutBuf[cbIn], 24); nthash = (PBYTE) malloc (24); cbIn = g_pOutBuf[24] + (g_pOutBuf[25] << 8); memcpy (nthash, (void *)&g_pOutBuf[cbIn], 24); printf("\nNonce: "); PrintHex (8, nonce); printf("\nLMhash: "); PrintHex (24, lmhash); printf("\nNThash: "); PrintHex (24, nthash); printf("\nJTR: %s::%s", (unsigned char *)((int)cbUserName+1), (unsigned char *)pUserName); printf(":"); PrintHex (24, lmhash); printf(":"); PrintHex (24, nthash); printf(":"); PrintHex (8, nonce); printf("\n"); } else { printf("Unknown hashtype"); } return(TRUE); }
OM_uint32 gss_init_sec_context ( OM_uint32 *minor_status, gss_cred_id_t claimant_cred_handle, gss_ctx_id_t *context_handle, gss_name_t target_name, gss_OID mech_type, int req_flags, int time_req, gss_channel_bindings_t input_channel_bindings, gss_buffer_t input_token, gss_OID *actual_mech_types, gss_buffer_t output_token, int *ret_flags, OM_int32 *time_rec) { SecPkgInfoA *secPackInfo = NULL; gss_cred_id_t credhandle={0}; gss_ctx_id_t *pctx; // SECBUFFER_TOKEN // This buffer type is used to indicate the security token portion of the message. // This is read-only for input parameters or read/write for output parameters. SecBuffer InputBuf[1] = {input_token?input_token->length:0,SECBUFFER_TOKEN,input_token?input_token->value:0}; SecBuffer OutputBuf[1] = {0,SECBUFFER_TOKEN,NULL}; SecBufferDesc InBuffer[1] = {SECBUFFER_VERSION, 1, InputBuf}; SecBufferDesc OutBuffer[1] = {SECBUFFER_VERSION, 1, OutputBuf}; OM_uint32 ret; TimeStamp tr; unsigned long rf; SECURITY_STATUS retq; // // Previously gserver passed ISC_REQ_ALLOCATE_MEMORY to InitializeSecurityContext // but it returns SEC_E_BUFFER_TOO_SMALL - I think this is because // only Digest and Schannel will allocate output buffers for you, even though the documentation // doesn't make that clear for InitializeSecurityContext (see AcquireCredentialsHandle doco). // if((retq=QuerySecurityPackageInfoA( "Kerberos", &secPackInfo )) != SEC_E_OK) return 0; OutputBuf->BufferType = SECBUFFER_TOKEN; // preping a token here OutputBuf->cbBuffer = secPackInfo->cbMaxToken; OutputBuf->pvBuffer = malloc(secPackInfo->cbMaxToken); if(claimant_cred_handle.dwLower==0 && claimant_cred_handle.dwUpper==0) { static gss_cred_id_t global_client_cred={0}; if(global_client_cred.dwLower==0 || global_client_cred.dwUpper==0) { ret = AcquireCredentialsHandleA(NULL,"Kerberos",SECPKG_CRED_OUTBOUND,NULL,NULL,NULL,NULL,&global_client_cred,NULL); if(ret) return ret; } credhandle = global_client_cred; } else credhandle = claimant_cred_handle; if(context_handle->dwLower==0 && context_handle->dwUpper==0) pctx = NULL; else pctx = context_handle; // note - only Digest and Schannel will allocate output buffers for you. // so kerberos and other security contexts should not use ISC_REQ_ALLOCATE_MEMORY // and also should not free them by calling the FreeContextBuffer function. ret = InitializeSecurityContextA( &credhandle, pctx, target_name, req_flags, 0, SECURITY_NETWORK_DREP, input_token?InBuffer:NULL,0, pctx?NULL:context_handle, OutBuffer, &rf, &tr); // really need to return if that didn't work... if (ret != SEC_E_OK /*GSS_S_COMPLETE*/ && ret != SEC_I_CONTINUE_NEEDED /*GSS_S_CONTINUE_NEEDED*/ ) { free(OutputBuf->pvBuffer); OutputBuf->pvBuffer = NULL; return ret; } output_token->length = OutputBuf[0].cbBuffer; output_token->value = malloc((OutputBuf[0].cbBuffer)+100); if (output_token->value!=NULL) memcpy(output_token->value,OutputBuf[0].pvBuffer,output_token->length); // only call this if InitializeSecurityContext successfully created the buffers for us // FreeContextBuffer(OutBuffer); // manually made the memory, so manually release it... free(OutputBuf->pvBuffer); OutputBuf->pvBuffer = NULL; *minor_status = 0; if(time_rec) *time_rec=tr.LowPart; if(ret_flags) *ret_flags=rf; return ret; }
BOOL GenClientContext (BYTE *pIn, DWORD cbIn, BYTE *pOut, DWORD *pcbOut, BOOL *pfDone, SEC_CHAR *pszTarget, CredHandle *hCred, struct _SecHandle *hCtxt) { SECURITY_STATUS ss; TimeStamp Lifetime; SecBufferDesc OutBuffDesc; SecBuffer OutSecBuff; SecBufferDesc InBuffDesc; SecBuffer InSecBuff; ULONG ContextAttributes; SEC_CHAR lpPackageName[1024]; _SEC_WINNT_AUTH_IDENTITY auth_data; PCHAR pUserName = NULL; DWORD cbUserName = 0; DWORD dw; if( NULL == pIn ) { GetUserNameExA(NameSamCompatible, pUserName, &cbUserName); pUserName = (PCHAR) malloc (cbUserName); GetUserNameExA(NameSamCompatible, pUserName, &cbUserName); cbUserName = (DWORD)((int)strchr(pUserName,'\\')); *(char *)cbUserName = 0; auth_data.Domain = (unsigned char *)pUserName; auth_data.User = (unsigned char *)((int)cbUserName+1); printf("%s@%s\n",(char *)auth_data.User,(char *)auth_data.Domain); auth_data.UserLength = strlen((char *)auth_data.User); auth_data.DomainLength = strlen((char *)auth_data.Domain); auth_data.Password = NULL; auth_data.PasswordLength = 0; auth_data.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; lstrcpynA (lpPackageName, "NTLM", 5); ss = AcquireCredentialsHandleA (NULL, lpPackageName, SECPKG_CRED_OUTBOUND, NULL, &auth_data, NULL, NULL, hCred, &Lifetime); if (!(SEC_SUCCESS (ss))) MyHandleError("AcquireCreds failed "); } OutBuffDesc.ulVersion = 0; OutBuffDesc.cBuffers = 1; OutBuffDesc.pBuffers = &OutSecBuff; OutSecBuff.cbBuffer = *pcbOut; OutSecBuff.BufferType = SECBUFFER_TOKEN; OutSecBuff.pvBuffer = pOut; if (pIn) { InBuffDesc.ulVersion = 0; InBuffDesc.cBuffers = 1; InBuffDesc.pBuffers = &InSecBuff; InSecBuff.cbBuffer = cbIn; InSecBuff.BufferType = SECBUFFER_TOKEN; InSecBuff.pvBuffer = pIn; ss = InitializeSecurityContextA (hCred, hCtxt, pszTarget, ISC_REQ_CONFIDENTIALITY, 0, SECURITY_NATIVE_DREP, &InBuffDesc, 0, hCtxt, &OutBuffDesc, &ContextAttributes, &Lifetime); } else { ss = InitializeSecurityContextA (hCred, NULL, pszTarget, ISC_REQ_CONFIDENTIALITY, 0, SECURITY_NATIVE_DREP, NULL, 0, hCtxt, &OutBuffDesc, &ContextAttributes, &Lifetime); } if (!SEC_SUCCESS (ss)) MyHandleError ("InitializeSecurityContext failed " ); *pcbOut = OutSecBuff.cbBuffer; *pfDone = !((SEC_I_CONTINUE_NEEDED == ss) ||(SEC_I_COMPLETE_AND_CONTINUE == ss)); return TRUE; }