dcesrv_samr.c

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

C
2,389
字号
	case 1:		SET_UINT  (msg, info1.min_password_length,     "minPwdLength");		SET_UINT  (msg, info1.password_history_length, "pwdHistoryLength");		SET_UINT  (msg, info1.password_properties,     "pwdProperties");		SET_INT64  (msg, info1.max_password_age,       "maxPwdAge");		SET_INT64  (msg, info1.min_password_age,       "minPwdAge");		break;	case 3:		SET_UINT64  (msg, info3.force_logoff_time,      "forceLogoff");		break;	case 4:		SET_STRING(msg, info4.comment,          "comment");		break;	case 6:	case 7:	case 9:		/* No op, we don't know where to set these */		return NT_STATUS_OK;	case 12:				SET_INT64  (msg, info12.lockout_duration,      "lockoutDuration");		SET_INT64  (msg, info12.lockout_window,        "lockOutObservationWindow");		SET_INT64  (msg, info12.lockout_threshold,     "lockoutThreshold");		break;	default:		/* many info classes are not valid for SetDomainInfo */		return NT_STATUS_INVALID_INFO_CLASS;	}	/* modify the samdb record */	ret = ldb_modify(sam_ctx, msg);	if (ret != 0) {		DEBUG(1,("Failed to modify record %s: %s\n",			 ldb_dn_get_linearized(d_state->domain_dn),			 ldb_errstring(sam_ctx)));		/* we really need samdb.c to return NTSTATUS */		return NT_STATUS_UNSUCCESSFUL;	}	return NT_STATUS_OK;}/*   samr_CreateDomainGroup */static NTSTATUS dcesrv_samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,				       struct samr_CreateDomainGroup *r){	struct samr_domain_state *d_state;	struct samr_account_state *a_state;	struct dcesrv_handle *h;	const char *name;	struct ldb_message *msg;	struct dom_sid *sid;	const char *groupname;	struct dcesrv_handle *g_handle;	int ret;	ZERO_STRUCTP(r->out.group_handle);	*r->out.rid = 0;	DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);	d_state = h->data;	if (d_state->builtin) {		DEBUG(5, ("Cannot create a domain group in the BUILTIN domain"));		return NT_STATUS_ACCESS_DENIED;	}	groupname = r->in.name->string;	if (groupname == NULL) {		return NT_STATUS_INVALID_PARAMETER;	}	/* check if the group already exists */	name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL, 				   "sAMAccountName",				   "(&(sAMAccountName=%s)(objectclass=group))",				   ldb_binary_encode_string(mem_ctx, groupname));	if (name != NULL) {		return NT_STATUS_GROUP_EXISTS;	}	msg = ldb_msg_new(mem_ctx);	if (msg == NULL) {		return NT_STATUS_NO_MEMORY;	}	/* add core elements to the ldb_message for the user */	msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn);	ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", groupname);	if (!msg->dn) {		return NT_STATUS_NO_MEMORY;	}	samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", groupname);	samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", "group");			     	/* create the group */	ret = ldb_add(d_state->sam_ctx, msg);	switch (ret) {	case  LDB_SUCCESS:		break;	case  LDB_ERR_ENTRY_ALREADY_EXISTS:		DEBUG(0,("Failed to create group record %s: %s\n",			 ldb_dn_get_linearized(msg->dn),			 ldb_errstring(d_state->sam_ctx)));		return NT_STATUS_GROUP_EXISTS;	case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:		DEBUG(0,("Failed to create group record %s: %s\n",			 ldb_dn_get_linearized(msg->dn),			 ldb_errstring(d_state->sam_ctx)));		return NT_STATUS_ACCESS_DENIED;	default:		DEBUG(0,("Failed to create group record %s: %s\n",			 ldb_dn_get_linearized(msg->dn),			 ldb_errstring(d_state->sam_ctx)));		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, msg->dn);	/* retrieve the sid for the group just created */	sid = samdb_search_dom_sid(d_state->sam_ctx, a_state,				   msg->dn, "objectSid", NULL);	if (sid == NULL) {		return NT_STATUS_UNSUCCESSFUL;	}	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;	*r->out.rid = sid->sub_auths[sid->num_auths-1];	return NT_STATUS_OK;}/*  comparison function for sorting SamEntry array*/static int compare_SamEntry(struct samr_SamEntry *e1, struct samr_SamEntry *e2){	return e1->idx - e2->idx;}/*   samr_EnumDomainGroups */static NTSTATUS dcesrv_samr_EnumDomainGroups(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,				      struct samr_EnumDomainGroups *r){	struct dcesrv_handle *h;	struct samr_domain_state *d_state;	struct ldb_message **res;	int ldb_cnt, count, i, first;	struct samr_SamEntry *entries;	const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };	*r->out.resume_handle = 0;	r->out.sam = NULL;	r->out.num_entries = 0;	DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);	d_state = h->data;	/* search for all domain groups in this domain. This could possibly be	   cached and resumed based on resume_key */	ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx,				      d_state->domain_dn, &res, attrs,				      d_state->domain_sid,				      "(&(grouptype=%d)(objectclass=group))",				      GTYPE_SECURITY_GLOBAL_GROUP);	if (ldb_cnt == -1) {		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	/* convert to SamEntry format */	entries = talloc_array(mem_ctx, struct samr_SamEntry, ldb_cnt);	if (!entries) {		return NT_STATUS_NO_MEMORY;	}	count = 0;	for (i=0;i<ldb_cnt;i++) {		struct dom_sid *group_sid;		group_sid = samdb_result_dom_sid(mem_ctx, res[i],						 "objectSid");		if (group_sid == NULL)			continue;		entries[count].idx =			group_sid->sub_auths[group_sid->num_auths-1];		entries[count].name.string =			samdb_result_string(res[i], "sAMAccountName", "");		count += 1;	}	/* sort the results by rid */	qsort(entries, count, sizeof(struct samr_SamEntry), 	      (comparison_fn_t)compare_SamEntry);	/* find the first entry to return */	for (first=0;	     first<count && entries[first].idx <= *r->in.resume_handle;	     first++) ;	/* return the rest, limit by max_size. Note that we 	   use the w2k3 element size value of 54 */	r->out.num_entries = count - first;	r->out.num_entries = MIN(r->out.num_entries, 				 1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER));	r->out.sam = talloc(mem_ctx, struct samr_SamArray);	if (!r->out.sam) {		return NT_STATUS_NO_MEMORY;	}	r->out.sam->entries = entries+first;	r->out.sam->count = r->out.num_entries;	if (r->out.num_entries < count - first) {		*r->out.resume_handle = entries[first+r->out.num_entries-1].idx;		return STATUS_MORE_ENTRIES;	}	return NT_STATUS_OK;}/*   samr_CreateUser2   This call uses transactions to ensure we don't get a new conflicting  user while we are processing this, and to ensure the user either  completly exists, or does not.*/static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,				 struct samr_CreateUser2 *r){	struct samr_domain_state *d_state;	struct samr_account_state *a_state;	struct dcesrv_handle *h;	const char *name;	struct ldb_message *msg;	struct dom_sid *sid;	const char *account_name;	struct dcesrv_handle *u_handle;	int ret;	const char *container, *obj_class=NULL;	char *cn_name;	int cn_name_len;	const char *attrs[] = {		"objectSid", 		"userAccountControl",		NULL	};	uint32_t user_account_control;	struct ldb_message **msgs;	ZERO_STRUCTP(r->out.user_handle);	*r->out.access_granted = 0;	*r->out.rid = 0;	DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);	d_state = h->data;	if (d_state->builtin) {		DEBUG(5, ("Cannot create a user in the BUILTIN domain"));		return NT_STATUS_ACCESS_DENIED;	}	account_name = r->in.account_name->string;	if (account_name == NULL) {		return NT_STATUS_INVALID_PARAMETER;	}	ret = ldb_transaction_start(d_state->sam_ctx);	if (ret != 0) {		DEBUG(0,("Failed to start a transaction for user creation: %s\n",			 ldb_errstring(d_state->sam_ctx)));		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	/* check if the user already exists */	name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL, 				   "sAMAccountName", 				   "(&(sAMAccountName=%s)(objectclass=user))", 				   ldb_binary_encode_string(mem_ctx, account_name));	if (name != NULL) {		ldb_transaction_cancel(d_state->sam_ctx);		return NT_STATUS_USER_EXISTS;	}	msg = ldb_msg_new(mem_ctx);	if (msg == NULL) {		ldb_transaction_cancel(d_state->sam_ctx);		return NT_STATUS_NO_MEMORY;	}	cn_name   = talloc_strdup(mem_ctx, account_name);	if (!cn_name) {		ldb_transaction_cancel(d_state->sam_ctx);		return NT_STATUS_NO_MEMORY;	}	cn_name_len = strlen(cn_name);	/* This must be one of these values *only* */	if (r->in.acct_flags == ACB_NORMAL) {		container = "CN=Users";		obj_class = "user";	} else if (r->in.acct_flags == ACB_WSTRUST) {		if (cn_name[cn_name_len - 1] != '$') {			return NT_STATUS_FOOBAR;		}		cn_name[cn_name_len - 1] = '\0';		container = "CN=Computers";		obj_class = "computer";		samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, "primaryGroupID", DOMAIN_RID_DOMAIN_MEMBERS);	} else if (r->in.acct_flags == ACB_SVRTRUST) {		if (cn_name[cn_name_len - 1] != '$') {			return NT_STATUS_FOOBAR;				}		cn_name[cn_name_len - 1] = '\0';		container = "OU=Domain Controllers";		obj_class = "computer";		samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, "primaryGroupID", DOMAIN_RID_DCS);	} else if (r->in.acct_flags == ACB_DOMTRUST) {		container = "CN=Users";		obj_class = "user";	} else {		ldb_transaction_cancel(d_state->sam_ctx);		return NT_STATUS_INVALID_PARAMETER;	}	/* add core elements to the ldb_message for the user */	msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn);	if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s,%s", cn_name, container)) {		ldb_transaction_cancel(d_state->sam_ctx);		return NT_STATUS_FOOBAR;	}	samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", account_name);	samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", obj_class);		/* Start a transaction, so we can query and do a subsequent atomic modify */		/* create the user */	ret = ldb_add(d_state->sam_ctx, msg);	switch (ret) {	case LDB_SUCCESS:		break;	case LDB_ERR_ENTRY_ALREADY_EXISTS:		ldb_transaction_cancel(d_state->sam_ctx);		DEBUG(0,("Failed to create user record %s: %s\n",			 ldb_dn_get_linearized(msg->dn),			 ldb_errstring(d_state->sam_ctx)));		return NT_STATUS_USER_EXISTS;	case LDB_ERR_UNWILLING_TO_PERFORM:	case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:		ldb_transaction_cancel(d_state->sam_ctx);		DEBUG(0,("Failed to create user record %s: %s\n",			 ldb_dn_get_linearized(msg->dn),			 ldb_errstring(d_state->sam_ctx)));		return NT_STATUS_ACCESS_DENIED;	default:		ldb_transaction_cancel(d_state->sam_ctx);		DEBUG(0,("Failed to create user record %s: %s\n",			 ldb_dn_get_linearized(msg->dn),			 ldb_errstring(d_state->sam_ctx)));		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	a_state = talloc(d_state, struct samr_account_state);	if (!a_state) {		ldb_transaction_cancel(d_state->sam_ctx);		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, msg->dn);	/* retrieve the sid and account control bits for the user just created */	ret = gendb_search_dn(d_state->sam_ctx, a_state,			      msg->dn, &msgs, attrs);	if (ret != 1) {		ldb_transaction_cancel(d_state->sam_ctx);		DEBUG(0,("Apparently we failed to create an account record, as %s now doesn't exist\n",			 ldb_dn_get_linearized(msg->dn)));		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	sid = samdb_result_dom_sid(mem_ctx, msgs[0], "objectSid");	if (sid == NULL) {		ldb_transaction_cancel(d_state->sam_ctx);		DEBUG(0,("Apparently we failed to get the objectSid of the just created account record %s\n",			 ldb_dn_get_linearized(msg->dn)));		return NT_STATUS_INTERNAL_DB_CORRUPTION;	}	/* Change the account control to be the correct account type.	 * The default is for a workstation account */	user_account_control = samdb_result_uint(msgs[0], "userAccountControl", 0);	user_account_control = (user_account_control & 				~(UF_NORMAL_ACCOUNT |				  UF_INTERDOMAIN_TRUST_ACCOUNT | 				  UF_WORKSTATION_TRUST_ACCOUNT | 				  UF_SERVER_TRUST_ACCOUNT));	user_account_control |= samdb_acb2uf(r->in.acct_flags);	talloc_free(msg);	msg = ldb_msg_new(mem_ctx);	if (msg == NULL) {		ldb_transaction_cancel(d_state->sam_ctx);		return NT_STATUS_NO_MEMORY;	}	msg->dn = ldb_dn_copy(msg, a_state->account_dn);	if (samdb_msg_add_uint(a_state->sam_ctx, mem_ctx, msg, 			       "userAccountControl", 			       user_account_control) != 0) { 		ldb_transaction_cancel(d_state->sam_ctx);		return NT_STATUS_NO_MEMORY; 	}	/* modify the samdb record */	ret = samdb_replace(a_state->sam_ctx, mem_ctx, msg);	if (ret != 0) {		DEBUG(0,("Failed to modify account record %s to set userAccountControl: %s\n",			 ldb_dn_get_linearized(msg->dn),			 ldb_errstring(d_state->sam_ctx)));		ldb_transaction_cancel(d_state->sam_ctx);		/* we really need samdb.c to return NTSTATUS */		return NT_STATUS_UNSUCCESSFUL;	}	ret = ldb_transaction_commit(d_state->sam_ctx);	if (ret != 0) {		DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",			 ldb_dn_get_linearized(msg->dn),

⌨️ 快捷键说明

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