Пример #1
0
/**
   \details exchange_ds_rrf RfrGetFQDNFromLegacyDN (0x1) function

   \param dce_call pointer to the session context
   \param mem_ctx pointer to the memory context
   \param r pointer to the RfrGetFQDNFromLegacyDN request data

   \return MAPI_E_SUCCESS on success
 */
static enum MAPISTATUS dcesrv_RfrGetFQDNFromLegacyDN(struct dcesrv_call_state *dce_call,
						     TALLOC_CTX *mem_ctx,
						     struct RfrGetFQDNFromLegacyDN *r)
{
	char		*fqdn;
	const char	*netbiosname = NULL;
	const char	*realm = NULL;

	OC_DEBUG(3, "exchange_ds_rfr: RfrGetFQDNFromLegacyDN (0x1)");

	if (!dcesrv_call_authenticated(dce_call)) {
		OC_DEBUG(1, "No challenge requested by client, cannot authenticate");

	failure:
		r->out.ppszServerFQDN = talloc_array(mem_ctx, const char *, 2);
		r->out.ppszServerFQDN[0] = NULL;
		r->out.result = MAPI_E_LOGON_FAILED;
		return MAPI_E_LOGON_FAILED;
	}
Пример #2
0
/**
   \details exchange_nsp NspiUnbind (0x1) function, Terminates a NSPI
   session with the client

   \param dce_call pointer to the session context
   \param mem_ctx pointer to the memory context
   \param r pointer to the NspiUnbind call structure
 */
static void dcesrv_NspiUnbind(struct dcesrv_call_state *dce_call,
					 TALLOC_CTX *mem_ctx,
					 struct NspiUnbind *r)
{
	struct dcesrv_handle		*h;
	struct exchange_nsp_session	*session;
	bool				ret;

	DEBUG(5, ("exchange_nsp: NspiUnbind (0x1)\n"));

	/* Step 0. Ensure incoming user is authenticated */
	if (!dcesrv_call_authenticated(dce_call)) {
		DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
		DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
	}

	/* Step 1. Retrieve handle and free if emsabp context and session are available */
	h = dcesrv_handle_fetch(dce_call->context, r->in.handle, DCESRV_HANDLE_ANY);
	if (h) {
		session = dcesrv_find_nsp_session(&r->in.handle->uuid);
		if (session) {
			ret = mpm_session_release(session->session);
			if (ret == true) {
				DLIST_REMOVE(nsp_session, session);
				DEBUG(5, ("[%s:%d]: Session found and released\n",
					  __FUNCTION__, __LINE__));
			} else {
				DEBUG(5, ("[%s:%d]: Session found and ref_count decreased\n",
					  __FUNCTION__, __LINE__));
			}
		}
		else {
			DEBUG(5, ("  nsp_session NOT found\n"));
		}
	}

	r->out.handle->uuid = GUID_zero();
	r->out.handle->handle_type = 0;
	r->out.result = (enum MAPISTATUS) 1;

	DCESRV_NSP_RETURN(r, 1, NULL);
}
Пример #3
0
/**
   \details exchange_ds_rfr RfrGetNewDSA (0x0) function

   \param dce_call pointer to the session context
   \param mem_ctx pointer to the memory context
   \param r pointer to the RfrGetNewDSA request data

   \note We incorrectly assume input pUserDN is correct and available,
   but it is OK for now.

   \return MAPI_E_SUCCESS on success
 */
static enum MAPISTATUS dcesrv_RfrGetNewDSA(struct dcesrv_call_state *dce_call,
					   TALLOC_CTX *mem_ctx,
					   struct RfrGetNewDSA *r)
{
	const char		*netbiosname = NULL;
	const char		*realm = NULL;
	char			*fqdn = NULL;

	OC_DEBUG(5, "exchange_ds_rfr: RfrGetNewDSA (0x0)");

	/* Step 0. Ensure incoming user is authenticated */
	if (!dcesrv_call_authenticated(dce_call)) {
		OC_DEBUG(1, "No challenge requested by client, cannot authenticate");

		r->out.ppszUnused = NULL;
		r->out.ppszServer = NULL;
		r->out.result = MAPI_E_LOGON_FAILED;
		return MAPI_E_LOGON_FAILED;
	}

	/* Step 1. We don't have load-balancing support yet, just return Samba FQDN name */
	netbiosname = lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx);
	realm = lpcfg_realm(dce_call->conn->dce_ctx->lp_ctx);
	if (!netbiosname || !realm) {
		r->out.ppszUnused = NULL;
		r->out.ppszServer = NULL;
		r->out.result = MAPI_E_NO_SUPPORT;
		return MAPI_E_NO_SUPPORT;			
	}

