WindowsGSSAPIClientAuthenticator::WindowsGSSAPIClientAuthenticator(const std::string& hostname, const std::string& domainname, int port) : ClientAuthenticator("GSSAPI"), step_(BuildingSecurityContext), error_(false), haveCredentialsHandle_(false), haveContextHandle_(false), haveCompleteContext_(false) { WindowsServicePrincipalName servicePrincipalName(domainname); servicePrincipalName.setInstanceName(hostname); if ((port != -1) && (port != 5222)) { servicePrincipalName.setInstancePort(port); } servicePrincipalNameString_ = servicePrincipalName.toString(); errorCode_ = acquireCredentialsHandle(&credentialsHandle_); if (isError()) { return; } else { haveCredentialsHandle_ = true; } buildSecurityContext(boost::optional<ByteArray>()); }
/* * Processes received authentication tokens as well as supplies the * response token. */ int ne_sspi_authenticate(void *context, const char *base64Token, char **responseToken) { SecBufferDesc outBufferDesc; SecBuffer outBuffer; int status; SECURITY_STATUS securityStatus; ULONG contextFlags; SSPIContext *sspiContext; if (initialized <= 0) { return -1; } status = getContext(context, &sspiContext); if (status) { return status; } /* TODO: Not sure what flags should be set. joe: this needs to be * driven by the ne_auth interface; the GSSAPI code needs similar * flags. */ contextFlags = ISC_REQ_CONFIDENTIALITY | ISC_REQ_MUTUAL_AUTH; initSingleEmptyBuffer(&outBufferDesc, &outBuffer); status = makeBuffer(&outBufferDesc, sspiContext->maxTokenSize); if (status) { return status; } if (base64Token) { SecBufferDesc inBufferDesc; SecBuffer inBuffer; if (!sspiContext->continueNeeded) { freeBuffer(&outBufferDesc); NE_DEBUG(NE_DBG_HTTPAUTH, "sspi: Got an unexpected token.\n"); return -1; } initSingleEmptyBuffer(&inBufferDesc, &inBuffer); status = base64ToBuffer(base64Token, &inBufferDesc); if (status) { freeBuffer(&outBufferDesc); return status; } securityStatus = initializeSecurityContext(&sspiContext->credentials, &(sspiContext->context), sspiContext->serverName, contextFlags, &inBufferDesc, &(sspiContext->context), &outBufferDesc); if (securityStatus == SEC_E_OK) { sspiContext->authfinished = 1; } freeBuffer(&inBufferDesc); } else { if (sspiContext->continueNeeded) { freeBuffer(&outBufferDesc); NE_DEBUG(NE_DBG_HTTPAUTH, "sspi: Expected a token from server.\n"); return -1; } if (sspiContext->authfinished && (sspiContext->credentials.dwLower || sspiContext->credentials.dwUpper)) { if (sspiContext->authfinished) { freeBuffer(&outBufferDesc); sspiContext->authfinished = 0; NE_DEBUG(NE_DBG_HTTPAUTH,"sspi: failing because starting over from failed try.\n"); return -1; } sspiContext->authfinished = 0; } /* Reset any existing context since we are starting over */ resetContext(sspiContext); if (acquireCredentialsHandle (&sspiContext->credentials, sspiContext->mechanism) != SEC_E_OK) { freeBuffer(&outBufferDesc); NE_DEBUG(NE_DBG_HTTPAUTH, "sspi: acquireCredentialsHandle failed.\n"); return -1; } securityStatus = initializeSecurityContext(&sspiContext->credentials, NULL, sspiContext->serverName, contextFlags, NULL, &(sspiContext->context), &outBufferDesc); } if (securityStatus == SEC_I_COMPLETE_AND_CONTINUE || securityStatus == SEC_I_COMPLETE_NEEDED) { SECURITY_STATUS compleStatus = pSFT->CompleteAuthToken(&(sspiContext->context), &outBufferDesc); if (compleStatus != SEC_E_OK) { freeBuffer(&outBufferDesc); NE_DEBUG(NE_DBG_HTTPAUTH, "sspi: CompleteAuthToken failed.\n"); return -1; } } if (securityStatus == SEC_I_COMPLETE_AND_CONTINUE || securityStatus == SEC_I_CONTINUE_NEEDED) { sspiContext->continueNeeded = 1; } else { sspiContext->continueNeeded = 0; } if (!(securityStatus == SEC_I_COMPLETE_AND_CONTINUE || securityStatus == SEC_I_COMPLETE_NEEDED || securityStatus == SEC_I_CONTINUE_NEEDED || securityStatus == SEC_E_OK)) { NE_DEBUG(NE_DBG_HTTPAUTH, "sspi: initializeSecurityContext [failed] [%x].\n", securityStatus); freeBuffer(&outBufferDesc); return -1; } *responseToken = ne_base64(outBufferDesc.pBuffers->pvBuffer, outBufferDesc.pBuffers->cbBuffer); freeBuffer(&outBufferDesc); return 0; }