dcesrv_samr.c

来自「samba最新软件」· C语言 代码 · 共 2,389 行 · 第 1/5 页

C
2,389
字号
		if (rtype == SID_NAME_UNKNOWN) {			status = STATUS_SOME_UNMAPPED;			continue;		}		r->out.rids.ids[i] = sid->sub_auths[sid->num_auths-1];		r->out.types.ids[i] = rtype;		num_mapped++;	}		if (num_mapped == 0) {		return NT_STATUS_NONE_MAPPED;	}	return status;}/*   samr_LookupRids */static NTSTATUS dcesrv_samr_LookupRids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,		       struct samr_LookupRids *r){	struct dcesrv_handle *h;	struct samr_domain_state *d_state;	int i, total;	NTSTATUS status = NT_STATUS_OK;	struct lsa_String *names;	uint32_t *ids;	ZERO_STRUCT(r->out.names);	ZERO_STRUCT(r->out.types);	DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);	d_state = h->data;	if (r->in.num_rids == 0)		return NT_STATUS_OK;	names = talloc_array(mem_ctx, struct lsa_String, r->in.num_rids);	ids = talloc_array(mem_ctx, uint32_t, r->in.num_rids);	if ((names == NULL) || (ids == NULL))		return NT_STATUS_NO_MEMORY;	total = 0;	for (i=0; i<r->in.num_rids; i++) {		struct ldb_message **res;		int count;		const char * const attrs[] = { 	"sAMAccountType",						"sAMAccountName", NULL };		uint32_t atype;		struct dom_sid *sid;		ids[i] = SID_NAME_UNKNOWN;		sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rids[i]);		if (sid == NULL) {			names[i].string = NULL;			status = STATUS_SOME_UNMAPPED;			continue;		}				count = gendb_search(d_state->sam_ctx, mem_ctx,				     d_state->domain_dn, &res, attrs,				     "(objectSid=%s)", 				     ldap_encode_ndr_dom_sid(mem_ctx, sid));		if (count != 1) {			names[i].string = NULL;			status = STATUS_SOME_UNMAPPED;			continue;		}		names[i].string = samdb_result_string(res[0], "sAMAccountName",						      NULL);		atype = samdb_result_uint(res[0], "sAMAccountType", 0);		if (atype == 0) {			status = STATUS_SOME_UNMAPPED;			continue;		}		ids[i] = samdb_atype_map(atype);				if (ids[i] == SID_NAME_UNKNOWN) {			status = STATUS_SOME_UNMAPPED;			continue;		}	}	r->out.names.names = names;	r->out.names.count = r->in.num_rids;	r->out.types.ids = ids;	r->out.types.count = r->in.num_rids;	return status;}/*   samr_OpenGroup */static NTSTATUS dcesrv_samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,		       struct samr_OpenGroup *r){	struct samr_domain_state *d_state;	struct samr_account_state *a_state;	struct dcesrv_handle *h;	const char *groupname;	struct dom_sid *sid;	struct ldb_message **msgs;	struct dcesrv_handle *g_handle;	const char * const attrs[2] = { "sAMAccountName", NULL };	int ret;	ZERO_STRUCTP(r->out.group_handle);	DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);	d_state = h->data;	/* form the group SID */	sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);	if (!sid) {		return NT_STATUS_NO_MEMORY;	}	/* search for the group record */	ret = gendb_search(d_state->sam_ctx,			   mem_ctx, d_state->domain_dn, &msgs, attrs,			   "(&(objectSid=%s)(objectclass=group)"			   "(grouptype=%d))",			   ldap_encode_ndr_dom_sid(mem_ctx, sid),			   GTYPE_SECURITY_GLOBAL_GROUP);	if (ret == 0) {		return NT_STATUS_NO_SUCH_GROUP;	}	if (ret != 1) {		DEBUG(0,("Found %d records matching sid %s\n", 			 ret, dom_sid_string(mem_ctx, sid)));		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	groupname = samdb_result_string(msgs[0], "sAMAccountName", NULL);	if (groupname == NULL) {		DEBUG(0,("sAMAccountName field missing for sid %s\n", 			 dom_sid_string(mem_ctx, sid)));		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	a_state = talloc(d_state, struct samr_account_state);	if (!a_state) {		return NT_STATUS_NO_MEMORY;	}	a_state->sam_ctx = d_state->sam_ctx;	a_state->access_mask = r->in.access_mask;	a_state->domain_state = talloc_reference(a_state, d_state);	a_state->account_dn = talloc_steal(a_state, msgs[0]->dn);	a_state->account_sid = talloc_steal(a_state, sid);	a_state->account_name = talloc_strdup(a_state, groupname);	if (!a_state->account_name) {		return NT_STATUS_NO_MEMORY;	}	/* create the policy handle */	g_handle = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_GROUP);	if (!g_handle) {		return NT_STATUS_NO_MEMORY;	}	g_handle->data = talloc_steal(g_handle, a_state);	*r->out.group_handle = g_handle->wire_handle;	return NT_STATUS_OK;}/*   samr_QueryGroupInfo */static NTSTATUS dcesrv_samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,		       struct samr_QueryGroupInfo *r){	struct dcesrv_handle *h;	struct samr_account_state *a_state;	struct ldb_message *msg;	struct ldb_result *res;	const char * const attrs[4] = { "sAMAccountName", "description",					"numMembers", NULL };	int ret;	r->out.info = NULL;	DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);	a_state = h->data;		ret = ldb_search_exp_fmt(a_state->sam_ctx, mem_ctx, &res, a_state->account_dn, LDB_SCOPE_SUBTREE, attrs, "objectClass=*");		if (ret == LDB_ERR_NO_SUCH_OBJECT) {		return NT_STATUS_NO_SUCH_GROUP;	} else if (ret != LDB_SUCCESS) {		DEBUG(2, ("Error reading group info: %s\n", ldb_errstring(a_state->sam_ctx)));		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	if (res->count != 1) {		DEBUG(2, ("Error finding group info, got %d entries\n", res->count));				return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	msg = res->msgs[0];	/* allocate the info structure */	r->out.info = talloc(mem_ctx, union samr_GroupInfo);	if (r->out.info == NULL) {		return NT_STATUS_NO_MEMORY;	}	ZERO_STRUCTP(r->out.info);	/* Fill in the level */	switch (r->in.level) {	case GROUPINFOALL:		QUERY_STRING(msg, all.name,        "sAMAccountName");		r->out.info->all.attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; /* Do like w2k3 */		QUERY_UINT  (msg, all.num_members,      "numMembers")		QUERY_STRING(msg, all.description, "description");		break;	case GROUPINFONAME:		QUERY_STRING(msg, name,            "sAMAccountName");		break;	case GROUPINFOATTRIBUTES:		r->out.info->attributes.attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; /* Do like w2k3 */		break;	case GROUPINFODESCRIPTION:		QUERY_STRING(msg, description, "description");		break;	case GROUPINFOALL2:		QUERY_STRING(msg, all2.name,        "sAMAccountName");		r->out.info->all.attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; /* Do like w2k3 */		QUERY_UINT  (msg, all2.num_members,      "numMembers")		QUERY_STRING(msg, all2.description, "description");		break;	default:		r->out.info = NULL;		return NT_STATUS_INVALID_INFO_CLASS;	}		return NT_STATUS_OK;}/*   samr_SetGroupInfo */static NTSTATUS dcesrv_samr_SetGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,				  struct samr_SetGroupInfo *r){	struct dcesrv_handle *h;	struct samr_account_state *g_state;	struct ldb_message *msg;	struct ldb_context *sam_ctx;	int ret;	DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);	g_state = h->data;	sam_ctx = g_state->sam_ctx;	msg = ldb_msg_new(mem_ctx);	if (msg == NULL) {		return NT_STATUS_NO_MEMORY;	}		msg->dn = ldb_dn_copy(mem_ctx, g_state->account_dn);	if (!msg->dn) {		return NT_STATUS_NO_MEMORY;	}	switch (r->in.level) {	case GROUPINFODESCRIPTION:		SET_STRING(msg, description,         "description");		break;	case GROUPINFONAME:		/* On W2k3 this does not change the name, it changes the		 * sAMAccountName attribute */		SET_STRING(msg, name,                "sAMAccountName");		break;	case GROUPINFOATTRIBUTES:		/* This does not do anything obviously visible in W2k3 LDAP */		return NT_STATUS_OK;	default:		return NT_STATUS_INVALID_INFO_CLASS;	}	/* modify the samdb record */	ret = ldb_modify(g_state->sam_ctx, msg);	if (ret != 0) {		/* we really need samdb.c to return NTSTATUS */		return NT_STATUS_UNSUCCESSFUL;	}	return NT_STATUS_OK;}/*   samr_AddGroupMember */static NTSTATUS dcesrv_samr_AddGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,		       struct samr_AddGroupMember *r){	struct dcesrv_handle *h;	struct samr_account_state *a_state;	struct samr_domain_state *d_state;	struct ldb_message *mod;	struct dom_sid *membersid;	const char *memberdn;	struct ldb_result *res;	const char * const attrs[] = { NULL };	int ret;	DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);	a_state = h->data;	d_state = a_state->domain_state;	membersid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);	if (membersid == NULL)		return NT_STATUS_NO_MEMORY;	/* In native mode, AD can also nest domain groups. Not sure yet	 * whether this is also available via RPC. */	ret = ldb_search_exp_fmt(d_state->sam_ctx, mem_ctx, &res,				 d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs,				 "(&(objectSid=%s)(objectclass=user))",				 ldap_encode_ndr_dom_sid(mem_ctx, membersid));	if (ret != 0) {		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	if (res->count == 0) {		return NT_STATUS_NO_SUCH_USER;	}			if (res->count > 1) {		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	memberdn = ldb_dn_alloc_linearized(mem_ctx, res->msgs[0]->dn);	if (memberdn == NULL)		return NT_STATUS_NO_MEMORY;	mod = ldb_msg_new(mem_ctx);	if (mod == NULL) {		return NT_STATUS_NO_MEMORY;	}	mod->dn = talloc_reference(mem_ctx, a_state->account_dn);	if (samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member",				 memberdn) != 0)		return NT_STATUS_UNSUCCESSFUL;	ret = ldb_modify(a_state->sam_ctx, mod);	switch (ret) {	case LDB_SUCCESS:		return NT_STATUS_OK;	case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:		return NT_STATUS_MEMBER_IN_GROUP;	case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:		return NT_STATUS_ACCESS_DENIED;	default:		return NT_STATUS_UNSUCCESSFUL;	}}/*   samr_DeleteDomainGroup */static NTSTATUS dcesrv_samr_DeleteDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,		       struct samr_DeleteDomainGroup *r){	struct dcesrv_handle *h;	struct samr_account_state *a_state;	int ret;        *r->out.group_handle = *r->in.group_handle;	DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);	a_state = h->data;	ret = ldb_delete(a_state->sam_ctx, a_state->account_dn);	if (ret != 0) {		return NT_STATUS_UNSUCCESSFUL;	}	ZERO_STRUCTP(r->out.group_handle);	return NT_STATUS_OK;}/*   samr_DeleteGroupMember */static NTSTATUS dcesrv_samr_DeleteGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,		       struct samr_DeleteGroupMember *r){	struct dcesrv_handle *h;	struct samr_account_state *a_state;	struct samr_domain_state *d_state;	struct ldb_message *mod;	struct dom_sid *membersid;	const char *memberdn;	struct ldb_result *res;	const char * const attrs[] = { NULL };	int ret;	DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);	a_state = h->data;	d_state = a_state->domain_state;	membersid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);	if (membersid == NULL)		return NT_STATUS_NO_MEMORY;	/* In native mode, AD can also nest domain groups. Not sure yet	 * whether this is also available via RPC. */	ret = ldb_search_exp_fmt(d_state->sam_ctx, mem_ctx, &res,				 d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs,				 "(&(objectSid=%s)(objectclass=user))",				 ldap_encode_ndr_dom_sid(mem_ctx, membersid));	if (ret != 0) {		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	if (res->count == 0) {		return NT_STATUS_NO_SUCH_USER;	}			if (res->count > 1) {		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	memberdn = ldb_dn_alloc_linearized(mem_ctx, res->msgs[0]->dn);	if (memberdn == NULL)		return NT_STATUS_NO_MEMORY;	mod = ldb_msg_new(mem_ctx);	if (mod == NULL) {		return NT_STATUS_NO_MEMORY;	}	mod->dn = talloc_reference(mem_ctx, a_state->account_dn);	if (samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, "member",				 memberdn) != 0) {		return NT_STATUS_NO_MEMORY;	}	ret = ldb_modify(a_state->sam_ctx, mod);	switch (ret) {	case LDB_SUCCESS:		return NT_STATUS_OK;	case LDB_ERR_NO_SUCH_AT

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?