Example #1
0
bool ZStreamRWCon_SSL_Win::pConnect()
{
    SecBuffer outSB[1];
    outSB[0].cbBuffer = 0;
    outSB[0].pvBuffer = nullptr;
    outSB[0].BufferType = SECBUFFER_TOKEN;

    SecBufferDesc outSBD;
    outSBD.cBuffers = 1;
    outSBD.pBuffers = outSB;
    outSBD.ulVersion = SECBUFFER_VERSION;

    DWORD attributes;
    if (SEC_I_CONTINUE_NEEDED != spPSFT->InitializeSecurityContextA(
                &fCredHandle,
                nullptr,
                nullptr, // other party, needed if we're verifying
                spRequirements,
                0, // Reserved1
                SECURITY_NATIVE_DREP,
                nullptr,
                0, // Reserved2
                &fCtxtHandle,
                &outSBD,
                &attributes,
                nullptr))
    {
        return false;
    }

    spWriteFreeFlush(outSB[0], fStreamW);

    return this->pHandshake();
}
Example #2
0
/*
 * Wrapper arround initializeSecurityContext.  Supplies several
 * default parameters as well as logging in case of errors.
 */
static SECURITY_STATUS
initializeSecurityContext(CredHandle * credentials, CtxtHandle * context,
                          char *spn, ULONG contextReq,
                          SecBufferDesc * inBuffer, CtxtHandle * newContext,
                          SecBufferDesc * outBuffer)
{
    ULONG contextAttributes;
    SECURITY_STATUS status;

    status =
        pSFT->InitializeSecurityContextA(credentials, context, spn, contextReq,
                                        0, SECURITY_NETWORK_DREP, inBuffer, 0,
                                        newContext, outBuffer,
                                        &contextAttributes, NULL);

    if (!SEC_SUCCESS(status)) {
        if (status == SEC_E_INVALID_TOKEN) {
            NE_DEBUG(NE_DBG_HTTPAUTH,
                     "InitializeSecurityContext [fail] SEC_E_INVALID_TOKEN.\n");
        } else if (status == SEC_E_UNSUPPORTED_FUNCTION) {
            NE_DEBUG(NE_DBG_HTTPAUTH,
                     "InitializeSecurityContext [fail] SEC_E_UNSUPPORTED_FUNCTION.\n");
        } else {
            NE_DEBUG(NE_DBG_HTTPAUTH,
                     "InitializeSecurityContext [fail] [%x].\n", status);
        }
    }

    return status;
}
Example #3
0
static int
tds_sspi_handle_next(TDSSOCKET * tds, struct tds_authentication * tds_auth, size_t len)
{
	SecBuffer in_buf, out_buf;
	SecBufferDesc in_desc, out_desc;
	SECURITY_STATUS status;
	ULONG attrs;
	TimeStamp ts;
	TDS_UCHAR *auth_buf;

	TDSSSPIAUTH *auth = (TDSSSPIAUTH *) tds_auth;

	if (len < 32 || len > NTLMBUF_LEN)
		return TDS_FAIL;

	auth_buf = (TDS_UCHAR *) malloc(len);
	if (!auth_buf)
		return TDS_FAIL;
	tds_get_n(tds, auth_buf, (int)len);

	in_desc.ulVersion  = out_desc.ulVersion  = SECBUFFER_VERSION;
	in_desc.cBuffers   = out_desc.cBuffers   = 1;
	in_desc.pBuffers   = &in_buf;
	out_desc.pBuffers   = &out_buf;

	in_buf.BufferType = SECBUFFER_TOKEN;
	in_buf.pvBuffer   = auth_buf;
	in_buf.cbBuffer   = (ULONG)len;

	out_buf.BufferType = SECBUFFER_TOKEN;
	out_buf.pvBuffer   = auth->tds_auth.packet;
	out_buf.cbBuffer   = NTLMBUF_LEN;

	status = sec_fn->InitializeSecurityContextA(&auth->cred, &auth->cred_ctx, auth->sname,
		ISC_REQ_CONFIDENTIALITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION,
		0, SECURITY_NETWORK_DREP, &in_desc,
		0, &auth->cred_ctx, &out_desc,
		&attrs, &ts);

	free(auth_buf);

	if (status != SEC_E_OK)
		return TDS_FAIL;
	if (out_buf.cbBuffer == 0)
		return TDS_SUCCEED;

	tds_put_n(tds, auth->tds_auth.packet, out_buf.cbBuffer);

	return tds_flush_packet(tds);
}
Example #4
0
void ZStreamRWCon_SSL_Win::Imp_SendDisconnect()
{
    ZAcqMtx acq(fMtx_W);

    if (not fSendOpen)
        return;

    fSendOpen = false;

    SecBuffer outSB[1];
    outSB[0].cbBuffer = 0;
    outSB[0].pvBuffer = nullptr;
    outSB[0].BufferType= SECBUFFER_TOKEN;

    SecBufferDesc outSBD;
    outSBD.cBuffers = 1;
    outSBD.pBuffers = outSB;
    outSBD.ulVersion = SECBUFFER_VERSION;

    DWORD attributes;
    SECURITY_STATUS scRet = spPSFT->InitializeSecurityContextA(
                                &fCredHandle,
                                &fCtxtHandle,
                                nullptr,
                                spRequirements,
                                0, // Reserved1
                                SECURITY_NATIVE_DREP,
                                nullptr,
                                0, // Reserved2
                                nullptr,
                                &outSBD,
                                &attributes,
                                nullptr);

    if (FAILED(scRet))
        return;

    spWriteFreeFlush(outSB[0], fStreamW);
}
Example #5
0
/**
 * Build a SSPI packet to send to server
 * @param tds     A pointer to the TDSSOCKET structure managing a client/server operation.
 */
