Example #1
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 #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;
}