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>());
}
Example #2
0
/*
 * 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;
}