TDSAUTHENTICATION *
tds_sspi_get_auth(TDSSOCKET * tds)
{
	SecBuffer buf;
	SecBufferDesc desc;
	SECURITY_STATUS status;
	ULONG attrs;
	TimeStamp ts;
	SEC_WINNT_AUTH_IDENTITY identity;
	const char *p, *user_name, *server_name;

	TDSSSPIAUTH *auth;
	TDSCONNECTION *connection = tds->connection;

	/* check connection */
	if (!connection)
		return NULL;

	if (!tds_init_secdll())
		return NULL;

	/* parse username/password informations */
	memset(&identity, 0, sizeof(identity));
	user_name = tds_dstr_cstr(&connection->user_name);
	if ((p = strchr(user_name, '\\')) != NULL) {
		identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
		identity.Password = (void *) tds_dstr_cstr(&connection->password);
		identity.PasswordLength = tds_dstr_len(&connection->password);
		identity.Domain = (void *) user_name;
		identity.DomainLength = p - user_name;
		user_name = p + 1;
		identity.User = (void *) user_name;
		identity.UserLength = strlen(user_name);
	}

	auth = (TDSSSPIAUTH *) calloc(1, sizeof(TDSSSPIAUTH));
	if (!auth || !tds->connection)
		return NULL;

	auth->tds_auth.free = tds_sspi_free;
	auth->tds_auth.handle_next = tds_sspi_handle_next;

	/* using Negotiate system will use proper protocol (either NTLM or Kerberos) */
	if (sec_fn->AcquireCredentialsHandleA(NULL, (char *)"Negotiate", SECPKG_CRED_OUTBOUND,
		NULL, identity.Domain ? &identity : NULL,
		NULL, NULL, &auth->cred, &ts) != SEC_E_OK) {
		free(auth);
		return NULL;
	}

	/* allocate buffer */
	auth->tds_auth.packet = (TDS_UCHAR *) malloc(NTLMBUF_LEN);
	if (!auth->tds_auth.packet) {
		sec_fn->FreeCredentialsHandle(&auth->cred);
		free(auth);
		return NULL;
	}
	desc.ulVersion = SECBUFFER_VERSION;
	desc.cBuffers  = 1;
	desc.pBuffers  = &buf;

	buf.cbBuffer   = NTLMBUF_LEN;
	buf.BufferType = SECBUFFER_TOKEN;
	buf.pvBuffer   = auth->tds_auth.packet;

	/* build SPN */
	server_name = tds_dstr_cstr(&connection->server_host_name);
	if (strchr(server_name, '.') == NULL) {
		struct hostent *host = gethostbyname(server_name);
		if (host && strchr(host->h_name, '.') != NULL)
			server_name = host->h_name;
	}
	if (strchr(server_name, '.') != NULL) {
		if (asprintf(&auth->sname, "MSSQLSvc/%s:%d", server_name, connection->port) < 0) {
			free(auth->tds_auth.packet);
			sec_fn->FreeCredentialsHandle(&auth->cred);
			free(auth);
			return NULL;
		}
		tdsdump_log(TDS_DBG_NETWORK, "kerberos name %s\n", auth->sname);
	}

	status = sec_fn->InitializeSecurityContextA(&auth->cred, NULL, auth->sname,
		ISC_REQ_CONFIDENTIALITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION,
		0, SECURITY_NETWORK_DREP,
		NULL, 0,
		&auth->cred_ctx, &desc,
		&attrs, &ts);

	if (status == SEC_I_COMPLETE_AND_CONTINUE || status == SEC_I_CONTINUE_NEEDED) {
		sec_fn->CompleteAuthToken(&auth->cred_ctx, &desc);
	} else if(status != SEC_E_OK) {
		free(auth->sname);
		free(auth->tds_auth.packet);
		sec_fn->FreeCredentialsHandle(&auth->cred);
		free(auth);
		return NULL;
	}

	auth->tds_auth.packet_len = buf.cbBuffer;
	return &auth->tds_auth;
}
Example #6
0
bool ZStreamRWCon_SSL_Win::pHandshake()
{
    for (;;)
    {
        SecBuffer inSB[2];

        // Data from peer is in fBufferEnc, and passed to schannel via inSB[0].
        inSB[0].cbBuffer = fBufferEnc.size();
        inSB[0].pvBuffer = ZUtil_STL::sFirstOrNil(fBufferEnc);
        inSB[0].BufferType = SECBUFFER_TOKEN;

        // After calling schannel, any unused data in fBufferEnc is described by inSB[1].
        inSB[1].cbBuffer = 0;
        inSB[1].pvBuffer = nullptr;
        inSB[1].BufferType = SECBUFFER_EMPTY;

        SecBufferDesc inSBD;
        inSBD.cBuffers = 2;
        inSBD.pBuffers = inSB;
        inSBD.ulVersion = SECBUFFER_VERSION;

        // Will hold data to be sent to peer
        SecBuffer outSB[1];
        outSB[0].cbBuffer = 0;
        outSB[0].pvBuffer = nullptr;
        outSB[0].BufferType= SECBUFFER_TOKEN;

        SecBufferDesc outSBD;
        outSBD.cBuffers = 1;
        outSBD.pBuffers = outSB;
        outSBD.ulVersion = SECBUFFER_VERSION;

        DWORD attributes;
        const SECURITY_STATUS result = spPSFT->InitializeSecurityContextA(
                                           &fCredHandle,
                                           &fCtxtHandle,
                                           nullptr,
                                           spRequirements,
                                           0, // Reserved1
                                           SECURITY_NATIVE_DREP,
                                           &inSBD,
                                           0, // Reserved2
                                           nullptr,
                                           &outSBD,
                                           &attributes,
                                           nullptr);

        if (result == SEC_E_INCOMPLETE_MESSAGE)
        {
            if (not spReadMore(fBufferEnc, fStreamR))
                return false;
        }
        else
        {
            // Send anything that was generated.
            spWriteFreeFlush(outSB[0], fStreamW);

            if (FAILED(result))
                return false;

            // Remove consumed data.
            if (inSB[1].BufferType == SECBUFFER_EXTRA)
                fBufferEnc.erase(fBufferEnc.begin(), fBufferEnc.end() - inSB[1].cbBuffer);
            else
                fBufferEnc.clear();

            if (result == SEC_E_OK)
            {
                // Handshake completed successfully.
                return true;
            }
        }
    }
}