/* lsa_LookupNames4 Identical to LookupNames3, but doesn't take a policy handle */ NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct lsa_LookupNames4 *r) { enum dcerpc_transport_t transport = dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description); struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info; struct lsa_policy_state *policy_state; struct lsa_LookupNames3 q; NTSTATUS status; if (transport != NCACN_IP_TCP) { DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); } /* * We don't have policy handles on this call. So this must be restricted * to crypto connections only. */ if (auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL || auth_info->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) { DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); } status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &policy_state); if (!NT_STATUS_IS_OK(status)) { return status; } ZERO_STRUCT(q); q.in.handle = NULL; q.in.num_names = r->in.num_names; q.in.names = r->in.names; q.in.level = r->in.level; q.in.sids = r->in.sids; q.in.count = r->in.count; q.in.lookup_options = r->in.lookup_options; q.in.client_revision = r->in.client_revision; q.out.count = r->out.count; q.out.sids = r->out.sids; q.out.domains = r->out.domains; status = dcesrv_lsa_LookupNames_common(dce_call, mem_ctx, policy_state, &q); talloc_free(policy_state); r->out.count = q.out.count; r->out.sids = q.out.sids; r->out.domains = q.out.domains; return status; }
/* lsa_OpenPolicy2 */ NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct lsa_OpenPolicy2 *r) { enum dcerpc_transport_t transport = dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description); NTSTATUS status; struct lsa_policy_state *state; struct dcesrv_handle *handle; if (transport != NCACN_NP && transport != NCALRPC) { DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED); } ZERO_STRUCTP(r->out.handle); if (r->in.attr != NULL && r->in.attr->root_dir != NULL) { /* MS-LSAD 3.1.4.4.1 */ return NT_STATUS_INVALID_PARAMETER; } status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state); if (!NT_STATUS_IS_OK(status)) { return status; } handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_POLICY); if (!handle) { return NT_STATUS_NO_MEMORY; } handle->data = talloc_steal(handle, state); /* need to check the access mask against - need ACLs - fails WSPP test */ state->access_mask = r->in.access_mask; state->handle = handle; *r->out.handle = handle->wire_handle; /* note that we have completely ignored the attr element of the OpenPolicy. As far as I can tell, this is what w2k3 does */ return NT_STATUS_OK; }
/* lsa_OpenPolicy2 */ NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct lsa_OpenPolicy2 *r) { NTSTATUS status; struct lsa_policy_state *state; struct dcesrv_handle *handle; ZERO_STRUCTP(r->out.handle); if (r->in.attr != NULL && r->in.attr->root_dir != NULL) { /* MS-LSAD 3.1.4.4.1 */ return NT_STATUS_INVALID_PARAMETER; } status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state); if (!NT_STATUS_IS_OK(status)) { return status; } handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_POLICY); if (!handle) { return NT_STATUS_NO_MEMORY; } handle->data = talloc_steal(handle, state); /* need to check the access mask against - need ACLs - fails WSPP test */ state->access_mask = r->in.access_mask; state->handle = handle; *r->out.handle = handle->wire_handle; /* note that we have completely ignored the attr element of the OpenPolicy. As far as I can tell, this is what w2k3 does */ return NT_STATUS_OK; }
/* lsa_LookupSids2 */ NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct lsa_LookupSids2 *r) { struct lsa_policy_state *state; struct lsa_RefDomainList *domains = NULL; int i; NTSTATUS status = NT_STATUS_OK; if (r->in.level < LSA_LOOKUP_NAMES_ALL || r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) { return NT_STATUS_INVALID_PARAMETER; } *r->out.domains = NULL; /* NOTE: the WSPP test suite tries SIDs with invalid revision numbers, and expects NT_STATUS_INVALID_PARAMETER back - we just treat it as an unknown SID. We could add a SID validator here. (tridge) MS-DTYP 2.4.2 */ status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state); if (!NT_STATUS_IS_OK(status)) { return status; } domains = talloc_zero(r->out.domains, struct lsa_RefDomainList); if (domains == NULL) { return NT_STATUS_NO_MEMORY; } *r->out.domains = domains; r->out.names = talloc_zero(mem_ctx, struct lsa_TransNameArray2); if (r->out.names == NULL) { return NT_STATUS_NO_MEMORY; } *r->out.count = 0; r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2, r->in.sids->num_sids); if (r->out.names->names == NULL) { return NT_STATUS_NO_MEMORY; } for (i=0; i<r->in.sids->num_sids; i++) { struct dom_sid *sid = r->in.sids->sids[i].sid; char *sid_str = dom_sid_string(mem_ctx, sid); const char *name, *authority_name; enum lsa_SidType rtype; uint32_t sid_index; NTSTATUS status2; r->out.names->count++; r->out.names->names[i].sid_type = SID_NAME_UNKNOWN; r->out.names->names[i].name.string = sid_str; r->out.names->names[i].sid_index = 0xFFFFFFFF; r->out.names->names[i].unknown = 0; if (sid_str == NULL) { r->out.names->names[i].name.string = "(SIDERROR)"; status = STATUS_SOME_UNMAPPED; continue; } status2 = dcesrv_lsa_lookup_sid(state, mem_ctx, sid, sid_str, &authority_name, &name, &rtype); if (!NT_STATUS_IS_OK(status2)) { status = STATUS_SOME_UNMAPPED; continue; } /* set up the authority table */ status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, authority_name, sid, domains, &sid_index); if (!NT_STATUS_IS_OK(status2)) { continue; } r->out.names->names[i].sid_type = rtype; r->out.names->names[i].name.string = name; r->out.names->names[i].sid_index = sid_index; r->out.names->names[i].unknown = 0; (*r->out.count)++; } if (*r->out.count == 0) { return NT_STATUS_NONE_MAPPED; } if (*r->out.count != r->in.sids->num_sids) { return STATUS_SOME_UNMAPPED; } return NT_STATUS_OK; }