	fqdn = talloc_asprintf(mem_ctx, "%s.%s", netbiosname, realm);
	r->out.ppszUnused = NULL;
	r->out.ppszServer = talloc_array(mem_ctx, const char *, 2);
	r->out.ppszServer[0] = strlower_talloc(mem_ctx, fqdn);
	r->out.ppszServer[1] = NULL;
	r->out.result = MAPI_E_SUCCESS;

	return MAPI_E_SUCCESS;
}
Пример #4
0
/**
   \details exchange_nsp NspiQueryRows (0x3) function

   \param dce_call pointer to the session context
   \param mem_ctx pointer to the memory context
   \param r pointer to the NspiQueryRows request data

   \return MAPI_E_SUCCESS on success
 */
static void dcesrv_NspiQueryRows(struct dcesrv_call_state *dce_call,
				 TALLOC_CTX *mem_ctx,
				 struct NspiQueryRows *r)
{
	enum MAPISTATUS			retval = MAPI_E_SUCCESS;
	struct emsabp_context		*emsabp_ctx = NULL;
	struct SPropTagArray		*pPropTags;
	struct PropertyRowSet_r		*pRows;
	uint32_t			count = 0;
	uint32_t			i, j;

	DEBUG(3, ("exchange_nsp: NspiQueryRows (0x3)\n"));

	/* Step 0. Ensure incoming user is authenticated */
	if (!dcesrv_call_authenticated(dce_call)) {
		DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
		DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
	}

	emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
	if (!emsabp_ctx) {
		DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
	}

	/* Step 1. Sanity Checks (MS-NSPI Server Processing Rules) */
	if (r->in.pStat->ContainerID && r->in.lpETable == NULL && (emsabp_tdb_lookup_MId(emsabp_ctx->tdb_ctx, r->in.pStat->ContainerID) == false)) {
		retval = MAPI_E_INVALID_BOOKMARK;
		goto failure;
	}

	if (r->in.pPropTags == NULL) {
		pPropTags = set_SPropTagArray(mem_ctx, 0x7,
					      PR_EMS_AB_CONTAINERID,
					      PR_OBJECT_TYPE,
					      PR_DISPLAY_TYPE,
					      PR_DISPLAY_NAME,
					      PR_OFFICE_TELEPHONE_NUMBER,
					      PR_COMPANY_NAME,
					      PR_OFFICE_LOCATION);
	} else {
		pPropTags = r->in.pPropTags;
	}

	/* Allocate RowSet to be filled in */
	pRows = talloc_zero(mem_ctx, struct PropertyRowSet_r);

