BOOL ClientAuthenticate(const char *name, const char *hostname) { int rc, rcISC; SEC_WINNT_AUTH_IDENTITY nameAndPwd = {0}; int bytesReceived = 0, bytesSent = 0; char myTokenSource[256]; TimeStamp useBefore; DWORD ctxReq, ctxAttr; int dwRead,dwWritten; // input and output buffers SecBufferDesc obd, ibd; SecBuffer ob, ib[2]; BOOL haveInbuffer = FALSE; BOOL haveContext = FALSE; SCHANNEL_CRED cred = {0}; PCCERT_CONTEXT cert = NULL; HANDLE hMy = CertOpenSystemStore(0,"MY"); if(!hMy) { rcISC = SEC_E_NO_CREDENTIALS; server_error(1,"[%08x] %s\n",rcISC,GetErrorString(rcISC)); return FALSE; } if(name) { cert = CertFindCertificateInStore(hMy, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, (const wchar_t *)cvs::wide(name), NULL); if(!cert) { rcISC = SEC_E_NO_CREDENTIALS; server_error(1,"No certificate for '%s': %s\n",name,GetErrorString(rcISC)); return FALSE; } } cred.dwVersion = SCHANNEL_CRED_VERSION; cred.dwFlags = SCH_CRED_USE_DEFAULT_CREDS; if(cert) { cred.cCreds = 1; cred.paCred = &cert; } rc = AcquireCredentialsHandle( NULL, "SChannel", SECPKG_CRED_OUTBOUND, NULL, &cred, NULL, NULL, &credHandle, &useBefore ); ctxReq = ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_INTEGRITY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_STREAM | ISC_REQ_USE_SUPPLIED_CREDS; strncpy(myTokenSource,hostname,sizeof(myTokenSource)); CertCloseStore(hMy,0); ib[0].pvBuffer = NULL; while ( 1 ) { obd.ulVersion = SECBUFFER_VERSION; obd.cBuffers = 1; obd.pBuffers = &ob; // just one buffer ob.BufferType = SECBUFFER_TOKEN; // preping a token here ob.cbBuffer = secPackInfo->cbMaxToken; ob.pvBuffer = malloc(secPackInfo->cbMaxToken); rcISC = InitializeSecurityContext( &credHandle, haveContext? &contextHandle: NULL, myTokenSource, ctxReq, 0, SECURITY_NATIVE_DREP, haveInbuffer? &ibd: NULL, 0, &contextHandle, &obd, &ctxAttr, &useBefore ); if ( ib[0].pvBuffer != NULL ) { free(ib[0].pvBuffer); ib[0].pvBuffer = NULL; } if ( rcISC == SEC_I_COMPLETE_AND_CONTINUE || rcISC == SEC_I_COMPLETE_NEEDED ) { CompleteAuthToken( &contextHandle, &obd ); if ( rcISC == SEC_I_COMPLETE_NEEDED ) rcISC = SEC_E_OK; else if ( rcISC == SEC_I_COMPLETE_AND_CONTINUE ) rcISC = SEC_I_CONTINUE_NEEDED; } if(rcISC<0) { server_error(1,"[%08x] %s\n",rcISC,GetErrorString(rcISC)); } // send the output buffer off to the server if ( ob.cbBuffer != 0 ) { if((dwWritten=tcp_write( (const char *) ob.pvBuffer, ob.cbBuffer))<=0) break; bytesSent += dwWritten; } free(ob.pvBuffer); ob.pvBuffer = NULL; ob.cbBuffer = 0; if ( rcISC != SEC_I_CONTINUE_NEEDED ) break; // prepare to get the server's response ibd.ulVersion = SECBUFFER_VERSION; ibd.cBuffers = 2; ibd.pBuffers = ib; // just one buffer ib[0].BufferType = SECBUFFER_TOKEN; // preping a token here ib[0].cbBuffer = secPackInfo->cbMaxToken; ib[0].pvBuffer = malloc(secPackInfo->cbMaxToken); ib[1].cbBuffer = 0; ib[1].pvBuffer = NULL; ib[1].BufferType = SECBUFFER_EMPTY; // Spare stuff // receive the server's response if((dwRead=tcp_read(ib[0].pvBuffer,ib[0].cbBuffer))<=0) break; bytesReceived += dwRead; // by now we have an input buffer and a client context haveInbuffer = TRUE; haveContext = TRUE; } // we arrive here as soon as InitializeSecurityContext() // returns != SEC_I_CONTINUE_NEEDED. if ( rcISC != SEC_E_OK ) haveContext = FALSE; else haveContext = TRUE; /* Looopback kerberos needs this */ return haveContext; }
static DWORD ServerAcquireCreds( IN PCHAR pServiceName, IN PCHAR pServicePassword, IN PCHAR pServiceRealm, IN PCHAR pSecPkgName, OUT CredHandle *pServerCreds ) { DWORD dwError = SEC_E_OK; TimeStamp Expiry; SEC_WINNT_AUTH_IDENTITY_A AuthIdentity; PSEC_WINNT_AUTH_IDENTITY_A pAuthId = NULL; memset(&Expiry, 0, sizeof(TimeStamp)); memset(&AuthIdentity, 0, sizeof(SEC_WINNT_AUTH_IDENTITY_A)); memset(pServerCreds, 0, sizeof(CredHandle)); if (pServiceName) { AuthIdentity.User = (PBYTE) pServiceName; AuthIdentity.UserLength = (ULONG)strlen(pServiceName); pAuthId = &AuthIdentity; } if (pServicePassword) { AuthIdentity.Password = (PBYTE) pServicePassword; AuthIdentity.PasswordLength = (ULONG)strlen(pServicePassword); pAuthId = &AuthIdentity; } if (pServiceRealm) { AuthIdentity.Domain = (PBYTE) pServiceRealm; AuthIdentity.DomainLength = (ULONG)strlen(pServiceRealm); pAuthId = &AuthIdentity; } AuthIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; dwError = AcquireCredentialsHandle( NULL, pSecPkgName, SECPKG_CRED_INBOUND, NULL, // no logon id pAuthId, NULL, // no get key fn NULL, // no get key arg pServerCreds, &Expiry ); BAIL_ON_ERROR(dwError); error: return dwError; }
int SSL_SOCKET :: ClientInit(bool NoLoop) { SECURITY_STATUS ss = 0; if (IsExternalCert) { ; } else { OurCertificate = CreateOurCertificate(); } // Configure our SSL SChannel memset(&m_SchannelCred,0,sizeof(m_SchannelCred)); m_SchannelCred.dwVersion = SCHANNEL_CRED_VERSION; m_SchannelCred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; m_SchannelCred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_NO_SYSTEM_MAPPER | SCH_CRED_REVOCATION_CHECK_CHAIN; if (OurCertificate) { m_SchannelCred.cCreds = 1; m_SchannelCred.paCred = &OurCertificate; } // AcquireCredentialsHandle ss = AcquireCredentialsHandle(0,SCHANNEL_NAME,SECPKG_CRED_OUTBOUND,0,&m_SchannelCred,0,0,&hCred,0); // ss = AcquireCredentialsHandle(0,UNISP_NAME,SECPKG_CRED_OUTBOUND,0,&m_SchannelCred,0,0,&hCred,0); if (FAILED(ss)) return 0; if (NoLoop) return 0; return ClientLoop(); }
GSSAPISession::GSSAPISession(QString authMethod) : _authMethod(authMethod), _first(true) { #ifdef Q_OS_WIN SECURITY_STATUS status; LPWSTR methodName = new WCHAR[_authMethod.length()+1]; _authMethod.toWCharArray(methodName); methodName[_authMethod.length()] = 0; status = QuerySecurityPackageInfo(methodName, &_info); TimeStamp serverLifetime; status = AcquireCredentialsHandle(NULL, methodName, SECPKG_CRED_BOTH, NULL, NULL, NULL, NULL, &_serverHandle, &serverLifetime); _outSecBufDesc.ulVersion = 0; _outSecBufDesc.cBuffers = 1; _outSecBufDesc.pBuffers = &_outSecBuf; _outSecBuf.cbBuffer = _info->cbMaxToken; _outSecBuf.BufferType = SECBUFFER_TOKEN; _outSecBuf.pvBuffer = static_cast<PBYTE>(malloc (_info->cbMaxToken)); _inSecBufDesc.ulVersion = 0; _inSecBufDesc.cBuffers = 1; _inSecBufDesc.pBuffers = &_inSecBuf; _inSecBuf.BufferType = SECBUFFER_TOKEN; delete methodName; #endif }
apr_status_t serf__kerb_create_sec_context(serf__kerb_context_t **ctx_p, apr_pool_t *scratch_pool, apr_pool_t *result_pool) { SECURITY_STATUS sspi_status; serf__kerb_context_t *ctx; ctx = apr_pcalloc(result_pool, sizeof(*ctx)); SecInvalidateHandle(&ctx->sspi_context); SecInvalidateHandle(&ctx->sspi_credentials); ctx->initalized = FALSE; apr_pool_cleanup_register(result_pool, ctx, cleanup_ctx, apr_pool_cleanup_null); sspi_status = AcquireCredentialsHandle( NULL, "Negotiate", SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &ctx->sspi_credentials, NULL); if (FAILED(sspi_status)) { return map_sspi_status(sspi_status); } *ctx_p = ctx; return APR_SUCCESS; }
NTSTATUS AcquireLMCredentials ( VOID ) { UNICODE_STRING Ntlm; PUCHAR AllocateMemory = NULL; ULONG AllocateLength = 8; NTSTATUS status; TimeStamp Expiry; status = NtAllocateVirtualMemory( NtCurrentProcess(), &AllocateMemory, 0, &AllocateLength, MEM_COMMIT, PAGE_READWRITE ); if ( !NT_SUCCESS(status) ) { return status; } Ntlm.Length = Ntlm.MaximumLength = 8; Ntlm.Buffer = (LPWSTR)AllocateMemory, RtlCopyMemory( Ntlm.Buffer, L"NTLM", 8 ); status = AcquireCredentialsHandle( NULL, // Default principal (PSECURITY_STRING) &Ntlm, SECPKG_CRED_INBOUND, // Need to define this NULL, // No LUID NULL, // No AuthData NULL, // No GetKeyFn NULL, // No GetKeyArg &SrvLmLsaHandle, &Expiry ); (VOID)NtFreeVirtualMemory( NtCurrentProcess(), &AllocateMemory, &AllocateLength, MEM_DECOMMIT ); if ( !NT_SUCCESS(status) ) { status = MapSecurityError(status); return status; } SrvHaveCreds |= HAVENTLM; return status; } // AcquireLMCredentials
void LSSLContext::AcquireCredentials() { //SSPI:инициализация удостоверения //параметны получаемого удостоверения пользователя SCHANNEL_CRED credData; ZeroMemory(&credData, sizeof(credData)); credData.dwVersion = SCHANNEL_CRED_VERSION; //получение дискриптора удостоверения пользователя SECURITY_STATUS sec_s = AcquireCredentialsHandle(0, UNISP_NAME, SECPKG_CRED_OUTBOUND, 0, &credData, 0, 0, &m_hUserCred, &m_UserCredExpiry); //ASSERT(SEC_E_OK==sec_s); }
SchannelCredential(ULONG usage, SchannelCredentialData* pCredentialData) { SECURITY_STATUS result = AcquireCredentialsHandle( NULL, UNISP_NAME, usage, NULL, pCredentialData, NULL, NULL, &credentialHandle_, NULL); }
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options) { TLSContext *c = h->priv_data; TLSShared *s = &c->tls_shared; SECURITY_STATUS sspi_ret; SCHANNEL_CRED schannel_cred = { 0 }; int ret; if ((ret = ff_tls_open_underlying(s, h, uri, options)) < 0) goto fail; if (s->listen) { av_log(h, AV_LOG_ERROR, "TLS Listen Sockets with SChannel is not implemented.\n"); ret = AVERROR(EINVAL); goto fail; } /* SChannel Options */ schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; if (s->verify) schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION | SCH_CRED_REVOCATION_CHECK_CHAIN; else schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE; /* Get credential handle */ sspi_ret = AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL, &schannel_cred, NULL, NULL, &c->cred_handle, &c->cred_timestamp); if (sspi_ret != SEC_E_OK) { av_log(h, AV_LOG_ERROR, "Unable to acquire security credentials (0x%lx)\n", sspi_ret); ret = AVERROR_UNKNOWN; goto fail; } ret = tls_client_handshake(h); if (ret < 0) goto fail; c->connected = 1; return 0; fail: tls_close(h); return ret; }
apr_status_t serf__spnego_create_sec_context(serf__spnego_context_t **ctx_p, const serf__authn_scheme_t *scheme, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { SECURITY_STATUS sspi_status; serf__spnego_context_t *ctx; const char *sspi_package; ctx = apr_pcalloc(result_pool, sizeof(*ctx)); SecInvalidateHandle(&ctx->sspi_context); SecInvalidateHandle(&ctx->sspi_credentials); ctx->initalized = FALSE; ctx->pool = result_pool; ctx->target_name = NULL; ctx->authn_type = scheme->type; apr_pool_cleanup_register(result_pool, ctx, cleanup_ctx, apr_pool_cleanup_null); if (ctx->authn_type == SERF_AUTHN_NEGOTIATE) sspi_package = "Negotiate"; else sspi_package = "NTLM"; sspi_status = AcquireCredentialsHandle( NULL, sspi_package, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &ctx->sspi_credentials, NULL); if (FAILED(sspi_status)) { return map_sspi_status(sspi_status); } *ctx_p = ctx; return APR_SUCCESS; }
BOOL AcquireCreds() { SECURITY_STATUS ss; TimeStamp Lifetime; PSecPkgInfo pkgInfo; // Set the default package to negotiate. tstrcpy_s(g_lpPackageName, 1024, TEXT("Negotiate")); // Initialize the security package. ss = QuerySecurityPackageInfo(g_lpPackageName, &pkgInfo); // get the max token size g_cbMaxMessage = pkgInfo->cbMaxToken; FreeContextBuffer(pkgInfo); // set the max token sizes g_pInBuf = (PBYTE)malloc(g_cbMaxMessage); g_pOutBuf = (PBYTE)malloc(g_cbMaxMessage); // get the security handles ss = AcquireCredentialsHandle( NULL, g_lpPackageName, SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &hcred, &Lifetime); if (!SEC_SUCCESS(ss)) { fprintf(stderr, "AcquireCreds failed: 0x%08x\n", ss); return(FALSE); } return (TRUE); }
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 sqAuthInitiate(char *method, char *username, char *password, char *domain, char *principal){ SEC_WINNT_AUTH_IDENTITY credentials; SECURITY_STATUS ret; ULONG flags = DEFAULT_AUTH_FLAGS; ULONG attrs = 0; sqAuthData *auth; if(debug) { printf("sqAuthInitiate: method=%s, user=%s, pass=%s, domain=%s\n", method, username, password, domain); } auth = calloc(1, sizeof(sqAuthData)); if(principal) auth->principal = strdup(principal); auth->sbdIn.ulVersion = SECBUFFER_VERSION; auth->sbdIn.pBuffers = auth->inbuf; auth->sbdOut.ulVersion = SECBUFFER_VERSION; auth->sbdOut.pBuffers = auth->outbuf; /* initialize additional credentials */ memset(&credentials,0,sizeof(SEC_WINNT_AUTH_IDENTITY)); // XXXX: fixme. use unicode and utf8 conversion credentials.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; if(username) { credentials.User = username; credentials.UserLength = strlen(username); } if(password) { credentials.Password = password; credentials.PasswordLength = strlen(password); } if(domain) { credentials.Domain = domain; credentials.DomainLength = strlen(domain); } ret = AcquireCredentialsHandle(NULL, method, SECPKG_CRED_OUTBOUND, NULL, username ? &credentials : NULL, NULL, NULL, &auth->cred, &auth->expiry); if (ret != SEC_E_OK) { if(debug) printf("AquireCredentialsHandle error: %x\n", ret); return 0; } auth->outbuf[0].BufferType = SECBUFFER_TOKEN; auth->outbuf[0].cbBuffer = 0; auth->outbuf[0].pvBuffer = NULL; auth->outbuf[1].BufferType = SECBUFFER_EMPTY; auth->outbuf[1].cbBuffer = 0; auth->outbuf[1].pvBuffer = NULL; auth->sbdOut.cBuffers = 2; ret = InitializeSecurityContext(&auth->cred, NULL, auth->principal, flags, 0, SECURITY_NETWORK_DREP, NULL, 0, &auth->ctxt, &auth->sbdOut, &attrs, NULL); /* The only expected return value here is SEC_I_CONTINUE_NEEDED since we're just trying to establish the auth session */ if(ret != SEC_I_CONTINUE_NEEDED) { if(debug) printf("InitializeSecurityContext returned: %x\n", ret); return 0; } /* XXXX: fixme. return a real handle */ return (int)auth; }
BOOL GenClientContext ( BYTE *pIn, DWORD cbIn, BYTE *pOut, DWORD *pcbOut, BOOL *pfDone, CHAR *pszTarget, CredHandle *hCred, struct _SecHandle *hcText) { SECURITY_STATUS ss; TimeStamp Lifetime; SecBufferDesc OutBuffDesc; SecBuffer OutSecBuff; SecBufferDesc InBuffDesc; SecBuffer InSecBuff; ULONG ContextAttributes; static TCHAR lpPackageName[1024]; if( NULL == pIn ) { strcpy_s(lpPackageName, 1024 * sizeof(TCHAR), "Negotiate"); ss = AcquireCredentialsHandle ( NULL, lpPackageName, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, hCred, &Lifetime); if (!(SEC_SUCCESS (ss))) { MyHandleError("AcquireCreds failed "); } } //-------------------------------------------------------------------- // Prepare the buffers. OutBuffDesc.ulVersion = 0; OutBuffDesc.cBuffers = 1; OutBuffDesc.pBuffers = &OutSecBuff; OutSecBuff.cbBuffer = *pcbOut; OutSecBuff.BufferType = SECBUFFER_TOKEN; OutSecBuff.pvBuffer = pOut; //------------------------------------------------------------------- // The input buffer is created only if a message has been received // from the server. if (pIn) { InBuffDesc.ulVersion = 0; InBuffDesc.cBuffers = 1; InBuffDesc.pBuffers = &InSecBuff; InSecBuff.cbBuffer = cbIn; InSecBuff.BufferType = SECBUFFER_TOKEN; InSecBuff.pvBuffer = pIn; ss = InitializeSecurityContext ( hCred, hcText, pszTarget, MessageAttribute, 0, SECURITY_NATIVE_DREP, &InBuffDesc, 0, hcText, &OutBuffDesc, &ContextAttributes, &Lifetime); } else { ss = InitializeSecurityContext ( hCred, NULL, pszTarget, MessageAttribute, 0, SECURITY_NATIVE_DREP, NULL, 0, hcText, &OutBuffDesc, &ContextAttributes, &Lifetime); } if (!SEC_SUCCESS (ss)) { MyHandleError ("InitializeSecurityContext failed " ); } //------------------------------------------------------------------- // If necessary, complete the token. if ((SEC_I_COMPLETE_NEEDED == ss) || (SEC_I_COMPLETE_AND_CONTINUE == ss)) { ss = CompleteAuthToken (hcText, &OutBuffDesc); if (!SEC_SUCCESS(ss)) { fprintf (stderr, "complete failed: 0x%08x\n", ss); return FALSE; } } *pcbOut = OutSecBuff.cbBuffer; *pfDone = !((SEC_I_CONTINUE_NEEDED == ss) || (SEC_I_COMPLETE_AND_CONTINUE == ss)); printf ("Token buffer generated (%lu bytes):\n", OutSecBuff.cbBuffer); PrintHexDump (OutSecBuff.cbBuffer, (PBYTE)OutSecBuff.pvBuffer); return TRUE; }
/* * '_sspiGetCredentials()' - Retrieve an SSL/TLS certificate from the system store * If one cannot be found, one is created. */ BOOL /* O - 1 on success, 0 on failure */ _sspiGetCredentials(_sspi_struct_t *conn, /* I - Client connection */ const LPWSTR container, /* I - Cert container name */ const TCHAR *cn, /* I - Common name of certificate */ BOOL isServer) /* I - Is caller a server? */ { HCERTSTORE store = NULL; /* Certificate store */ PCCERT_CONTEXT storedContext = NULL; /* Context created from the store */ PCCERT_CONTEXT createdContext = NULL; /* Context created by us */ DWORD dwSize = 0; /* 32 bit size */ PBYTE p = NULL; /* Temporary storage */ HCRYPTPROV hProv = (HCRYPTPROV) NULL; /* Handle to a CSP */ CERT_NAME_BLOB sib; /* Arbitrary array of bytes */ SCHANNEL_CRED SchannelCred; /* Schannel credential data */ TimeStamp tsExpiry; /* Time stamp */ SECURITY_STATUS Status; /* Status */ HCRYPTKEY hKey = (HCRYPTKEY) NULL; /* Handle to crypto key */ CRYPT_KEY_PROV_INFO kpi; /* Key container info */ SYSTEMTIME et; /* System time */ CERT_EXTENSIONS exts; /* Array of cert extensions */ CRYPT_KEY_PROV_INFO ckp; /* Handle to crypto key */ BOOL ok = TRUE; /* Return value */ DEBUG_printf(("_sspiGetCredentials(conn=%p, container=%p, cn=\"%s\", isServer=%d)", conn, container, cn, isServer)); if (!conn) return (FALSE); if (!cn) return (FALSE); if (!CryptAcquireContextW(&hProv, (LPWSTR) container, MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET)) { if (GetLastError() == NTE_EXISTS) { if (!CryptAcquireContextW(&hProv, (LPWSTR) container, MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET)) { DEBUG_printf(("_sspiGetCredentials: CryptAcquireContext failed: %x\n", GetLastError())); ok = FALSE; goto cleanup; } } } store = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, hProv, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_NO_CRYPT_RELEASE_FLAG | CERT_STORE_OPEN_EXISTING_FLAG, L"MY"); if (!store) { DEBUG_printf(("_sspiGetCredentials: CertOpenSystemStore failed: %x\n", GetLastError())); ok = FALSE; goto cleanup; } dwSize = 0; if (!CertStrToName(X509_ASN_ENCODING, cn, CERT_OID_NAME_STR, NULL, NULL, &dwSize, NULL)) { DEBUG_printf(("_sspiGetCredentials: CertStrToName failed: %x\n", GetLastError())); ok = FALSE; goto cleanup; } p = (PBYTE) malloc(dwSize); if (!p) { DEBUG_printf(("_sspiGetCredentials: malloc failed for %d bytes", dwSize)); ok = FALSE; goto cleanup; } if (!CertStrToName(X509_ASN_ENCODING, cn, CERT_OID_NAME_STR, NULL, p, &dwSize, NULL)) { DEBUG_printf(("_sspiGetCredentials: CertStrToName failed: %x", GetLastError())); ok = FALSE; goto cleanup; } sib.cbData = dwSize; sib.pbData = p; storedContext = CertFindCertificateInStore(store, X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_NAME, &sib, NULL); if (!storedContext) { /* * If we couldn't find the context, then we'll * create a new one */ if (!CryptGenKey(hProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, &hKey)) { DEBUG_printf(("_sspiGetCredentials: CryptGenKey failed: %x", GetLastError())); ok = FALSE; goto cleanup; } ZeroMemory(&kpi, sizeof(kpi)); kpi.pwszContainerName = (LPWSTR) container; kpi.pwszProvName = MS_DEF_PROV_W; kpi.dwProvType = PROV_RSA_FULL; kpi.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID; kpi.dwKeySpec = AT_KEYEXCHANGE; GetSystemTime(&et); et.wYear += 10; ZeroMemory(&exts, sizeof(exts)); createdContext = CertCreateSelfSignCertificate(hProv, &sib, 0, &kpi, NULL, NULL, &et, &exts); if (!createdContext) { DEBUG_printf(("_sspiGetCredentials: CertCreateSelfSignCertificate failed: %x", GetLastError())); ok = FALSE; goto cleanup; } if (!CertAddCertificateContextToStore(store, createdContext, CERT_STORE_ADD_REPLACE_EXISTING, &storedContext)) { DEBUG_printf(("_sspiGetCredentials: CertAddCertificateContextToStore failed: %x", GetLastError())); ok = FALSE; goto cleanup; } ZeroMemory(&ckp, sizeof(ckp)); ckp.pwszContainerName = (LPWSTR) container; ckp.pwszProvName = MS_DEF_PROV_W; ckp.dwProvType = PROV_RSA_FULL; ckp.dwFlags = CRYPT_MACHINE_KEYSET; ckp.dwKeySpec = AT_KEYEXCHANGE; if (!CertSetCertificateContextProperty(storedContext, CERT_KEY_PROV_INFO_PROP_ID, 0, &ckp)) { DEBUG_printf(("_sspiGetCredentials: CertSetCertificateContextProperty failed: %x", GetLastError())); ok = FALSE; goto cleanup; } } ZeroMemory(&SchannelCred, sizeof(SchannelCred)); SchannelCred.dwVersion = SCHANNEL_CRED_VERSION; SchannelCred.cCreds = 1; SchannelCred.paCred = &storedContext; /* * SSPI doesn't seem to like it if grbitEnabledProtocols * is set for a client */ if (isServer) SchannelCred.grbitEnabledProtocols = SP_PROT_SSL3TLS1; /* * Create an SSPI credential. */ Status = AcquireCredentialsHandle(NULL, UNISP_NAME, isServer ? SECPKG_CRED_INBOUND:SECPKG_CRED_OUTBOUND, NULL, &SchannelCred, NULL, NULL, &conn->creds, &tsExpiry); if (Status != SEC_E_OK) { DEBUG_printf(("_sspiGetCredentials: AcquireCredentialsHandle failed: %x", Status)); ok = FALSE; goto cleanup; } cleanup: /* * Cleanup */ if (hKey) CryptDestroyKey(hKey); if (createdContext) CertFreeCertificateContext(createdContext); if (storedContext) CertFreeCertificateContext(storedContext); if (p) free(p); if (store) CertCloseStore(store, 0); if (hProv) CryptReleaseContext(hProv, 0); return (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; }
int SSL_SOCKET :: ServerInit(bool NoLoop) { SECURITY_STATUS ss = 0; /* if (wcslen(un)) { // Find certificate in the store // Open Certificate Store hCS = CertOpenSystemStore(0,_T("MY")); if (!hCS) return -1; CERT_RDN cert_rdn; CERT_RDN_ATTR cert_rdn_attr; cert_rdn.cRDNAttr = 1; cert_rdn.rgRDNAttr = &cert_rdn_attr; cert_rdn_attr.pszObjId = szOID_COMMON_NAME; cert_rdn_attr.dwValueType = CERT_RDN_ANY_TYPE; cert_rdn_attr.Value.cbData = (DWORD)wcslen(un); cert_rdn_attr.Value.pbData = (BYTE *)un; OurCertificate = CertFindCertificateInStore(hCS, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,0,cft,&cert_rdn,NULL); }*/ if (IsExternalCert) { ; } else { //BOOL AX; OurCertificate = CreateOurCertificate(); } // Configure our SSL SChannel memset(&m_SchannelCred,0,sizeof(m_SchannelCred)); m_SchannelCred.dwVersion = SCHANNEL_CRED_VERSION; m_SchannelCred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; m_SchannelCred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_NO_SYSTEM_MAPPER | SCH_CRED_REVOCATION_CHECK_CHAIN; m_SchannelCred.hRootStore = hCS; m_SchannelCred.dwMinimumCipherStrength = 128; if (OurCertificate) { m_SchannelCred.cCreds = 1; m_SchannelCred.paCred = &OurCertificate; } // AcquireCredentialsHandle ss = AcquireCredentialsHandle(0,SCHANNEL_NAME,SECPKG_CRED_INBOUND,0,&m_SchannelCred,0,0,&hCred,0); // ss = AcquireCredentialsHandle(0,UNISP_NAME,SECPKG_CRED_INBOUND,0,&m_SchannelCred,0,0,&hCred,0); if (FAILED(ss)) return -1; if (NoLoop) return 0; return ServerLoop(); }
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; }
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; }
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 SECURITY_STATUS CreateSchannelCredentials( LPCTSTR opt, /* in */ LPSTR pszUserName, /* in */ PCredHandle phCreds) /* out */ { TimeStamp tsExpiry; SECURITY_STATUS Status; SCHANNEL_CRED SchannelCred; DWORD cSupportedAlgs = 0; ALG_ID rgbSupportedAlgs[16]; DWORD dwProtocol = SP_PROT_SSL3 | SP_PROT_SSL2; DWORD aiKeyExch = 0; PCCERT_CONTEXT pCertContext = NULL; /* * If a user name is specified, then attempt to find a client * certificate. Otherwise, just create a NULL credential. */ if (pszUserName) { /* Find client certificate. Note that this sample just searchs for a * certificate that contains the user name somewhere in the subject name. * A real application should be a bit less casual. */ pCertContext = CertFindCertificateInStore(hMyCertStore, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR_A, pszUserName, NULL); if (pCertContext == NULL) { mylog("**** Error 0x%p returned by CertFindCertificateInStore\n", GetLastError()); return SEC_E_NO_CREDENTIALS; } } /* * Build Schannel credential structure. Currently, this sample only * specifies the protocol to be used (and optionally the certificate, * of course). Real applications may wish to specify other parameters * as well. */ ZeroMemory(&SchannelCred, sizeof(SchannelCred)); SchannelCred.dwVersion = SCHANNEL_CRED_VERSION; if (pCertContext) { SchannelCred.cCreds = 1; SchannelCred.paCred = &pCertContext; } SchannelCred.grbitEnabledProtocols = dwProtocol; if (aiKeyExch) { rgbSupportedAlgs[cSupportedAlgs++] = aiKeyExch; } if (cSupportedAlgs) { SchannelCred.cSupportedAlgs = cSupportedAlgs; SchannelCred.palgSupportedAlgs = rgbSupportedAlgs; } SchannelCred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; /* The SCH_CRED_MANUAL_CRED_VALIDATION flag is specified because * this sample verifies the server certificate manually. * Applications that expect to run on WinNT, Win9x, or WinME * should specify this flag and also manually verify the server * certificate. Applications running on newer versions of Windows can * leave off this flag, in which case the InitializeSecurityContext * function will validate the server certificate automatically. */ SchannelCred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; /* * Create an SSPI credential. */ 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() */ phCreds, /* (out) Cred Handle */ &tsExpiry); /* (out) Lifetime (optional) */ if (Status != SEC_E_OK) { mylog("**** Error 0x%p returned by AcquireCredentialsHandle\n", Status); goto cleanup; } cleanup: /* * Free the certificate context. Schannel has already made its own copy. */ if(pCertContext) { CertFreeCertificateContext(pCertContext); } return Status; }
static void on_underlying_io_open_complete(void* context, IO_OPEN_RESULT io_open_result) { TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context; if (tls_io_instance->tlsio_state != TLSIO_STATE_OPENING_UNDERLYING_IO) { tls_io_instance->tlsio_state = TLSIO_STATE_ERROR; indicate_error(tls_io_instance); } else { SecBuffer init_security_buffers[2]; ULONG context_attributes; SECURITY_STATUS status; SCHANNEL_CRED auth_data; auth_data.dwVersion = SCHANNEL_CRED_VERSION; auth_data.cCreds = 0; auth_data.paCred = NULL; auth_data.hRootStore = NULL; auth_data.cSupportedAlgs = 0; auth_data.palgSupportedAlgs = NULL; auth_data.grbitEnabledProtocols = 0; auth_data.dwMinimumCipherStrength = 0; auth_data.dwMaximumCipherStrength = 0; auth_data.dwSessionLifespan = 0; auth_data.dwFlags = SCH_USE_STRONG_CRYPTO | SCH_CRED_NO_DEFAULT_CREDS; auth_data.dwCredFormat = 0; status = AcquireCredentialsHandle(NULL, UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL, &auth_data, NULL, NULL, &tls_io_instance->credential_handle, NULL); if (status != SEC_E_OK) { tls_io_instance->tlsio_state = TLSIO_STATE_ERROR; indicate_error(tls_io_instance); } else { tls_io_instance->credential_handle_allocated = true; init_security_buffers[0].cbBuffer = 0; init_security_buffers[0].BufferType = SECBUFFER_TOKEN; init_security_buffers[0].pvBuffer = NULL; init_security_buffers[1].cbBuffer = 0; init_security_buffers[1].BufferType = SECBUFFER_EMPTY; init_security_buffers[1].pvBuffer = 0; SecBufferDesc security_buffers_desc; security_buffers_desc.cBuffers = 2; security_buffers_desc.pBuffers = init_security_buffers; security_buffers_desc.ulVersion = SECBUFFER_VERSION; status = InitializeSecurityContext(&tls_io_instance->credential_handle, NULL, (SEC_CHAR*)tls_io_instance->host_name, ISC_REQ_EXTENDED_ERROR | ISC_REQ_STREAM | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_USE_SUPPLIED_CREDS, 0, 0, NULL, 0, &tls_io_instance->security_context, &security_buffers_desc, &context_attributes, NULL); if ((status == SEC_I_COMPLETE_NEEDED) || (status == SEC_I_CONTINUE_NEEDED) || (status == SEC_I_COMPLETE_AND_CONTINUE)) { if (xio_send(tls_io_instance->socket_io, init_security_buffers[0].pvBuffer, init_security_buffers[0].cbBuffer, NULL, NULL) != 0) { tls_io_instance->tlsio_state = TLSIO_STATE_ERROR; indicate_error(tls_io_instance); } else { /* set the needed bytes to 1, to get on the next byte how many we actually need */ tls_io_instance->needed_bytes = 1; if (resize_receive_buffer(tls_io_instance, tls_io_instance->needed_bytes + tls_io_instance->received_byte_count) != 0) { tls_io_instance->tlsio_state = TLSIO_STATE_ERROR; indicate_error(tls_io_instance); } else { tls_io_instance->tlsio_state = TLSIO_STATE_HANDSHAKE_CLIENT_HELLO_SENT; } } } } } }
NTSTATUS SrvValidateBlob( IN PSESSION Session, IN PCONNECTION Connection, IN PUNICODE_STRING UserName, IN OUT PCHAR Blob, IN OUT ULONG *BlobLength ) /*++ Routine Description: Validates a Kerberos Blob sent from the client Arguments: Session - A pointer to a session block so that this routine can insert a user token. Connection - A pointer to the connection this user is on. UserName - ASCIIZ string corresponding to the user name to validate. Blob - The Blob to validate and the place to return the output Blob. Note this means that this string space has to be long enough to hold the maximum length Blob. BlobLength - The length of the aforementioned Blob Return Value: NTSTATUS from the security system. --*/ { NTSTATUS Status; ULONG Catts; LARGE_INTEGER Expiry; PUCHAR AllocateMemory = NULL; ULONG AllocateLength = *BlobLength; BOOLEAN virtualMemoryAllocated = FALSE; SecBufferDesc InputToken; SecBuffer InputBuffer; SecBufferDesc OutputToken; SecBuffer OutputBuffer; ULONG oldSessionCount; AllocateLength += 16; Status = NtAllocateVirtualMemory( NtCurrentProcess(), &AllocateMemory, 0, &AllocateLength, MEM_COMMIT, PAGE_READWRITE ); if ( !NT_SUCCESS(Status) ) { INTERNAL_ERROR( ERROR_LEVEL_UNEXPECTED, "Could not allocate Blob Memory %lC\n", Status, NULL); goto get_out; } virtualMemoryAllocated = TRUE; if ( (SrvHaveCreds & HAVEKERBEROS) == 0 ) { // Need to get cred handle first UNICODE_STRING Kerb; Kerb.Length = Kerb.MaximumLength = 16; Kerb.Buffer = (LPWSTR) AllocateMemory; RtlCopyMemory( Kerb.Buffer, MICROSOFT_KERBEROS_NAME, 16); Status = AcquireCredentialsHandle( NULL, // Default principal (PSECURITY_STRING) &Kerb, SECPKG_CRED_INBOUND, // Need to define this NULL, // No LUID NULL, // no AuthData NULL, // no GetKeyFn NULL, // no GetKeyArg &SrvKerberosLsaHandle, (PTimeStamp)&Expiry ); if ( !NT_SUCCESS(Status) ) { Status = MapSecurityError(Status); goto get_out; } SrvHaveCreds |= HAVEKERBEROS; } RtlCopyMemory( AllocateMemory, Blob, *BlobLength ); InputToken.pBuffers = &InputBuffer; InputToken.cBuffers = 1; InputToken.ulVersion = 0; InputBuffer.pvBuffer = AllocateMemory; InputBuffer.cbBuffer = *BlobLength; InputBuffer.BufferType = SECBUFFER_TOKEN; OutputToken.pBuffers = &OutputBuffer; OutputToken.cBuffers = 1; OutputToken.ulVersion = 0; OutputBuffer.pvBuffer = AllocateMemory; OutputBuffer.cbBuffer = *BlobLength; OutputBuffer.BufferType = SECBUFFER_TOKEN; SrvStatistics.SessionLogonAttempts++; Status = AcceptSecurityContext( &SrvKerberosLsaHandle, (PCtxtHandle)NULL, &InputToken, ASC_REQ_EXTENDED_ERROR, // fContextReq SECURITY_NATIVE_DREP, &Session->UserHandle, &OutputToken, &Catts, (PTimeStamp)&Expiry ); Status = MapSecurityError( Status ); if ( NT_SUCCESS(Status) || (Catts & ASC_RET_EXTENDED_ERROR) ) { *BlobLength = OutputBuffer.cbBuffer; RtlCopyMemory( Blob, AllocateMemory, *BlobLength ); // // BUGBUG // All of the following values need to come from someplace // And while we're at it, get the LogonId as well // if(NT_SUCCESS(Status)) { // // Note whether or not this user is an administrator // Session->IsAdmin = SrvIsAdmin( Session->UserHandle ); // // fiddle with the session structures iff the // security context was actually accepted // Session->HaveHandle = TRUE; Session->KickOffTime = Expiry; Session->LogOffTime = Expiry; Session->GuestLogon = FALSE; // No guest logon this way Session->EncryptedLogon = TRUE; // // See if the session count is being exceeded. We'll allow it only // if the new client is an administrator // oldSessionCount = ExInterlockedAddUlong( &SrvStatistics.CurrentNumberOfSessions, 1, &GLOBAL_SPIN_LOCK(Statistics) ); if ( oldSessionCount >= SrvMaxUsers ) { if( oldSessionCount != SrvMaxUsers || !SrvIsAdmin( Session->UserHandle ) ) { ExInterlockedAddUlong( &SrvStatistics.CurrentNumberOfSessions, (ULONG)-1, &GLOBAL_SPIN_LOCK(Statistics) ); DeleteSecurityContext( &Session->UserHandle ); Session->HaveHandle = FALSE; Status = STATUS_REQUEST_NOT_ACCEPTED; goto get_out; } } } } else { *BlobLength = 0; } get_out: if (virtualMemoryAllocated) { (VOID)NtFreeVirtualMemory( NtCurrentProcess(), &AllocateMemory, &AllocateLength, MEM_DECOMMIT ); } return Status; } // SrvValidateBlob
void SchannelContext::connect() { ScopedCertContext pCertContext; m_state = Connecting; // If a user name is specified, then attempt to find a client // certificate. Otherwise, just create a NULL credential. if (!m_cert_name.empty()) { if (m_my_cert_store == NULL) { m_my_cert_store = CertOpenSystemStore(0, m_cert_store_name.c_str()); if (!m_my_cert_store) { ///// printf( "**** Error 0x%x returned by CertOpenSystemStore\n", GetLastError() ); indicateError(); return; } } pCertContext = findCertificateInStore( m_my_cert_store, m_cert_name ); if (pCertContext == NULL) { ///// printf("**** Error 0x%x returned by CertFindCertificateInStore\n", GetLastError()); indicateError(); return; } } // We use an empty list for client certificates PCCERT_CONTEXT clientCerts[1] = {0}; SCHANNEL_CRED sc = {0}; sc.dwVersion = SCHANNEL_CRED_VERSION; /////SSL3? sc.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT | SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT; sc.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION; if (pCertContext) { sc.cCreds = 1; sc.paCred = pCertContext.GetPointer(); sc.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; } else { sc.cCreds = 0; // Let Crypto API find the appropriate certificate for us sc.paCred = clientCerts; sc.dwFlags |= SCH_CRED_USE_DEFAULT_CREDS; } // Swiften performs the server name check for us sc.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; SECURITY_STATUS status = AcquireCredentialsHandle( NULL, UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL, &sc, NULL, NULL, m_credHandle.Reset(), NULL); if (status != SEC_E_OK) { // We failed to obtain the credentials handle indicateError(); return; } SecBuffer outBuffers[2]; // We let Schannel allocate the output buffer for us outBuffers[0].pvBuffer = NULL; outBuffers[0].cbBuffer = 0; outBuffers[0].BufferType = SECBUFFER_TOKEN; // Contains alert data if an alert is generated outBuffers[1].pvBuffer = NULL; outBuffers[1].cbBuffer = 0; outBuffers[1].BufferType = SECBUFFER_ALERT; // Make sure the output buffers are freed ScopedSecBuffer scopedOutputData(&outBuffers[0]); ScopedSecBuffer scopedOutputAlertData(&outBuffers[1]); SecBufferDesc outBufferDesc = {0}; outBufferDesc.cBuffers = 2; outBufferDesc.pBuffers = outBuffers; outBufferDesc.ulVersion = SECBUFFER_VERSION; // Create the initial security context status = InitializeSecurityContext( m_credHandle, NULL, NULL, m_ctxtFlags, 0, 0, NULL, 0, m_ctxtHandle.Reset(), &outBufferDesc, &m_secContext, NULL); if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) { // We failed to initialize the security context handleCertError(status); indicateError(); return; } // Start the handshake sendDataOnNetwork(outBuffers[0].pvBuffer, outBuffers[0].cbBuffer); if (status == SEC_E_OK) { status = validateServerCertificate(); if (status != SEC_E_OK) handleCertError(status); m_state = Connected; determineStreamSizes(); onConnected(); } }
BOOL ServerAuthenticate(const char *hostname) { int rc, rcISC, rcl; BOOL haveToken; int bytesReceived = 0, bytesSent = 0; TimeStamp useBefore; // input and output buffers SecBufferDesc obd, ibd; SecBuffer ob, ib[2]; BOOL haveContext = FALSE; DWORD ctxReq,ctxAttr; int n; short len; SCHANNEL_CRED cred = {0}; char host[256]; struct addrinfo *ai=NULL, hints = {0}; PCCERT_CONTEXT cert; HANDLE hMy = CertOpenSystemStore(0,"MY"); if(!hMy) { rcISC = SEC_E_NO_CREDENTIALS; server_error(1,"[%08x] %s\n",rcISC,GetErrorString(rcISC)); return FALSE; } if(!hostname) { gethostname (host, sizeof host); hints.ai_flags=AI_CANONNAME; if(getaddrinfo(cvs::idn(host),NULL,&hints,&ai)) server_error (1, "can't get canonical hostname"); hostname = ai->ai_canonname; cert = CertFindCertificateInStore(hMy, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, (const wchar_t*)cvs::wide(cvs::decode_idn(hostname)), NULL); } else cert = CertFindCertificateInStore(hMy, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, (const wchar_t*)cvs::wide(hostname), NULL); if(!cert) { rcISC = SEC_E_NO_CREDENTIALS; server_error(1,"No certificate for '%s': %s\n",hostname,GetErrorString(rcISC)); return FALSE; } cred.cCreds = 1; cred.paCred = &cert; if(ai) freeaddrinfo(ai); cred.dwVersion = SCHANNEL_CRED_VERSION; cred.dwFlags = SCH_CRED_USE_DEFAULT_CREDS; rc = AcquireCredentialsHandle( NULL, "SChannel", SECPKG_CRED_INBOUND, NULL, &cred, NULL, NULL, &credHandle, &useBefore ); if ( rc == SEC_E_OK ) haveToken = TRUE; else haveToken = FALSE; CertCloseStore(hMy,0); while ( 1 ) { // prepare to get the server's response ibd.ulVersion = SECBUFFER_VERSION; ibd.cBuffers = 2; ibd.pBuffers = ib; // just one buffer ib[0].BufferType = SECBUFFER_TOKEN; // preping a token here ib[0].cbBuffer = secPackInfo->cbMaxToken; ib[0].pvBuffer = malloc(ib[0].cbBuffer); ib[1].cbBuffer = 0; ib[1].pvBuffer = NULL; ib[1].BufferType = SECBUFFER_EMPTY; // Spare stuff // receive the client's POD rcl = read( current_server()->in_fd, ib[0].pvBuffer, ib[0].cbBuffer); if(rcl<=0) { rc = SEC_E_INTERNAL_ERROR; break; } // by now we have an input buffer obd.ulVersion = SECBUFFER_VERSION; obd.cBuffers = 1; obd.pBuffers = &ob; // just one buffer ob.BufferType = SECBUFFER_TOKEN; // preping a token here ob.cbBuffer = secPackInfo->cbMaxToken; ob.pvBuffer = malloc(secPackInfo->cbMaxToken); if(rc<0) { len=0; if((n=write(current_server()->out_fd,&len,sizeof(len)))<=0) break; break; } ctxReq = ASC_REQ_INTEGRITY | ASC_REQ_CONFIDENTIALITY | ASC_REQ_REPLAY_DETECT | ASC_REQ_SEQUENCE_DETECT | ASC_REQ_STREAM; rc = AcceptSecurityContext( &credHandle, haveContext? &contextHandle: NULL, &ibd, ctxReq, SECURITY_NATIVE_DREP, &contextHandle, &obd, &ctxAttr, &useBefore ); if ( ib[0].pvBuffer != NULL ) { free( ib[0].pvBuffer ); ib[0].pvBuffer = NULL; } if ( rc == SEC_I_COMPLETE_AND_CONTINUE || rc == SEC_I_COMPLETE_NEEDED ) { CompleteAuthToken( &contextHandle, &obd ); if ( rc == SEC_I_COMPLETE_NEEDED ) rc = SEC_E_OK; else if ( rc == SEC_I_COMPLETE_AND_CONTINUE ) rc = SEC_I_CONTINUE_NEEDED; } // send the output buffer off to the server // warning -- this is machine-dependent! FIX IT! if ( rc == SEC_E_OK || rc == SEC_I_CONTINUE_NEEDED ) { if ( ob.cbBuffer != 0 ) { if((n=write(current_server()->out_fd,ob.pvBuffer, ob.cbBuffer))<=0) break; bytesSent += n; } free(ob.pvBuffer); ob.pvBuffer = NULL; ob.cbBuffer = 0; } else { break; } if ( rc != SEC_I_CONTINUE_NEEDED ) break; haveContext = TRUE; } // we arrive here as soon as InitializeSecurityContext() // returns != SEC_I_CONTINUE_NEEDED. if ( rc != SEC_E_OK ) { haveToken = FALSE; } if(rc<0) server_error(0,"[%08x] %s\n",rc, GetErrorString(rc)); return haveToken?TRUE:FALSE; }
static SSLSTREAM *ssl_start (TCPSTREAM *tstream,char *host,unsigned long flags) { SECURITY_STATUS e; ULONG a; TimeStamp t; SecBuffer ibuf[2],obuf[1]; SecBufferDesc ibufs,obufs; SCHANNEL_CRED tlscred; CERT_CONTEXT *cert; CERT_CHAIN_PARA chparam; CERT_CHAIN_CONTEXT *chain; SSL_EXTRA_CERT_CHAIN_POLICY_PARA policy; CERT_CHAIN_POLICY_PARA polparam; CERT_CHAIN_POLICY_STATUS status; char tmp[MAILTMPLEN],certname[256]; char *reason = NIL; ULONG req = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_USE_SESSION_KEY | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM | ISC_REQ_EXTENDED_ERROR | ISC_REQ_MANUAL_CRED_VALIDATION; LPSTR usage[] = { szOID_PKIX_KP_SERVER_AUTH, szOID_SERVER_GATED_CRYPTO, szOID_SGC_NETSCAPE }; PWSTR whost = NIL; char *buf = (char *) fs_get (ssltsz); unsigned long size = 0; sslcertificatequery_t scq = (sslcertificatequery_t) mail_parameters (NIL,GET_SSLCERTIFICATEQUERY,NIL); sslfailure_t sf = (sslfailure_t) mail_parameters (NIL,GET_SSLFAILURE,NIL); SSLSTREAM *stream = (SSLSTREAM *) memset (fs_get (sizeof (SSLSTREAM)),0, sizeof (SSLSTREAM)); stream->tcpstream = tstream; /* bind TCP stream */ /* initialize TLS credential */ memset (&tlscred,0,sizeof (SCHANNEL_CRED)); tlscred.dwVersion = SCHANNEL_CRED_VERSION; tlscred.grbitEnabledProtocols = SP_PROT_TLS1; /* acquire credentials */ if (AcquireCredentialsHandle (NIL,UNISP_NAME,SECPKG_CRED_OUTBOUND,NIL,(flags & NET_TLSCLIENT) ? &tlscred : NIL,NIL,NIL,&stream->cred,&t) != SEC_E_OK) reason = "Acquire credentials handle failed"; else while (!reason) { /* negotiate security context */ /* initialize buffers */ ibuf[0].cbBuffer = size; ibuf[0].pvBuffer = buf; ibuf[1].cbBuffer = 0; ibuf[1].pvBuffer = NIL; obuf[0].cbBuffer = 0; obuf[0].pvBuffer = NIL; ibuf[0].BufferType = obuf[0].BufferType = SECBUFFER_TOKEN; ibuf[1].BufferType = SECBUFFER_EMPTY; /* initialize buffer descriptors */ ibufs.ulVersion = obufs.ulVersion = SECBUFFER_VERSION; ibufs.cBuffers = 2; obufs.cBuffers = 1; ibufs.pBuffers = ibuf; obufs.pBuffers = obuf; /* negotiate security */ e = InitializeSecurityContext (&stream->cred,size ? &stream->context : NIL,host,req,0, SECURITY_NETWORK_DREP,size? &ibufs:NIL,0,&stream->context,&obufs,&a,&t); /* have an output buffer we need to send? */ if (obuf[0].pvBuffer && obuf[0].cbBuffer) { if (!tcp_sout (stream->tcpstream,obuf[0].pvBuffer,obuf[0].cbBuffer)) reason = "Unexpected TCP output disconnect"; /* free the buffer */ FreeContextBuffer (obuf[0].pvBuffer); } if (!reason) switch (e) { /* negotiation state */ case SEC_I_INCOMPLETE_CREDENTIALS: break; /* server wants client auth */ case SEC_I_CONTINUE_NEEDED: if (size) { /* continue, read any data? */ /* yes, anything regurgiated back to us? */ if (ibuf[1].BufferType == SECBUFFER_EXTRA) { /* yes, set this as the new data */ memmove (buf,buf + size - ibuf[1].cbBuffer,ibuf[1].cbBuffer); size = ibuf[1].cbBuffer; break; } size = 0; /* otherwise, read more stuff from server */ } case SEC_E_INCOMPLETE_MESSAGE: /* need to read more data from server */ if (!tcp_getdata (stream->tcpstream)) reason = "Unexpected TCP input disconnect"; else { memcpy (buf+size,stream->tcpstream->iptr,stream->tcpstream->ictr); size += stream->tcpstream->ictr; /* empty it from TCP's buffers */ stream->tcpstream->iptr += stream->tcpstream->ictr; stream->tcpstream->ictr = 0; } break; case SEC_E_OK: /* success, any data to be regurgitated? */ if (ibuf[1].BufferType == SECBUFFER_EXTRA) { /* yes, set this as the new data */ memmove (stream->tcpstream->iptr = stream->tcpstream->ibuf, buf + size - ibuf[1].cbBuffer,ibuf[1].cbBuffer); stream->tcpstream->ictr = ibuf[1].cbBuffer; } if (!(flags & NET_NOVALIDATECERT)) { /* need validation, make wchar of host */ if (!((size = MultiByteToWideChar (CP_ACP,0,host,-1,NIL,0)) && (whost = (PWSTR) fs_get (size*sizeof (WCHAR))) && MultiByteToWideChar (CP_ACP,0,host,-1,whost,size))) fatal ("Can't make wchar of host name!"); /* get certificate */ if ((QueryContextAttributes (&stream->context,SECPKG_ATTR_REMOTE_CERT_CONTEXT,&cert) != SEC_E_OK) || !cert) { reason = "*Unable to get certificate"; strcpy (certname,"<no certificate>"); } else { /* get certificate subject name */ CertNameToStr (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &cert->pCertInfo->Subject,CERT_X500_NAME_STR, certname,255); /* build certificate chain */ memset (&chparam,0,sizeof (chparam)); chparam.cbSize = sizeof (chparam); chparam.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; chparam.RequestedUsage.Usage.rgpszUsageIdentifier = usage; chparam.RequestedUsage.Usage.cUsageIdentifier = sizeof (usage) / sizeof (LPSTR); if (!CertGetCertificateChain (NIL,cert,NIL,cert->hCertStore,&chparam,NIL,NIL,&chain)) reason = ssl_analyze_status (GetLastError (),tmp); else { /* validate certificate chain */ memset (&policy,0,sizeof (SSL_EXTRA_CERT_CHAIN_POLICY_PARA)); policy.cbStruct = sizeof (SSL_EXTRA_CERT_CHAIN_POLICY_PARA); policy.dwAuthType = AUTHTYPE_SERVER; policy.fdwChecks = NIL; policy.pwszServerName = whost; memset (&polparam,0,sizeof (polparam)); polparam.cbSize = sizeof (polparam); polparam.pvExtraPolicyPara = &policy; memset (&status,0,sizeof (status)); status.cbSize = sizeof (status); if (!CertVerifyCertificateChainPolicy (CERT_CHAIN_POLICY_SSL,chain,&polparam,&status)) reason = ssl_analyze_status (GetLastError (),tmp); else if (status.dwError) reason = ssl_analyze_status (status.dwError,tmp); CertFreeCertificateChain (chain); } } if (whost) fs_give ((void **) &whost); if (reason) { /* got an error? */ /* application callback */ if (scq) reason = (*scq) ((*reason == '*') ? reason + 1 : reason, host,certname) ? NIL : ""; else if (*certname) { /* error message to return via mm_log() */ sprintf (buf,"*%.128s: %.255s", (*reason == '*') ? reason + 1 : reason,certname); reason = buf; } } } if (reason || (reason = ssl_analyze_status (QueryContextAttributes (&stream->context,SECPKG_ATTR_STREAM_SIZES,&stream->sizes),buf))) break; /* error in certificate or getting sizes */ fs_give ((void **) &buf); /* flush temporary buffer */ /* make maximum-sized buffers */ stream->bufsize = stream->sizes.cbHeader + stream->sizes.cbMaximumMessage + stream->sizes.cbTrailer; if (stream->sizes.cbMaximumMessage < SSLBUFLEN) fatal ("cbMaximumMessage is less than SSLBUFLEN!"); else if (stream->sizes.cbMaximumMessage < 16384) { sprintf (tmp,"WINDOWS BUG: cbMaximumMessage = %ld, should be 16384", (long) stream->sizes.cbMaximumMessage); mm_log (tmp,NIL); } stream->ibuf = (char *) fs_get (stream->bufsize); stream->obuf = (char *) fs_get (stream->bufsize); return stream; default: reason = ssl_analyze_status (e,buf); } } ssl_close (stream); /* failed to do SSL */ stream = NIL; /* no stream returned */ switch (*reason) { /* analyze reason */ case '*': /* certificate failure */ ++reason; /* skip over certificate failure indication */ /* pass to error callback */ if (sf) (*sf) (host,reason,flags); else { /* no error callback, build error message */ sprintf (tmp,"Certificate failure for %.80s: %.512s",host,reason); mm_log (tmp,ERROR); } case '\0': /* user answered no to certificate callback */ if (flags & NET_TRYSSL) /* return dummy stream to stop tryssl */ stream = (SSLSTREAM *) memset (fs_get (sizeof (SSLSTREAM)),0, sizeof (SSLSTREAM)); break; default: /* non-certificate failure */ if (flags & NET_TRYSSL); /* no error output if tryssl */ /* pass to error callback */ else if (sf) (*sf) (host,reason,flags); else { /* no error callback, build error message */ sprintf (tmp,"TLS/SSL failure for %.80s: %.512s",host,reason); mm_log (tmp,ERROR); } break; } fs_give ((void **) &buf); /* flush temporary buffer */ return stream; }
static sqInt sqSetupCert(sqSSL *ssl, char *certName, int server) { SCHANNEL_CRED sc_cred = { 0 }; SECURITY_STATUS ret; HCERTSTORE hStore; PCCERT_CONTEXT pContext = NULL; DWORD dwPropSize; WCHAR wFriendlyName[MAX_NAME_SIZE]; char bFriendlyName[MAX_NAME_SIZE]; if(certName) { hStore = CertOpenSystemStore(0, "MY"); if(!hStore) { if(ssl->loglevel) printf("sqSetupCert: CertOpenSystemStore failed\n"); return 0; } pContext = NULL; /* Enumerate the certificate store to find the cert with the given friendly name */ while(pContext = CertEnumCertificatesInStore(hStore, pContext)) { if(ssl->loglevel) printf("Checking certificate: "); dwPropSize = MAX_NAME_SIZE * sizeof(WCHAR); if(!CertGetCertificateContextProperty(pContext, CERT_FRIENDLY_NAME_PROP_ID, wFriendlyName, &dwPropSize)) { if(ssl->loglevel) printf("<no friendly name>"); continue; } if(!WideCharToMultiByte(CP_UTF8, 0, wFriendlyName, -1, bFriendlyName, MAX_NAME_SIZE, NULL, NULL)) { if(ssl->loglevel) printf("<utf-8 conversion failure>"); continue; } if(ssl->loglevel) printf("%s\n", bFriendlyName); if(strcmp(certName, bFriendlyName) == 0) break; } if(pContext == 0) { /* For compatibility with older versions of SqueakSSL, attempt to match against subject string */ pContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR_A, certName, NULL); } if(!pContext) { if(ssl->loglevel) printf("sqSetupCert: No suitable certificate found\n"); CertCloseStore(hStore, 0); return 0; } } sc_cred.dwVersion = SCHANNEL_CRED_VERSION; sc_cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_MANUAL_CRED_VALIDATION; sc_cred.grbitEnabledProtocols = server ? SP_PROT_TLS1_SERVER | SP_PROT_SSL3_SERVER : 0; sc_cred.dwMinimumCipherStrength = 0; sc_cred.dwMaximumCipherStrength = 0; if(pContext) { sc_cred.cCreds = 1; sc_cred.paCred = &pContext; } else { sc_cred.cCreds = 0; } ret = AcquireCredentialsHandle(NULL, UNISP_NAME, server ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND, NULL, &sc_cred, NULL, NULL, &ssl->sslCred, NULL); if(ssl->loglevel) printf("AquireCredentialsHandle returned: %x\n", ret); if(pContext) { CertCloseStore(hStore, 0); CertFreeCertificateContext(pContext); } if (ret != SEC_E_OK) { if(ssl->loglevel) printf("AquireCredentialsHandle error: %x\n", ret); return 0; } return 1; }
/* * Send initial SSPI authentication token. * If use_negotiate is 0, use kerberos authentication package which is * compatible with Unix. If use_negotiate is 1, use the negotiate package * which supports both kerberos and NTLM, but is not compatible with Unix. */ static int pg_SSPI_startup(PGconn *conn, int use_negotiate) { SECURITY_STATUS r; TimeStamp expire; conn->sspictx = NULL; /* * Retreive credentials handle */ conn->sspicred = malloc(sizeof(CredHandle)); if (conn->sspicred == NULL) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n")); return STATUS_ERROR; } r = AcquireCredentialsHandle(NULL, use_negotiate ? "negotiate" : "kerberos", SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, conn->sspicred, &expire); if (r != SEC_E_OK) { pg_SSPI_error(conn, libpq_gettext("could not acquire SSPI credentials"), r); free(conn->sspicred); conn->sspicred = NULL; return STATUS_ERROR; } /* * Compute target principal name. SSPI has a different format from GSSAPI, * but not more complex. We can skip the @REALM part, because Windows will * fill that in for us automatically. */ if (!(conn->pghost && conn->pghost[0] != '\0')) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("host name must be specified\n")); return STATUS_ERROR; } conn->sspitarget = malloc(strlen(conn->krbsrvname) + strlen(conn->pghost) + 2); if (!conn->sspitarget) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n")); return STATUS_ERROR; } sprintf(conn->sspitarget, "%s/%s", conn->krbsrvname, conn->pghost); /* * Indicate that we're in SSPI authentication mode to make sure that * pg_SSPI_continue is called next time in the negotiation. */ conn->usesspi = 1; return pg_SSPI_continue(conn); }
static void on_underlying_io_open_complete(void* context, IO_OPEN_RESULT io_open_result) { TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context; if (tls_io_instance->tlsio_state != TLS_SERVER_IO_STATE_OPENING_UNDERLYING_IO) { tls_io_instance->tlsio_state = TLS_SERVER_IO_STATE_ERROR; indicate_error(tls_io_instance); } else { if (io_open_result != IO_OPEN_OK) { tls_io_instance->tlsio_state = TLS_SERVER_IO_STATE_NOT_OPEN; if (tls_io_instance->on_io_open_complete != NULL) { tls_io_instance->on_io_open_complete(tls_io_instance->on_io_open_complete_context, IO_OPEN_ERROR); } } else { SECURITY_STATUS status; SCHANNEL_CRED auth_data; PCCERT_CONTEXT certContext; auth_data.dwVersion = SCHANNEL_CRED_VERSION; if (tls_io_instance->x509_schannel_handle != NULL) { certContext = x509_schannel_get_certificate_context(tls_io_instance->x509_schannel_handle); auth_data.cCreds = 1; auth_data.paCred = &certContext; } else { certContext = tls_io_instance->cert_context; auth_data.cCreds = 1; auth_data.paCred = &certContext; } auth_data.hRootStore = NULL; auth_data.cSupportedAlgs = 0; auth_data.palgSupportedAlgs = NULL; #if defined(SP_PROT_TLS1_2_SERVER) auth_data.grbitEnabledProtocols = SP_PROT_TLS1_2_SERVER; #else auth_data.grbitEnabledProtocols = SP_PROT_TLS1_SERVER; #endif auth_data.dwMinimumCipherStrength = 0; auth_data.dwMaximumCipherStrength = 0; auth_data.dwSessionLifespan = 0; auth_data.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER; auth_data.dwCredFormat = 0; status = AcquireCredentialsHandle(NULL, UNISP_NAME, SECPKG_CRED_INBOUND, NULL, &auth_data, NULL, NULL, &tls_io_instance->credential_handle, NULL); if (status != SEC_E_OK) { tls_io_instance->tlsio_state = TLS_SERVER_IO_STATE_ERROR; indicate_error(tls_io_instance); } else { tls_io_instance->credential_handle_allocated = true; tls_io_instance->needed_bytes = 1; tls_io_instance->tlsio_state = TLS_SERVER_IO_STATE_WAITING_FOR_CLIENT_HELLO; } } } }