	/* Step 2. Fill ppRows  */
	if (r->in.lpETable == NULL) {
		/* Step 2.1 Fill ppRows for supplied Container ID */
		struct ldb_result	*ldb_res;

		retval = emsabp_ab_container_enum(mem_ctx, emsabp_ctx,
						  r->in.pStat->ContainerID, &ldb_res);
		if (retval != MAPI_E_SUCCESS)  {
			goto failure;
		}

		if (ldb_res->count < r->in.pStat->NumPos) {
			/* Bad position */
			retval = MAPI_E_INVALID_PARAMETER;
			goto failure;
		}

		count = ldb_res->count - r->in.pStat->NumPos;

		if (r->in.Count < count) {
			count = r->in.Count;
		}
		if (count) {
			pRows->cRows = count;
			pRows->aRow = talloc_array(mem_ctx, struct PropertyRow_r, count);
		}

		/* fetch required attributes for every entry found */
		for (i = 0; i < count; i++) {
			retval = emsabp_fetch_attrs_from_msg(mem_ctx, emsabp_ctx, pRows->aRow + i,
							     ldb_res->msgs[i+r->in.pStat->NumPos], 0, r->in.dwFlags, pPropTags);
			if (retval != MAPI_E_SUCCESS) {
				goto failure;
			}
		}
		r->in.pStat->NumPos = r->in.pStat->Delta + pRows->cRows;
		r->in.pStat->CurrentRec = MID_END_OF_TABLE;
		r->in.pStat->TotalRecs = pRows->cRows;
		r->in.pStat->Delta = 0;
	} else {
Пример #5
0
/**
   \details exchange_nsp NspiUpdateStat (0x2) function

   \param dce_call pointer to the session context
   \param mem_ctx pointer to the memory context
   \param r pointer to the NspiUpdateStat request data

   \return MAPI_E_SUCCESS on success
*/
static void dcesrv_NspiUpdateStat(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct NspiUpdateStat *r)
{
	enum MAPISTATUS			retval = MAPI_E_SUCCESS;
        enum MAPISTATUS                 ret;
	struct emsabp_context		*emsabp_ctx = NULL;
	uint32_t			row, row_max;
	TALLOC_CTX			*local_mem_ctx;
	struct PropertyTagArray_r	*mids;

	DEBUG(3, ("exchange_nsp: NspiUpdateStat (0x2)"));

	/* Step 0. Ensure incoming user is authenticated */
	if (!dcesrv_call_authenticated(dce_call)) {
		DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
		DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, NULL);
	}

	emsabp_ctx = dcesrv_find_emsabp_context(&r->in.handle->uuid);
	if (!emsabp_ctx) {
		DCESRV_NSP_RETURN(r, MAPI_E_CALL_FAILED, NULL);
	}

	local_mem_ctx = talloc_zero(NULL, TALLOC_CTX);

	/* Step 1. Sanity Checks (MS-NSPI Server Processing Rules) */
	if (r->in.pStat->ContainerID && (emsabp_tdb_lookup_MId(emsabp_ctx->tdb_ctx, r->in.pStat->ContainerID) == false)) {
		retval = MAPI_E_INVALID_BOOKMARK;
		goto end;
	}

	mids = talloc_zero(local_mem_ctx, struct PropertyTagArray_r);
        if (!mids) {
                DCESRV_NSP_RETURN(r, MAPI_E_NOT_ENOUGH_MEMORY, NULL);
        }

        ret = emsabp_search(local_mem_ctx, emsabp_ctx, mids, NULL, r->in.pStat, 0);
	if (ret != MAPI_E_SUCCESS) {
		row_max = 0;
                if (ret == MAPI_E_CALL_FAILED) {
                        retval = ret;
                        goto end;
                }
	}
	else {
		row_max = mids->cValues;
	}

	if (r->in.pStat->CurrentRec == MID_CURRENT) {
		/* Fractional positioning (3.1.1.4.2) */
		row = r->in.pStat->NumPos * row_max / r->in.pStat->TotalRecs;
		if (row > row_max) {
			row = row_max;
		}
	}
	else {
		if (r->in.pStat->CurrentRec == MID_BEGINNING_OF_TABLE) {
			row = 0;
		}
		else if (r->in.pStat->CurrentRec == MID_END_OF_TABLE) {
			row = row_max;
		}
		else {
			retval = MAPI_E_NOT_FOUND;
			row = 0;
			while (row < row_max) {
				if ((uint32_t) mids->aulPropTag[row] == (uint32_t) r->in.pStat->CurrentRec) {
					retval = MAPI_E_SUCCESS;
					break;
				}
				else {
					row++;
				}
			}
			if (retval == MAPI_E_NOT_FOUND) {
				goto end;
			}
		}
	}

	if (-r->in.pStat->Delta > row) {
		row = 0;
		r->in.pStat->CurrentRec = mids->aulPropTag[row];
	}
	else if (r->in.pStat->Delta + row >= row_max) {
		row = row_max;
		r->in.pStat->CurrentRec = MID_END_OF_TABLE;
	}
	else {
		row += r->in.pStat->Delta;
		r->in.pStat->CurrentRec = mids->aulPropTag[row];
	}

	r->in.pStat->Delta = 0;
	r->in.pStat->NumPos = row;
	r->in.pStat->TotalRecs = row_max;

end:
	r->out.pStat = r->in.pStat;

	DCESRV_NSP_RETURN(r, retval, local_mem_ctx);
}
Пример #6
0
/**
   \details exchange_nsp NspiBind (0x0) function, Initiates a NSPI
   session with the client.

   This function checks if the user is an Exchange user and input
   parameters like codepage are valid. If it passes the tests, the
   function initializes an emsabp context and returns to the client a
   valid policy_handle and expected reply parameters.

   \param dce_call pointer to the session context
   \param mem_ctx pointer to the memory context
   \param r pointer to the NspiBind call structure

   \return MAPI_E_SUCCESS on success, otherwise a MAPI error
 */
static void dcesrv_NspiBind(struct dcesrv_call_state *dce_call,
				       TALLOC_CTX *mem_ctx,
				       struct NspiBind *r)
{
	struct GUID			*guid = (struct GUID *) NULL;
	struct emsabp_context		*emsabp_ctx;
	struct dcesrv_handle		*handle;
	struct policy_handle		wire_handle;
	struct exchange_nsp_session	*session;

	DEBUG(5, ("exchange_nsp: NspiBind (0x0)\n"));

	/* Step 0. Ensure incoming user is authenticated */
	if (!dcesrv_call_authenticated(dce_call) && (r->in.dwFlags & fAnonymousLogin)) {
		DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));

		wire_handle.handle_type = EXCHANGE_HANDLE_NSP;
		wire_handle.uuid = GUID_zero();
		*r->out.handle = wire_handle;

		r->out.mapiuid = r->in.mapiuid;
		DCESRV_NSP_RETURN(r, MAPI_E_FAILONEPROVIDER, NULL);
	}

	/* Step 1. Initialize the emsabp context */
	emsabp_ctx = emsabp_init(dce_call->conn->dce_ctx->lp_ctx, emsabp_tdb_ctx);
	if (!emsabp_ctx) {
		OC_ABORT(false, ("[exchange_nsp] Unable to initialize emsabp context"));

		wire_handle.handle_type = EXCHANGE_HANDLE_NSP;
		wire_handle.uuid = GUID_zero();
		*r->out.handle = wire_handle;

		r->out.mapiuid = r->in.mapiuid;
		DCESRV_NSP_RETURN(r, MAPI_E_FAILONEPROVIDER, NULL);
	}

	if (lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL, 
			    "exchange_nsp", "debug", false)) {
		emsabp_enable_debug(emsabp_ctx);
	}

	/* Step 2. Check if incoming user belongs to the Exchange organization */
	if ((emsabp_verify_user(dce_call, emsabp_ctx) == false) && (r->in.dwFlags & fAnonymousLogin)) {
		talloc_free(emsabp_ctx);

		wire_handle.handle_type = EXCHANGE_HANDLE_NSP;
		wire_handle.uuid = GUID_zero();
		*r->out.handle = wire_handle;

		r->out.mapiuid = r->in.mapiuid;
		DCESRV_NSP_RETURN(r, MAPI_E_LOGON_FAILED, emsabp_tdb_ctx);
	}

	/* Step 3. Check if valid cpID has been supplied */
	if (emsabp_verify_codepage(emsabp_ctx, r->in.pStat->CodePage) == false) {
		talloc_free(emsabp_ctx);

		wire_handle.handle_type = EXCHANGE_HANDLE_NSP;
		wire_handle.uuid = GUID_zero();
		*r->out.handle = wire_handle;

		r->out.mapiuid = r->in.mapiuid;
		DCESRV_NSP_RETURN(r, MAPI_E_UNKNOWN_CPID, emsabp_tdb_ctx);
	}

	/* Step 4. Retrieve OpenChange server GUID */
	guid = (struct GUID *) samdb_ntds_objectGUID(emsabp_ctx->samdb_ctx);
	if (!guid) {
		DCESRV_NSP_RETURN(r, MAPI_E_FAILONEPROVIDER, emsabp_ctx);
	}

	/* Step 5. Fill NspiBind reply */
	handle = dcesrv_handle_new(dce_call->context, EXCHANGE_HANDLE_NSP);
	if (!handle) {
		DCESRV_NSP_RETURN(r, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
	}

	handle->data = (void *) emsabp_ctx;
	*r->out.handle = handle->wire_handle;
	r->out.mapiuid = guid;

	/* Search for an existing session and increment ref_count, otherwise create it */
	session = dcesrv_find_nsp_session(&handle->wire_handle.uuid);
	if (session) {
		mpm_session_increment_ref_count(session->session);
		DEBUG(5, ("  [unexpected]: existing nsp_session: %p; session: %p (ref++)\n", session, session->session));
	}
	else {
		DEBUG(5, ("%s: Creating new session\n", __func__));

		/* Step 6. Associate this emsabp context to the session */
		session = talloc((TALLOC_CTX *)nsp_session, struct exchange_nsp_session);
		if (!session) {
			DCESRV_NSP_RETURN(r, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
		}

		session->session = mpm_session_init((TALLOC_CTX *)nsp_session, dce_call);
		if (!session->session) {
			DCESRV_NSP_RETURN(r, MAPI_E_NOT_ENOUGH_RESOURCES, emsabp_ctx);
		}

		session->uuid = handle->wire_handle.uuid;

		mpm_session_set_private_data(session->session, (void *) emsabp_ctx);
		mpm_session_set_destructor(session->session, emsabp_destructor);

		DLIST_ADD_END(nsp_session, session, struct exchange_nsp_session *);
	}

	DCESRV_NSP_RETURN(r, MAPI_E_SUCCESS, NULL);
}