示例#1
0
static void ridalloc_get_ridset_values(struct ldb_message *msg, struct ridalloc_ridset_values *v)
{
	v->alloc_pool = ldb_msg_find_attr_as_uint64(msg, "rIDAllocationPool", UINT64_MAX);
	v->prev_pool = ldb_msg_find_attr_as_uint64(msg, "rIDPreviousAllocationPool", UINT64_MAX);
	v->next_rid = ldb_msg_find_attr_as_uint(msg, "rIDNextRID", UINT32_MAX);
	v->used_pool = ldb_msg_find_attr_as_uint(msg, "rIDUsedPool", UINT32_MAX);
}
示例#2
0
/* port functions */
static WERROR sptr_EnumPorts(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
			     struct spoolss_EnumPorts *r)
{
	struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context);
	struct ldb_message **msgs;
	int count;
	int i;
	union spoolss_PortInfo *info;

	count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL,
			       "(&(objectclass=port))");

	if (count == 0) return WERR_OK;
	if (count < 0) return WERR_GENERAL_FAILURE;

	info = talloc_array(mem_ctx, union spoolss_PortInfo, count);
	W_ERROR_HAVE_NO_MEMORY(info);

	switch (r->in.level) {
	case 1:
		for (i = 0; i < count; i++) {
			info[i].info1.port_name		= ldb_msg_find_attr_as_string(msgs[i], "port-name", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info1.port_name);
		}
		break;
	case 2:
		for (i=0; i < count; i++) {
			info[i].info2.port_name		= ldb_msg_find_attr_as_string(msgs[i], "port-name", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info2.port_name);

			info[i].info2.monitor_name	= ldb_msg_find_attr_as_string(msgs[i], "monitor-name", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info2.monitor_name);

			info[i].info2.description	= ldb_msg_find_attr_as_string(msgs[i], "description", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info2.description);

			info[i].info2.port_type		= ldb_msg_find_attr_as_uint(msgs[i], "port-type", SPOOLSS_PORT_TYPE_WRITE);
			info[i].info2.reserved		= ldb_msg_find_attr_as_uint(msgs[i], "reserved", 0);
		}
		break;
	default:
		return WERR_UNKNOWN_LEVEL;
	}

	*r->out.info	= info;
	*r->out.count	= count;
	return WERR_OK;
}
/**
   \details return the next unmapped property ID

   \param ldb_ctx pointer to the namedprops ldb context

   \return 0 on error, the next mapped id otherwise
 */
_PUBLIC_ uint16_t mapistore_namedprops_next_unused_id(struct ldb_context *ldb_ctx)
{
	uint16_t		highest_id = 0, current_id;
	TALLOC_CTX		*mem_ctx;
	struct ldb_result	*res = NULL;
	const char * const	attrs[] = { "mappedId", NULL };
	int			ret;
	unsigned int		i;

	mem_ctx = talloc_named(NULL, 0, "mapistore_namedprops_get_mapped_propID");

	ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
			 LDB_SCOPE_SUBTREE, attrs, "(cn=*)");
	MAPISTORE_RETVAL_IF(ret != LDB_SUCCESS, 0, mem_ctx);

	for (i = 0; i < res->count; i++) {
		current_id = ldb_msg_find_attr_as_uint(res->msgs[i], "mappedId", 0);
		if (current_id > 0 && highest_id < current_id) {
			highest_id = current_id;
		}
	}

	talloc_free(mem_ctx);

	DEBUG(5, ("next_mapped_id: %d\n", (highest_id + 1)));

	return (highest_id + 1);
}
示例#4
0
static NTSTATUS unbecomeDC_ldap_computer_object(struct libnet_UnbecomeDC_state *s)
{
	int ret;
	struct ldb_result *r;
	struct ldb_dn *basedn;
	static const char *attrs[] = {
		"distinguishedName",
		"userAccountControl",
		NULL
	};

	basedn = ldb_dn_new(s, s->ldap.ldb, s->domain.dn_str);
	NT_STATUS_HAVE_NO_MEMORY(basedn);

	ret = ldb_search(s->ldap.ldb, s, &r, basedn, LDB_SCOPE_SUBTREE, attrs,
			 "(&(|(objectClass=user)(objectClass=computer))(sAMAccountName=%s$))",
			 s->dest_dsa.netbios_name);
	talloc_free(basedn);
	if (ret != LDB_SUCCESS) {
		return NT_STATUS_LDAP(ret);
	} else if (r->count != 1) {
		talloc_free(r);
		return NT_STATUS_INVALID_NETWORK_RESPONSE;
	}

	s->dest_dsa.computer_dn_str	= ldb_msg_find_attr_as_string(r->msgs[0], "distinguishedName", NULL);
	if (!s->dest_dsa.computer_dn_str) return NT_STATUS_INVALID_NETWORK_RESPONSE;
	talloc_steal(s, s->dest_dsa.computer_dn_str);

	s->dest_dsa.user_account_control = ldb_msg_find_attr_as_uint(r->msgs[0], "userAccountControl", 0);

	talloc_free(r);
	return NT_STATUS_OK;
}
示例#5
0
static void generate_sambaPrimaryGroupSID(struct ldb_module *module, const char *local_attr, const struct ldb_message *local, struct ldb_message *remote_mp, struct ldb_message *remote_fb)
{
	const struct ldb_val *sidval;
	char *sidstring;
	struct dom_sid *sid;
	NTSTATUS status;

	/* We need the domain, so we get it from the objectSid that we hope is here... */
	sidval = ldb_msg_find_ldb_val(local, "objectSid");

	if (!sidval)
		return; /* Sorry, no SID today.. */

	sid = talloc(remote_mp, struct dom_sid);
	if (sid == NULL) {
		return;
	}
	status = ndr_pull_struct_blob(sidval, sid, sid, (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(sid);
		return;
	}

	if (!ldb_msg_find_ldb_val(local, "primaryGroupID"))
		return; /* Sorry, no SID today.. */

	sid->num_auths--;

	sidstring = dom_sid_string(remote_mp, sid);
	talloc_free(sid);
	ldb_msg_add_fmt(remote_mp, "sambaPrimaryGroupSID", "%s-%d", sidstring, ldb_msg_find_attr_as_uint(local, "primaryGroupID", 0));
	talloc_free(sidstring);
}
示例#6
0
/*
  construct msDS-User-Account-Control-Computed attr
*/
static int construct_msds_user_account_control_computed(struct ldb_module *module,
							struct ldb_message *msg, enum ldb_scope scope,
							struct ldb_request *parent)
{
	uint32_t userAccountControl;
	uint32_t msDS_User_Account_Control_Computed = 0;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	NTTIME now;
	struct ldb_dn *nc_root;
	int ret;

	ret = dsdb_find_nc_root(ldb, msg, msg->dn, &nc_root);
	if (ret != 0) {
		ldb_asprintf_errstring(ldb,
				       "Failed to find NC root of DN: %s: %s",
				       ldb_dn_get_linearized(msg->dn),
				       ldb_errstring(ldb_module_get_ctx(module)));
		return ret;
	}
	if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) != 0) {
		/* Only calculate this on our default NC */
		return 0;
	}
	/* Test account expire time */
	unix_to_nt_time(&now, time(NULL));

	userAccountControl = ldb_msg_find_attr_as_uint(msg,
						       "userAccountControl",
						       0);
	if (!(userAccountControl & _UF_TRUST_ACCOUNTS)) {

		int64_t lockoutTime = ldb_msg_find_attr_as_int64(msg, "lockoutTime", 0);
		if (lockoutTime != 0) {
			int64_t lockoutDuration = samdb_search_int64(ldb,
								     msg, 0, nc_root,
								     "lockoutDuration", NULL);
			if (lockoutDuration >= 0) {
				msDS_User_Account_Control_Computed |= UF_LOCKOUT;
			} else if (lockoutTime - lockoutDuration >= now) {
				msDS_User_Account_Control_Computed |= UF_LOCKOUT;
			}
		}
	}

	if (!(userAccountControl & _UF_NO_EXPIRY_ACCOUNTS)) {
		NTTIME must_change_time
			= get_msds_user_password_expiry_time_computed(module,
								      msg, nc_root);
		/* check for expired password */
		if (must_change_time < now) {
			msDS_User_Account_Control_Computed |= UF_PASSWORD_EXPIRED;
		}
	}

	return samdb_msg_add_int64(ldb,
				   msg->elements, msg,
				   "msDS-User-Account-Control-Computed",
				   msDS_User_Account_Control_Computed);
}
示例#7
0
bool ads_pull_uint32(ADS_STRUCT *ads, LDAPMessage *res, const char *field, uint32_t *ret)
{
	if (ldb_msg_find_element(res->msgs[0], field) == NULL) {
		return false;
	}
	*ret = ldb_msg_find_attr_as_uint(res->msgs[0], field, 0);
	return true;
}
示例#8
0
bool samba_princ_needs_pac(struct hdb_entry_ex *princ)
{

	struct samba_kdc_entry *p = talloc_get_type(princ->ctx, struct samba_kdc_entry);
	uint32_t userAccountControl;


	/* The service account may be set not to want the PAC */
	userAccountControl = ldb_msg_find_attr_as_uint(p->msg, "userAccountControl", 0);
	if (userAccountControl & UF_NO_AUTH_DATA_REQUIRED) {
		return false;
	}

	return true;
}
示例#9
0
/* Printer Form functions */
static WERROR sptr_GetPrinterForm(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
				  struct spoolss_GetForm *r)
{
	struct ldb_context *sptr_db = talloc_get_type(printer->ntptr->private_data, struct ldb_context);
	struct ldb_message **msgs;
	struct ldb_dn *base_dn;
	int count;
	union spoolss_FormInfo *info;

	/* TODO: do checks access here
	 * if (!(printer->access_mask & desired_access)) {
	 *	return WERR_FOOBAR;
	 * }
	 */

	base_dn = ldb_dn_new_fmt(mem_ctx, sptr_db, "CN=Forms,CN=%s,CN=Printers", printer->object_name);
	W_ERROR_HAVE_NO_MEMORY(base_dn);

	count = sptr_db_search(sptr_db, mem_ctx, base_dn, &msgs, NULL,
			       "(&(form-name=%s)(objectClass=form))",
			       r->in.form_name);

	if (count == 0) return WERR_FOOBAR;
	if (count > 1) return WERR_FOOBAR;
	if (count < 0) return WERR_GENERAL_FAILURE;

	info = talloc(mem_ctx, union spoolss_FormInfo);
	W_ERROR_HAVE_NO_MEMORY(info);

	switch (r->in.level) {
	case 1:
		info->info1.flags	= ldb_msg_find_attr_as_uint(msgs[0], "flags", SPOOLSS_FORM_BUILTIN);

		info->info1.form_name	= ldb_msg_find_attr_as_string(msgs[0], "form-name", NULL);
		W_ERROR_HAVE_NO_MEMORY(info->info1.form_name);

		info->info1.size.width	= ldb_msg_find_attr_as_uint(msgs[0], "size-width", 0);
		info->info1.size.height	= ldb_msg_find_attr_as_uint(msgs[0], "size-height", 0);

		info->info1.area.left	= ldb_msg_find_attr_as_uint(msgs[0], "area-left", 0);
		info->info1.area.top	= ldb_msg_find_attr_as_uint(msgs[0], "area-top", 0);
		info->info1.area.right	= ldb_msg_find_attr_as_uint(msgs[0], "area-right", 0);
		info->info1.area.bottom	= ldb_msg_find_attr_as_uint(msgs[0], "area-bottom", 0);
		break;
	default:
		return WERR_UNKNOWN_LEVEL;
	}

	r->out.info	= info;
	return WERR_OK;
}
示例#10
0
/* PrintServer Form functions */
static WERROR sptr_EnumPrintServerForms(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
					struct spoolss_EnumForms *r)
{
	struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context);
	struct ldb_message **msgs;
	int count;
	int i;
	union spoolss_FormInfo *info;

	count = sptr_db_search(sptr_db, mem_ctx,
				ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"),
				&msgs, NULL, "(&(objectClass=form))");

	if (count == 0) return WERR_OK;
	if (count < 0) return WERR_GENERAL_FAILURE;

	info = talloc_array(mem_ctx, union spoolss_FormInfo, count);
	W_ERROR_HAVE_NO_MEMORY(info);

	switch (r->in.level) {
	case 1:
		for (i=0; i < count; i++) {
			info[i].info1.flags		= ldb_msg_find_attr_as_uint(msgs[i], "flags", SPOOLSS_FORM_BUILTIN);

			info[i].info1.form_name		= ldb_msg_find_attr_as_string(msgs[i], "form-name", NULL);
			W_ERROR_HAVE_NO_MEMORY(info[i].info1.form_name);

			info[i].info1.size.width	= ldb_msg_find_attr_as_uint(msgs[i], "size-width", 0);
			info[i].info1.size.height	= ldb_msg_find_attr_as_uint(msgs[i], "size-height", 0);

			info[i].info1.area.left		= ldb_msg_find_attr_as_uint(msgs[i], "area-left", 0);
			info[i].info1.area.top		= ldb_msg_find_attr_as_uint(msgs[i], "area-top", 0);
			info[i].info1.area.right	= ldb_msg_find_attr_as_uint(msgs[i], "area-right", 0);
			info[i].info1.area.bottom	= ldb_msg_find_attr_as_uint(msgs[i], "area-bottom", 0);
		}
		break;
	default:
		return WERR_UNKNOWN_LEVEL;
	}

	*r->out.info	= info;
	*r->out.count	= count;
	return WERR_OK;
}
示例#11
0
static WERROR sptr_DeletePrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
					 struct spoolss_DeleteForm *r)
{
	struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context);
	struct ldb_message **msgs;
	const char * const attrs[] = { "flags", NULL};
	int count, ret;
	enum spoolss_FormFlags flags;

	/* TODO: do checks access here
	 * if (!(server->access_mask & desired_access)) {
	 *	return WERR_FOOBAR;
	 * }
	 */

	if (!r->in.form_name) {
		return WERR_FOOBAR;
	}

	count = sptr_db_search(sptr_db, mem_ctx,
			       ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"),
			       &msgs, attrs, "(&(form-name=%s)(objectclass=form))",
			       r->in.form_name);

	if (count == 0) return WERR_FOOBAR;
	if (count > 1) return WERR_FOOBAR;
	if (count < 0) return WERR_GENERAL_FAILURE;

	flags = ldb_msg_find_attr_as_uint(msgs[0], "flags", SPOOLSS_FORM_BUILTIN);
	if (flags != SPOOLSS_FORM_USER) {
		return WERR_FOOBAR;
	}

	ret = ldb_delete(sptr_db, msgs[0]->dn);
	if (ret != 0) {
		return WERR_FOOBAR;
	}

	return WERR_OK;
}
/**
   \details return the mapped property ID matching the nameid
   structure passed in parameter.

   \param ldb_ctx pointer to the namedprops ldb context
   \param nameid the MAPINAMEID structure to lookup
   \param propID pointer to the property ID the function returns

   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
 */
_PUBLIC_ enum mapistore_error mapistore_namedprops_get_mapped_id(struct ldb_context *ldb_ctx, struct MAPINAMEID nameid, uint16_t *propID)
{
	TALLOC_CTX		*mem_ctx;
	struct ldb_result	*res = NULL;
	const char * const	attrs[] = { "*", NULL };
	int			ret;
	char			*filter = NULL;
	char			*guid;

	/* Sanity checks */
	MAPISTORE_RETVAL_IF(!ldb_ctx, MAPISTORE_ERROR, NULL);
	MAPISTORE_RETVAL_IF(!propID, MAPISTORE_ERROR, NULL);

	*propID = 0;
	mem_ctx = talloc_named(NULL, 0, "mapistore_namedprops_get_mapped_propID");
	guid = GUID_string(mem_ctx, (const struct GUID *)&nameid.lpguid);

	switch (nameid.ulKind) {
	case MNID_ID:
		filter = talloc_asprintf(mem_ctx, "(&(objectClass=MNID_ID)(oleguid=%s)(cn=0x%.4x))",
					 guid, nameid.kind.lid);
		break;
	case MNID_STRING:
		filter = talloc_asprintf(mem_ctx, "(&(objectClass=MNID_STRING)(oleguid=%s)(cn=%s))",
					 guid, nameid.kind.lpwstr.Name);
		break;
	}
	talloc_free(guid);

	ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
			 LDB_SCOPE_SUBTREE, attrs, "%s", filter);
	MAPISTORE_RETVAL_IF((ret != LDB_SUCCESS || !res->count), MAPISTORE_ERROR, mem_ctx);

	*propID = ldb_msg_find_attr_as_uint(res->msgs[0], "mappedId", 0);
	MAPISTORE_RETVAL_IF(!*propID, MAPISTORE_ERROR, mem_ctx);

	talloc_free(mem_ctx);

	return MAPISTORE_SUCCESS;
}
示例#13
0
static WERROR sptr_SetPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
				      struct spoolss_SetForm *r)
{
	struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context);
	struct ldb_message *msg,**msgs;
	const char * const attrs[] = { "flags", NULL};
	int count, ret;
	enum spoolss_FormFlags flags;

	/* TODO: do checks access here
	 * if (!(server->access_mask & desired_access)) {
	 *	return WERR_FOOBAR;
	 * }
	 */

	switch (r->in.level) {
	case 1:
		if (!r->in.info.info1) {
			return WERR_FOOBAR;
		}

		count = sptr_db_search(sptr_db, mem_ctx,
				       ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"),
				       &msgs, attrs, "(&(form-name=%s)(objectClass=form))",
				       r->in.info.info1->form_name);

		if (count == 0) return WERR_FOOBAR;
		if (count > 1) return WERR_FOOBAR;
		if (count < 0) return WERR_GENERAL_FAILURE;

		flags = ldb_msg_find_attr_as_uint(msgs[0], "flags", SPOOLSS_FORM_BUILTIN);
		if (flags != SPOOLSS_FORM_USER) {
			return WERR_FOOBAR;
		}

		msg = ldb_msg_new(mem_ctx);
		W_ERROR_HAVE_NO_MEMORY(msg);

		/* add core elements to the ldb_message for the user */
		msg->dn = msgs[0]->dn;

		SET_UINT(sptr_db, msg, "flags", r->in.info.info1->flags);

		SET_STRING(sptr_db, msg, "form-name", r->in.info.info1->form_name);

		SET_UINT(sptr_db, msg, "size-width", r->in.info.info1->size.width);
		SET_UINT(sptr_db, msg, "size-height", r->in.info.info1->size.height);

		SET_UINT(sptr_db, msg, "area-left", r->in.info.info1->area.left);
		SET_UINT(sptr_db, msg, "area-top", r->in.info.info1->area.top);
		SET_UINT(sptr_db, msg, "area-right", r->in.info.info1->area.right);
		SET_UINT(sptr_db, msg, "area-bottom", r->in.info.info1->area.bottom);
		break;
	default:
		return WERR_UNKNOWN_LEVEL;
	}

	ret = dsdb_replace(sptr_db, msg, 0);
	if (ret != 0) {
		return WERR_FOOBAR;
	}

	return WERR_OK;
}
示例#14
0
/*
  calculate msDS-UserPasswordExpiryTimeComputed
*/
static NTTIME get_msds_user_password_expiry_time_computed(struct ldb_module *module,
						struct ldb_message *msg,
						struct ldb_dn *domain_dn)
{
	int64_t pwdLastSet, maxPwdAge;
	uint32_t userAccountControl;
	NTTIME ret;

	userAccountControl = ldb_msg_find_attr_as_uint(msg,
					"userAccountControl",
					0);
	if (userAccountControl & _UF_NO_EXPIRY_ACCOUNTS) {
		return 0x7FFFFFFFFFFFFFFFULL;
	}

	pwdLastSet = ldb_msg_find_attr_as_int64(msg, "pwdLastSet", 0);
	if (pwdLastSet == 0) {
		return 0;
	}

	if (pwdLastSet <= -1) {
		/*
		 * This can't really happen...
		 */
		return 0x7FFFFFFFFFFFFFFFULL;
	}

	if (pwdLastSet >= 0x7FFFFFFFFFFFFFFFULL) {
		/*
		 * Somethings wrong with the clock...
		 */
		return 0x7FFFFFFFFFFFFFFFULL;
	}

	/*
	 * Note that maxPwdAge is a stored as negative value.
	 *
	 * Possible values are in the range of:
	 *
	 * maxPwdAge: -864000000001
	 * to
	 * maxPwdAge: -9223372036854775808 (-0x8000000000000000ULL)
	 *
	 */
	maxPwdAge = samdb_search_int64(ldb_module_get_ctx(module), msg, 0,
				       domain_dn, "maxPwdAge", NULL);
	if (maxPwdAge >= -864000000000) {
		/*
		 * This is not really possible...
		 */
		return 0x7FFFFFFFFFFFFFFFULL;
	}

	if (maxPwdAge == -0x8000000000000000ULL) {
		return 0x7FFFFFFFFFFFFFFFULL;
	}

	/*
	 * Note we already catched maxPwdAge == -0x8000000000000000ULL
	 * and pwdLastSet >= 0x7FFFFFFFFFFFFFFFULL above.
	 *
	 * Remember maxPwdAge is a negative number,
	 * so it results in the following.
	 *
	 * 0x7FFFFFFFFFFFFFFEULL + 0x7FFFFFFFFFFFFFFFULL
	 * =
	 * 0xFFFFFFFFFFFFFFFFULL
	 */
	ret = pwdLastSet - maxPwdAge;
	if (ret >= 0x7FFFFFFFFFFFFFFFULL) {
		return 0x7FFFFFFFFFFFFFFFULL;
	}

	return ret;
}
示例#15
0
/*
 * complete a domain join, when joining to a AD domain:
 * 1.) connect and bind to the DRSUAPI pipe
 * 2.) do a DsCrackNames() to find the machine account dn
 * 3.) connect to LDAP
 * 4.) do an ldap search to find the "msDS-KeyVersionNumber" of the machine account
 * 5.) set the servicePrincipalName's of the machine account via LDAP, (maybe we should use DsWriteAccountSpn()...)
 * 6.) do a DsCrackNames() to find the domain dn
 * 7.) find out Site specific stuff, look at libnet_JoinSite() for details
 */
static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_JoinDomain *r)
{
	NTSTATUS status;

	TALLOC_CTX *tmp_ctx;

	const char *realm = r->out.realm;

	struct dcerpc_binding *samr_binding = r->out.samr_binding;

	struct dcerpc_pipe *drsuapi_pipe;
	struct dcerpc_binding *drsuapi_binding;
	struct drsuapi_DsBind r_drsuapi_bind;
	struct drsuapi_DsCrackNames r_crack_names;
	struct drsuapi_DsNameString names[1];
	struct policy_handle drsuapi_bind_handle;
	struct GUID drsuapi_bind_guid;

	struct ldb_context *remote_ldb;
	struct ldb_dn *account_dn;
	const char *account_dn_str;
	const char *remote_ldb_url;
	struct ldb_result *res;
	struct ldb_message *msg;

	int ret, rtn;

	unsigned int kvno;
	
	const char * const attrs[] = {
		"msDS-KeyVersionNumber",
		"servicePrincipalName",
		"dNSHostName",
		NULL,
	};

	r->out.error_string = NULL;
	
	/* We need to convert between a samAccountName and domain to a
	 * DN in the directory.  The correct way to do this is with
	 * DRSUAPI CrackNames */

	/* Fiddle with the bindings, so get to DRSUAPI on
	 * NCACN_IP_TCP, sealed */
	tmp_ctx = talloc_named(r, 0, "libnet_JoinADSDomain temp context");  
	if (!tmp_ctx) {
		r->out.error_string = NULL;
		return NT_STATUS_NO_MEMORY;
	}
	                                           
	drsuapi_binding = talloc(tmp_ctx, struct dcerpc_binding);
	if (!drsuapi_binding) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}
	
	*drsuapi_binding = *samr_binding;

	/* DRSUAPI is only available on IP_TCP, and locally on NCALRPC */
	if (drsuapi_binding->transport != NCALRPC) {
		drsuapi_binding->transport = NCACN_IP_TCP;
	}
	drsuapi_binding->endpoint = NULL;
	drsuapi_binding->flags |= DCERPC_SEAL;

	status = dcerpc_pipe_connect_b(tmp_ctx, 
				       &drsuapi_pipe,
				       drsuapi_binding,
				       &dcerpc_table_drsuapi,
				       ctx->cred, 
				       ctx->event_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		r->out.error_string = talloc_asprintf(r,
					"Connection to DRSUAPI pipe of PDC of domain '%s' failed: %s",
					r->in.domain_name,
					nt_errstr(status));
		talloc_free(tmp_ctx);
		return status;
	}

	/* get a DRSUAPI pipe handle */
	GUID_from_string(DRSUAPI_DS_BIND_GUID, &drsuapi_bind_guid);

	r_drsuapi_bind.in.bind_guid = &drsuapi_bind_guid;
	r_drsuapi_bind.in.bind_info = NULL;
	r_drsuapi_bind.out.bind_handle = &drsuapi_bind_handle;

	status = dcerpc_drsuapi_DsBind(drsuapi_pipe, tmp_ctx, &r_drsuapi_bind);
	if (!NT_STATUS_IS_OK(status)) {
		if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
			r->out.error_string
				= talloc_asprintf(r,
						  "dcerpc_drsuapi_DsBind failed - %s", 
						  dcerpc_errstr(tmp_ctx, drsuapi_pipe->last_fault_code));
			talloc_free(tmp_ctx);
			return status;
		} else {
			r->out.error_string
				= talloc_asprintf(r,
						  "dcerpc_drsuapi_DsBind failed - %s", 
						  nt_errstr(status));
			talloc_free(tmp_ctx);
			return status;
		}
	} else if (!W_ERROR_IS_OK(r_drsuapi_bind.out.result)) {
		r->out.error_string
				= talloc_asprintf(r,
						  "DsBind failed - %s", 
						  win_errstr(r_drsuapi_bind.out.result));
			talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* Actually 'crack' the names */
	ZERO_STRUCT(r_crack_names);
	r_crack_names.in.bind_handle		= &drsuapi_bind_handle;
	r_crack_names.in.level			= 1;
	r_crack_names.in.req.req1.unknown1	= 0x000004e4;
	r_crack_names.in.req.req1.unknown2	= 0x00000407;
	r_crack_names.in.req.req1.count		= 1;
	r_crack_names.in.req.req1.names		= names;
	r_crack_names.in.req.req1.format_flags	= DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
	r_crack_names.in.req.req1.format_offered= DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY;
	r_crack_names.in.req.req1.format_desired= DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
	names[0].str = dom_sid_string(tmp_ctx, r->out.account_sid);
	if (!names[0].str) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	status = dcerpc_drsuapi_DsCrackNames(drsuapi_pipe, tmp_ctx, &r_crack_names);
	if (!NT_STATUS_IS_OK(status)) {
		if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
			r->out.error_string
				= talloc_asprintf(r,
						  "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", 
						  names[0].str,
						  dcerpc_errstr(tmp_ctx, drsuapi_pipe->last_fault_code));
			talloc_free(tmp_ctx);
			return status;
		} else {
			r->out.error_string
				= talloc_asprintf(r,
						  "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", 
						  names[0].str,
						  nt_errstr(status));
			talloc_free(tmp_ctx);
			return status;
		}
	} else if (!W_ERROR_IS_OK(r_crack_names.out.result)) {
		r->out.error_string
				= talloc_asprintf(r,
						  "DsCrackNames failed - %s", win_errstr(r_crack_names.out.result));
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	} else if (r_crack_names.out.level != 1 
		   || !r_crack_names.out.ctr.ctr1 
		   || r_crack_names.out.ctr.ctr1->count != 1) {
		r->out.error_string = talloc_asprintf(r, "DsCrackNames failed");
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	} else if (r_crack_names.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
		r->out.error_string = talloc_asprintf(r, "DsCrackNames failed: %d", r_crack_names.out.ctr.ctr1->array[0].status);
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	} else if (r_crack_names.out.ctr.ctr1->array[0].result_name == NULL) {
		r->out.error_string = talloc_asprintf(r, "DsCrackNames failed: no result name");
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* Store the DN of our machine account. */
	account_dn_str = r_crack_names.out.ctr.ctr1->array[0].result_name;

	account_dn = ldb_dn_new(tmp_ctx, remote_ldb, account_dn_str);
	if (! ldb_dn_validate(account_dn)) {
		r->out.error_string = talloc_asprintf(r, "Invalid account dn: %s",
						      account_dn_str);
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* Now we know the user's DN, open with LDAP, read and modify a few things */

	remote_ldb_url = talloc_asprintf(tmp_ctx, "ldap://%s", 
					 drsuapi_binding->target_hostname);
	if (!remote_ldb_url) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	remote_ldb = ldb_wrap_connect(tmp_ctx, remote_ldb_url, 
				      NULL, ctx->cred, 0, NULL);
	if (!remote_ldb) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* search for the user's record */
	ret = ldb_search(remote_ldb, account_dn, LDB_SCOPE_BASE, 
			 NULL, attrs, &res);
	if (ret != LDB_SUCCESS) {
		r->out.error_string = talloc_asprintf(r, "ldb_search for %s failed - %s",
						      account_dn_str, ldb_errstring(remote_ldb));
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	talloc_steal(tmp_ctx, res);

	if (res->count != 1) {
		r->out.error_string = talloc_asprintf(r, "ldb_search for %s failed - found %d entries",
						      account_dn_str, res->count);
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* If we have a kvno recorded in AD, we need it locally as well */
	kvno = ldb_msg_find_attr_as_uint(res->msgs[0], "msDS-KeyVersionNumber", 0);

	/* Prepare a new message, for the modify */
	msg = ldb_msg_new(tmp_ctx);
	if (!msg) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}
	msg->dn = res->msgs[0]->dn;

	{
		int i;
		const char *service_principal_name[6];
		const char *dns_host_name = strlower_talloc(tmp_ctx, 
							    talloc_asprintf(tmp_ctx, 
									    "%s.%s", 
									    r->in.netbios_name, 
									    realm));

		if (!dns_host_name) {
			r->out.error_string = NULL;
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		service_principal_name[0] = talloc_asprintf(tmp_ctx, "host/%s", dns_host_name);
		service_principal_name[1] = talloc_asprintf(tmp_ctx, "host/%s", strlower_talloc(tmp_ctx, r->in.netbios_name));
		service_principal_name[2] = talloc_asprintf(tmp_ctx, "host/%s/%s", dns_host_name, realm);
		service_principal_name[3] = talloc_asprintf(tmp_ctx, "host/%s/%s", strlower_talloc(tmp_ctx, r->in.netbios_name), realm);
		service_principal_name[4] = talloc_asprintf(tmp_ctx, "host/%s/%s", dns_host_name, r->out.domain_name);
		service_principal_name[5] = talloc_asprintf(tmp_ctx, "host/%s/%s", strlower_talloc(tmp_ctx, r->in.netbios_name), r->out.domain_name);
		
		for (i=0; i < ARRAY_SIZE(service_principal_name); i++) {
			if (!service_principal_name[i]) {
				r->out.error_string = NULL;
				talloc_free(tmp_ctx);
				return NT_STATUS_NO_MEMORY;
			}
			rtn = samdb_msg_add_string(remote_ldb, tmp_ctx, msg, "servicePrincipalName", service_principal_name[i]);
			if (rtn == -1) {
				r->out.error_string = NULL;
				talloc_free(tmp_ctx);
				return NT_STATUS_NO_MEMORY;
			}
		}

		rtn = samdb_msg_add_string(remote_ldb, tmp_ctx, msg, "dNSHostName", dns_host_name);
		if (rtn == -1) {
			r->out.error_string = NULL;
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		rtn = samdb_replace(remote_ldb, tmp_ctx, msg);
		if (rtn != 0) {
			r->out.error_string
				= talloc_asprintf(r, 
						  "Failed to replace entries on %s", 
						  ldb_dn_get_linearized(msg->dn));
			talloc_free(tmp_ctx);
			return NT_STATUS_INTERNAL_DB_CORRUPTION;
		}
	}
				
	/* DsCrackNames to find out the DN of the domain. */
	r_crack_names.in.req.req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
	r_crack_names.in.req.req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
	names[0].str = talloc_asprintf(tmp_ctx, "%s\\", r->out.domain_name);
	if (!names[0].str) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	status = dcerpc_drsuapi_DsCrackNames(drsuapi_pipe, tmp_ctx, &r_crack_names);
	if (!NT_STATUS_IS_OK(status)) {
		if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
			r->out.error_string
				= talloc_asprintf(r,
						  "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", 
						  r->in.domain_name, 
						  dcerpc_errstr(tmp_ctx, drsuapi_pipe->last_fault_code));
			talloc_free(tmp_ctx);
			return status;
		} else {
			r->out.error_string
				= talloc_asprintf(r,
						  "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", 
						  r->in.domain_name, 
						  nt_errstr(status));
			talloc_free(tmp_ctx);
			return status;
		}
	} else if (!W_ERROR_IS_OK(r_crack_names.out.result)) {
		r->out.error_string
			= talloc_asprintf(r,
					  "DsCrackNames failed - %s", win_errstr(r_crack_names.out.result));
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	} else if (r_crack_names.out.level != 1 
		   || !r_crack_names.out.ctr.ctr1 
		   || r_crack_names.out.ctr.ctr1->count != 1
		   || !r_crack_names.out.ctr.ctr1->array[0].result_name		  
		   || r_crack_names.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
		r->out.error_string = talloc_asprintf(r, "DsCrackNames failed");
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* Store the account DN. */
	r->out.account_dn_str = account_dn_str;
	talloc_steal(r, account_dn_str);

	/* Store the domain DN. */
	r->out.domain_dn_str = r_crack_names.out.ctr.ctr1->array[0].result_name;
	talloc_steal(r, r_crack_names.out.ctr.ctr1->array[0].result_name);

	r->out.kvno = kvno;

	if (r->in.acct_type == ACB_SVRTRUST) {
		status = libnet_JoinSite(remote_ldb, r);
	}
	talloc_free(tmp_ctx);

	return status;
}
/*
  lookup a SID for 1 name
*/
static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx, 
				       struct loadparm_context *lp_ctx,
				       struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
				       const char *name, const char **authority_name, 
				       struct dom_sid **sid, enum lsa_SidType *rtype,
				       uint32_t *rid)
{
	int ret, i;
	uint32_t atype;
	struct ldb_message **res;
	const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
	const char *p;
	const char *domain;
	const char *username;
	struct ldb_dn *domain_dn;
	struct dom_sid *domain_sid;
	NTSTATUS status;

	p = strchr_m(name, '\\');
	if (p != NULL) {
		domain = talloc_strndup(mem_ctx, name, p-name);
		if (!domain) {
			return NT_STATUS_NO_MEMORY;
		}
		username = p + 1;
	} else if (strchr_m(name, '@')) {
		status = crack_name_to_nt4_name(mem_ctx, ev_ctx, lp_ctx, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, name, &domain, &username);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(3, ("Failed to crack name %s into an NT4 name: %s\n", name, nt_errstr(status)));
			return status;
		}
	} else {
		domain = NULL;
		username = name;
	}
	
	if (!domain) {
		/* Look up table of well known names */
		status = lookup_well_known_names(mem_ctx, NULL, username, authority_name, sid, rtype);
		if (NT_STATUS_IS_OK(status)) {
			dom_sid_split_rid(NULL, *sid, NULL, rid);
			return NT_STATUS_OK;
		}

		if (username == NULL) {
			*authority_name = NAME_BUILTIN;
			*sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
			if (*sid == NULL) {
				return NT_STATUS_NO_MEMORY;
			}
			*rtype = SID_NAME_DOMAIN;
			*rid = 0xFFFFFFFF;
			return NT_STATUS_OK;
		}

		if (strcasecmp_m(username, NAME_NT_AUTHORITY) == 0) { 
			*authority_name = NAME_NT_AUTHORITY;
			*sid =  dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
			if (*sid == NULL) {
				return NT_STATUS_NO_MEMORY;
			}
			*rtype = SID_NAME_DOMAIN;
			dom_sid_split_rid(NULL, *sid, NULL, rid);
			return NT_STATUS_OK;
		}
		if (strcasecmp_m(username, NAME_BUILTIN) == 0) { 
			*authority_name = NAME_BUILTIN;
			*sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
			if (*sid == NULL) {
				return NT_STATUS_NO_MEMORY;
			}
			*rtype = SID_NAME_DOMAIN;
			*rid = 0xFFFFFFFF;
			return NT_STATUS_OK;
		}
		if (strcasecmp_m(username, state->domain_dns) == 0) { 
			*authority_name = talloc_strdup(mem_ctx,
							state->domain_name);
			if (*authority_name == NULL) {
				return NT_STATUS_NO_MEMORY;
			}
			*sid =  dom_sid_dup(mem_ctx, state->domain_sid);
			if (*sid == NULL) {
				return NT_STATUS_NO_MEMORY;
			}
			*rtype = SID_NAME_DOMAIN;
			*rid = 0xFFFFFFFF;
			return NT_STATUS_OK;
		}
		if (strcasecmp_m(username, state->domain_name) == 0) { 
			*authority_name = talloc_strdup(mem_ctx,
							state->domain_name);
			if (*authority_name == NULL) {
				return NT_STATUS_NO_MEMORY;
			}
			*sid =  dom_sid_dup(mem_ctx, state->domain_sid);
			if (*sid == NULL) {
				return NT_STATUS_NO_MEMORY;
			}
			*rtype = SID_NAME_DOMAIN;
			*rid = 0xFFFFFFFF;
			return NT_STATUS_OK;
		}

		/* Perhaps this is a well known user? */
		name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_NT_AUTHORITY, username);
		if (!name) {
			return NT_STATUS_NO_MEMORY;
		}
		status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
		if (NT_STATUS_IS_OK(status)) {
			return status;
		}

		/* Perhaps this is a BUILTIN user? */
		name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_BUILTIN, username);
		if (!name) {
			return NT_STATUS_NO_MEMORY;
		}
		status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
		if (NT_STATUS_IS_OK(status)) {
			return status;
		}

		/* OK, I give up - perhaps we need to assume the user is in our domain? */
		name = talloc_asprintf(mem_ctx, "%s\\%s", state->domain_name, username);
		if (!name) {
			return NT_STATUS_NO_MEMORY;
		}
		status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
		if (NT_STATUS_IS_OK(status)) {
			return status;
		}

		return STATUS_SOME_UNMAPPED;
	} else if (strcasecmp_m(domain, NAME_NT_AUTHORITY) == 0) {
		if (!*username) {
			*authority_name = NAME_NT_AUTHORITY;
			*sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
			if (*sid == NULL) {
				return NT_STATUS_NO_MEMORY;
			}
			*rtype = SID_NAME_DOMAIN;
			dom_sid_split_rid(NULL, *sid, NULL, rid);
			return NT_STATUS_OK;
		}

		/* Look up table of well known names */
		status = lookup_well_known_names(mem_ctx, domain, username, authority_name, 
						 sid, rtype);
		if (NT_STATUS_IS_OK(status)) {
			dom_sid_split_rid(NULL, *sid, NULL, rid);
		}
		return status;
	} else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) {
		*authority_name = NAME_BUILTIN;
		domain_dn = state->builtin_dn;
	} else if (strcasecmp_m(domain, state->domain_dns) == 0) { 
		*authority_name = talloc_strdup(mem_ctx,
						state->domain_name);
		if (*authority_name == NULL) {
			return NT_STATUS_NO_MEMORY;
		}
		domain_dn = state->domain_dn;
	} else if (strcasecmp_m(domain, state->domain_name) == 0) { 
		*authority_name = talloc_strdup(mem_ctx,
						state->domain_name);
		if (*authority_name == NULL) {
			return NT_STATUS_NO_MEMORY;
		}
		domain_dn = state->domain_dn;
	} else {
		/* Not local, need to ask winbind in future */
		return STATUS_SOME_UNMAPPED;
	}

	ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs);
	if (ret != 1) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}
	domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
	if (domain_sid == NULL) {
		return NT_STATUS_INVALID_SID;
	}

	if (!*username) {
		*sid = domain_sid;
		*rtype = SID_NAME_DOMAIN;
		*rid = 0xFFFFFFFF;
		return NT_STATUS_OK;
	}
	
	ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs, 
			   "(&(sAMAccountName=%s)(objectSid=*))", 
			   ldb_binary_encode_string(mem_ctx, username));
	if (ret < 0) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	for (i=0; i < ret; i++) {
		*sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
		if (*sid == NULL) {
			return NT_STATUS_INVALID_SID;
		}

		/* Check that this is in the domain */
		if (!dom_sid_in_domain(domain_sid, *sid)) {
			continue;
		}

		atype = ldb_msg_find_attr_as_uint(res[i], "sAMAccountType", 0);
			
		*rtype = ds_atype_map(atype);
		if (*rtype == SID_NAME_UNKNOWN) {
			return STATUS_SOME_UNMAPPED;
		}

		dom_sid_split_rid(NULL, *sid, NULL, rid);
		return NT_STATUS_OK;
	}

	/* need to check for an allocated sid */

	return NT_STATUS_INVALID_SID;
}
/*
  lookup a name for 1 SID
*/
static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
				      struct dom_sid *sid, const char *sid_str,
				      const char **authority_name, 
				      const char **name, enum lsa_SidType *rtype)
{
	NTSTATUS status;
	int ret;
	uint32_t atype;
	struct ldb_message **res;
	struct ldb_dn *domain_dn;
	const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "cn", NULL};

	status = lookup_well_known_sids(mem_ctx, sid_str, authority_name, name, rtype);
	if (NT_STATUS_IS_OK(status)) {
		return status;
	}

	if (dom_sid_equal(state->domain_sid, sid)) {
		*authority_name = talloc_strdup(mem_ctx, state->domain_name);
		if (*authority_name == NULL) {
			return NT_STATUS_NO_MEMORY;
		}
		*name = NULL;
		*rtype = SID_NAME_DOMAIN;
		return NT_STATUS_OK;
	}

	if (dom_sid_in_domain(state->domain_sid, sid)) {
		*authority_name = talloc_strdup(mem_ctx, state->domain_name);
		if (*authority_name == NULL) {
			return NT_STATUS_NO_MEMORY;
		}
		domain_dn = state->domain_dn;
	} else if (dom_sid_in_domain(state->builtin_sid, sid)) {
		*authority_name = NAME_BUILTIN;
		domain_dn = state->builtin_dn;
	} else {
		/* Not well known, our domain or built in */

		/* In future, we must look at SID histories, and at trusted domains via winbind */

		return NT_STATUS_NOT_FOUND;
	}

	/* need to re-add a check for an allocated sid */

	ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs, 
			   "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
	if ((ret < 0) || (ret > 1)) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}
	if (ret == 0) {
		return NT_STATUS_NOT_FOUND;
	}

	*name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
	if (!*name) {
		*name = ldb_msg_find_attr_as_string(res[0], "cn", NULL);
		if (!*name) {
			*name = talloc_strdup(mem_ctx, sid_str);
			NT_STATUS_HAVE_NO_MEMORY(*name);
		}
	}

	atype = ldb_msg_find_attr_as_uint(res[0], "sAMAccountType", 0);
	*rtype = ds_atype_map(atype);

	return NT_STATUS_OK;
}
示例#18
0
/*
  see if we are on the last pool we have
 */
static int drepl_ridalloc_pool_exhausted(struct ldb_context *ldb,
					 bool *exhausted,
					 uint64_t *_alloc_pool)
{
	struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
	TALLOC_CTX *tmp_ctx = talloc_new(ldb);
	uint64_t alloc_pool;
	uint64_t prev_pool;
	uint32_t prev_pool_lo, prev_pool_hi;
	uint32_t next_rid;
	static const char * const attrs[] = {
		"rIDAllocationPool",
		"rIDPreviousAllocationPool",
		"rIDNextRid",
		NULL
	};
	int ret;
	struct ldb_result *res;

	*exhausted = false;
	*_alloc_pool = UINT64_MAX;

	server_dn = ldb_dn_get_parent(tmp_ctx, samdb_ntds_settings_dn(ldb));
	if (!server_dn) {
		talloc_free(tmp_ctx);
		return ldb_operr(ldb);
	}

	ret = samdb_reference_dn(ldb, tmp_ctx, server_dn, "serverReference", &machine_dn);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,(__location__ ": Failed to find serverReference in %s - %s\n",
			 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = samdb_reference_dn(ldb, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn);
	if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
		*exhausted = true;
		*_alloc_pool = 0;
		talloc_free(tmp_ctx);
		return LDB_SUCCESS;
	}
	if (ret != LDB_SUCCESS) {
		DEBUG(0,(__location__ ": Failed to find rIDSetReferences in %s - %s\n",
			 ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = ldb_search(ldb, tmp_ctx, &res, rid_set_dn, LDB_SCOPE_BASE, attrs, NULL);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,(__location__ ": Failed to load RID Set attrs from %s - %s\n",
			 ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return ret;
	}

	alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0);
	prev_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDPreviousAllocationPool", 0);
	prev_pool_lo = prev_pool & 0xFFFFFFFF;
	prev_pool_hi = prev_pool >> 32;
	next_rid = ldb_msg_find_attr_as_uint(res->msgs[0], "rIDNextRid", 0);

	if (alloc_pool != prev_pool) {
		talloc_free(tmp_ctx);
		return LDB_SUCCESS;
	}

	if (next_rid < (prev_pool_hi + prev_pool_lo)/2) {
		talloc_free(tmp_ctx);
		return LDB_SUCCESS;
	}

	*exhausted = true;
	*_alloc_pool = alloc_pool;
	talloc_free(tmp_ctx);
	return LDB_SUCCESS;
}
示例#19
0
/*
  construct the token groups for SAM objects from a message
*/
static int construct_token_groups(struct ldb_module *module,
				  struct ldb_message *msg, enum ldb_scope scope,
				  struct ldb_request *parent)
{
	struct ldb_context *ldb = ldb_module_get_ctx(module);;
	TALLOC_CTX *tmp_ctx = talloc_new(msg);
	unsigned int i;
	int ret;
	const char *filter;

	NTSTATUS status;

	struct dom_sid *primary_group_sid;
	const char *primary_group_string;
	const char *primary_group_dn;
	DATA_BLOB primary_group_blob;

	struct dom_sid *account_sid;
	const char *account_sid_string;
	const char *account_sid_dn;
	DATA_BLOB account_sid_blob;
	struct dom_sid *groupSIDs = NULL;
	unsigned int num_groupSIDs = 0;

	struct dom_sid *domain_sid;

	if (scope != LDB_SCOPE_BASE) {
		ldb_set_errstring(ldb, "Cannot provide tokenGroups attribute, this is not a BASE search");
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* If it's not a user, it won't have a primaryGroupID */
	if (ldb_msg_find_element(msg, "primaryGroupID") == NULL) {
		talloc_free(tmp_ctx);
		return LDB_SUCCESS;
	}

	/* Ensure it has an objectSID too */
	account_sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
	if (account_sid == NULL) {
		talloc_free(tmp_ctx);
		return LDB_SUCCESS;
	}

	status = dom_sid_split_rid(tmp_ctx, account_sid, &domain_sid, NULL);
	if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
		talloc_free(tmp_ctx);
		return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
	} else if (!NT_STATUS_IS_OK(status)) {
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	primary_group_sid = dom_sid_add_rid(tmp_ctx,
					    domain_sid,
					    ldb_msg_find_attr_as_uint(msg, "primaryGroupID", ~0));
	if (!primary_group_sid) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	/* only return security groups */
	filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
				 GROUP_TYPE_SECURITY_ENABLED);
	if (!filter) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	primary_group_string = dom_sid_string(tmp_ctx, primary_group_sid);
	if (!primary_group_string) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	primary_group_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", primary_group_string);
	if (!primary_group_dn) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	primary_group_blob = data_blob_string_const(primary_group_dn);

	account_sid_string = dom_sid_string(tmp_ctx, account_sid);
	if (!account_sid_string) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	account_sid_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", account_sid_string);
	if (!account_sid_dn) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	account_sid_blob = data_blob_string_const(account_sid_dn);

	status = dsdb_expand_nested_groups(ldb, &account_sid_blob,
					   true, /* We don't want to add the object's SID itself,
						    it's not returend in this attribute */
					   filter,
					   tmp_ctx, &groupSIDs, &num_groupSIDs);

	if (!NT_STATUS_IS_OK(status)) {
		ldb_asprintf_errstring(ldb, "Failed to construct tokenGroups: expanding groups of SID %s failed: %s",
				       account_sid_string, nt_errstr(status));
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* Expands the primary group - this function takes in
	 * memberOf-like values, so we fake one up with the
	 * <SID=S-...> format of DN and then let it expand
	 * them, as long as they meet the filter - so only
	 * domain groups, not builtin groups
	 */
	status = dsdb_expand_nested_groups(ldb, &primary_group_blob, false, filter,
					   tmp_ctx, &groupSIDs, &num_groupSIDs);
	if (!NT_STATUS_IS_OK(status)) {
		ldb_asprintf_errstring(ldb, "Failed to construct tokenGroups: expanding groups of SID %s failed: %s",
				       account_sid_string, nt_errstr(status));
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	for (i=0; i < num_groupSIDs; i++) {
		ret = samdb_msg_add_dom_sid(ldb, msg, msg, "tokenGroups", &groupSIDs[i]);
		if (ret) {
			talloc_free(tmp_ctx);
			return ret;
		}
	}

	return LDB_SUCCESS;
}
示例#20
0
static void reg_ldb_unpack_value(TALLOC_CTX *mem_ctx,
				 struct ldb_message *msg,
				 const char **name, uint32_t *type,
				 DATA_BLOB *data)
{
	const struct ldb_val *val;
	uint32_t value_type;

	if (name != NULL) {
		*name = talloc_strdup(mem_ctx,
				      ldb_msg_find_attr_as_string(msg, "value",
				      ""));
	}

	value_type = ldb_msg_find_attr_as_uint(msg, "type", 0);
	*type = value_type;

	val = ldb_msg_find_ldb_val(msg, "data");

	switch (value_type)
	{
	case REG_SZ:
	case REG_EXPAND_SZ:
		if (val != NULL) {
			/* The data should be provided as UTF16 string */
			convert_string_talloc(mem_ctx, CH_UTF8, CH_UTF16,
					      val->data, val->length,
					      (void **)&data->data, &data->length);
		} else {
			data->data = NULL;
			data->length = 0;
		}
		break;

	case REG_DWORD:
	case REG_DWORD_BIG_ENDIAN:
		if (val != NULL) {
			/* The data is a plain DWORD */
			uint32_t tmp = strtoul((char *)val->data, NULL, 0);
			data->data = talloc_size(mem_ctx, sizeof(uint32_t));
			if (data->data != NULL) {
				SIVAL(data->data, 0, tmp);
			}
			data->length = sizeof(uint32_t);
		} else {
			data->data = NULL;
			data->length = 0;
		}
		break;

	case REG_QWORD:
		if (val != NULL) {
			/* The data is a plain QWORD */
			uint64_t tmp = strtoull((char *)val->data, NULL, 0);
			data->data = talloc_size(mem_ctx, sizeof(uint64_t));
			if (data->data != NULL) {
				SBVAL(data->data, 0, tmp);
			}
			data->length = sizeof(uint64_t);
		} else {
			data->data = NULL;
			data->length = 0;
		}
		break;

	case REG_BINARY:
	default:
		if (val != NULL) {
			data->data = talloc_memdup(mem_ctx, val->data,
						   val->length);
			data->length = val->length;
		} else {
			data->data = NULL;
			data->length = 0;
		}
		break;
	}
}
示例#21
0
/*
 * complete a domain join, when joining to a AD domain:
 * 1.) connect and bind to the DRSUAPI pipe
 * 2.) do a DsCrackNames() to find the machine account dn
 * 3.) connect to LDAP
 * 4.) do an ldap search to find the "msDS-KeyVersionNumber" of the machine account
 * 5.) set the servicePrincipalName's of the machine account via LDAP, (maybe we should use DsWriteAccountSpn()...)
 * 6.) do a DsCrackNames() to find the domain dn
 * 7.) find out Site specific stuff, look at libnet_JoinSite() for details
 */
static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_JoinDomain *r)
{
	NTSTATUS status;

	TALLOC_CTX *tmp_ctx;

	const char *realm = r->out.realm;

	struct dcerpc_binding *samr_binding = r->out.samr_binding;

	struct dcerpc_pipe *drsuapi_pipe;
	struct dcerpc_binding *drsuapi_binding;
	struct drsuapi_DsBind r_drsuapi_bind;
	struct drsuapi_DsCrackNames r_crack_names;
	struct drsuapi_DsNameString names[1];
	struct policy_handle drsuapi_bind_handle;
	struct GUID drsuapi_bind_guid;

	struct ldb_context *remote_ldb;
	struct ldb_dn *account_dn;
	const char *account_dn_str;
	const char *remote_ldb_url;
	struct ldb_result *res;
	struct ldb_message *msg;

	int ret, rtn;

	const char * const attrs[] = {
		"msDS-KeyVersionNumber",
		"servicePrincipalName",
		"dNSHostName",
		"objectGUID",
		NULL,
	};

	r->out.error_string = NULL;
	
	/* We need to convert between a samAccountName and domain to a
	 * DN in the directory.  The correct way to do this is with
	 * DRSUAPI CrackNames */

	/* Fiddle with the bindings, so get to DRSUAPI on
	 * NCACN_IP_TCP, sealed */
	tmp_ctx = talloc_named(r, 0, "libnet_JoinADSDomain temp context");  
	if (!tmp_ctx) {
		r->out.error_string = NULL;
		return NT_STATUS_NO_MEMORY;
	}
	                                           
	drsuapi_binding = talloc_zero(tmp_ctx, struct dcerpc_binding);
	if (!drsuapi_binding) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}
	
	*drsuapi_binding = *samr_binding;

	/* DRSUAPI is only available on IP_TCP, and locally on NCALRPC */
	if (drsuapi_binding->transport != NCALRPC) {
		drsuapi_binding->transport = NCACN_IP_TCP;
	}
	drsuapi_binding->endpoint = NULL;
	drsuapi_binding->flags |= DCERPC_SEAL;

	status = dcerpc_pipe_connect_b(tmp_ctx, 
				       &drsuapi_pipe,
				       drsuapi_binding,
				       &ndr_table_drsuapi,
				       ctx->cred, 
				       ctx->event_ctx,
				       ctx->lp_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		r->out.error_string = talloc_asprintf(r,
					"Connection to DRSUAPI pipe of PDC of domain '%s' failed: %s",
					r->out.domain_name,
					nt_errstr(status));
		talloc_free(tmp_ctx);
		return status;
	}

	/* get a DRSUAPI pipe handle */
	GUID_from_string(DRSUAPI_DS_BIND_GUID, &drsuapi_bind_guid);

	r_drsuapi_bind.in.bind_guid = &drsuapi_bind_guid;
	r_drsuapi_bind.in.bind_info = NULL;
	r_drsuapi_bind.out.bind_handle = &drsuapi_bind_handle;

	status = dcerpc_drsuapi_DsBind_r(drsuapi_pipe->binding_handle, tmp_ctx, &r_drsuapi_bind);
	if (!NT_STATUS_IS_OK(status)) {
		r->out.error_string
			= talloc_asprintf(r,
					  "dcerpc_drsuapi_DsBind failed - %s",
					  nt_errstr(status));
		talloc_free(tmp_ctx);
		return status;
	} else if (!W_ERROR_IS_OK(r_drsuapi_bind.out.result)) {
		r->out.error_string
				= talloc_asprintf(r,
						  "DsBind failed - %s", 
						  win_errstr(r_drsuapi_bind.out.result));
			talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* Actually 'crack' the names */
	ZERO_STRUCT(r_crack_names);
	r_crack_names.in.bind_handle		= &drsuapi_bind_handle;
	r_crack_names.in.level			= 1;
	r_crack_names.in.req			= talloc(r, union drsuapi_DsNameRequest);
	if (!r_crack_names.in.req) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}
	r_crack_names.in.req->req1.codepage	= 1252; /* western european */
	r_crack_names.in.req->req1.language	= 0x00000407; /* german */
	r_crack_names.in.req->req1.count	= 1;
	r_crack_names.in.req->req1.names	= names;
	r_crack_names.in.req->req1.format_flags	= DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
	r_crack_names.in.req->req1.format_offered = DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY;
	r_crack_names.in.req->req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
	names[0].str = dom_sid_string(tmp_ctx, r->out.account_sid);
	if (!names[0].str) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	r_crack_names.out.ctr			= talloc(r, union drsuapi_DsNameCtr);
	r_crack_names.out.level_out		= talloc(r, uint32_t);
	if (!r_crack_names.out.ctr || !r_crack_names.out.level_out) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	status = dcerpc_drsuapi_DsCrackNames_r(drsuapi_pipe->binding_handle, tmp_ctx, &r_crack_names);
	if (!NT_STATUS_IS_OK(status)) {
		r->out.error_string
			= talloc_asprintf(r,
					  "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s",
					  names[0].str,
					  nt_errstr(status));
		talloc_free(tmp_ctx);
		return status;
	} else if (!W_ERROR_IS_OK(r_crack_names.out.result)) {
		r->out.error_string
				= talloc_asprintf(r,
						  "DsCrackNames failed - %s", win_errstr(r_crack_names.out.result));
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	} else if (*r_crack_names.out.level_out != 1
		   || !r_crack_names.out.ctr->ctr1
		   || r_crack_names.out.ctr->ctr1->count != 1) {
		r->out.error_string = talloc_asprintf(r, "DsCrackNames failed");
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	} else if (r_crack_names.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
		r->out.error_string = talloc_asprintf(r, "DsCrackNames failed: %d", r_crack_names.out.ctr->ctr1->array[0].status);
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	} else if (r_crack_names.out.ctr->ctr1->array[0].result_name == NULL) {
		r->out.error_string = talloc_asprintf(r, "DsCrackNames failed: no result name");
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* Store the DN of our machine account. */
	account_dn_str = r_crack_names.out.ctr->ctr1->array[0].result_name;

	/* Now we know the user's DN, open with LDAP, read and modify a few things */

	remote_ldb_url = talloc_asprintf(tmp_ctx, "ldap://%s", 
					 drsuapi_binding->target_hostname);
	if (!remote_ldb_url) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	remote_ldb = ldb_wrap_connect(tmp_ctx, ctx->event_ctx, ctx->lp_ctx,
				      remote_ldb_url, 
				      NULL, ctx->cred, 0);
	if (!remote_ldb) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	account_dn = ldb_dn_new(tmp_ctx, remote_ldb, account_dn_str);
	if (account_dn == NULL) {
		r->out.error_string = talloc_asprintf(r, "Invalid account dn: %s",
						      account_dn_str);
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* search for the user's record */
	ret = ldb_search(remote_ldb, tmp_ctx, &res,
			 account_dn, LDB_SCOPE_BASE, attrs, NULL);
	if (ret != LDB_SUCCESS) {
		r->out.error_string = talloc_asprintf(r, "ldb_search for %s failed - %s",
						      account_dn_str, ldb_errstring(remote_ldb));
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	if (res->count != 1) {
		r->out.error_string = talloc_asprintf(r, "ldb_search for %s failed - found %d entries",
						      account_dn_str, res->count);
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* Prepare a new message, for the modify */
	msg = ldb_msg_new(tmp_ctx);
	if (!msg) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}
	msg->dn = res->msgs[0]->dn;

	{
		unsigned int i;
		const char *service_principal_name[2];
		const char *dns_host_name = strlower_talloc(msg,
							    talloc_asprintf(msg, 
									    "%s.%s", 
									    r->in.netbios_name, 
									    realm));

		if (!dns_host_name) {
			r->out.error_string = NULL;
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		service_principal_name[0] = talloc_asprintf(msg, "HOST/%s",
							    dns_host_name);
		service_principal_name[1] = talloc_asprintf(msg, "HOST/%s",
							    r->in.netbios_name);
		
		for (i=0; i < ARRAY_SIZE(service_principal_name); i++) {
			if (!service_principal_name[i]) {
				r->out.error_string = NULL;
				talloc_free(tmp_ctx);
				return NT_STATUS_NO_MEMORY;
			}
			rtn = ldb_msg_add_string(msg, "servicePrincipalName",
						 service_principal_name[i]);
			if (rtn != LDB_SUCCESS) {
				r->out.error_string = NULL;
				talloc_free(tmp_ctx);
				return NT_STATUS_NO_MEMORY;
			}
		}

		rtn = ldb_msg_add_string(msg, "dNSHostName", dns_host_name);
		if (rtn != LDB_SUCCESS) {
			r->out.error_string = NULL;
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		rtn = dsdb_replace(remote_ldb, msg, 0);
		if (rtn != LDB_SUCCESS) {
			r->out.error_string
				= talloc_asprintf(r, 
						  "Failed to replace entries on %s", 
						  ldb_dn_get_linearized(msg->dn));
			talloc_free(tmp_ctx);
			return NT_STATUS_INTERNAL_DB_CORRUPTION;
		}
	}
				
	msg = ldb_msg_new(tmp_ctx);
	if (!msg) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}
	msg->dn = res->msgs[0]->dn;

	rtn = samdb_msg_add_uint(remote_ldb, msg, msg,
				 "msDS-SupportedEncryptionTypes", ENC_ALL_TYPES);
	if (rtn != LDB_SUCCESS) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	rtn = dsdb_replace(remote_ldb, msg, 0);
	/* The remote server may not support this attribute, if it
	 * isn't a modern schema */
	if (rtn != LDB_SUCCESS && rtn != LDB_ERR_NO_SUCH_ATTRIBUTE) {
		r->out.error_string
			= talloc_asprintf(r,
					  "Failed to replace msDS-SupportedEncryptionTypes on %s",
					  ldb_dn_get_linearized(msg->dn));
		talloc_free(tmp_ctx);
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	/* DsCrackNames to find out the DN of the domain. */
	r_crack_names.in.req->req1.format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
	r_crack_names.in.req->req1.format_desired = DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
	names[0].str = talloc_asprintf(tmp_ctx, "%s\\", r->out.domain_name);
	if (!names[0].str) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	status = dcerpc_drsuapi_DsCrackNames_r(drsuapi_pipe->binding_handle, tmp_ctx, &r_crack_names);
	if (!NT_STATUS_IS_OK(status)) {
		r->out.error_string
			= talloc_asprintf(r,
					  "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s",
					  r->in.domain_name,
					  nt_errstr(status));
		talloc_free(tmp_ctx);
		return status;
	} else if (!W_ERROR_IS_OK(r_crack_names.out.result)) {
		r->out.error_string
			= talloc_asprintf(r,
					  "DsCrackNames failed - %s", win_errstr(r_crack_names.out.result));
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	} else if (*r_crack_names.out.level_out != 1
		   || !r_crack_names.out.ctr->ctr1
		   || r_crack_names.out.ctr->ctr1->count != 1
		   || !r_crack_names.out.ctr->ctr1->array[0].result_name
		   || r_crack_names.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
		r->out.error_string = talloc_asprintf(r, "DsCrackNames failed");
		talloc_free(tmp_ctx);
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* Store the account DN. */
	r->out.account_dn_str = account_dn_str;
	talloc_steal(r, account_dn_str);

	/* Store the domain DN. */
	r->out.domain_dn_str = r_crack_names.out.ctr->ctr1->array[0].result_name;
	talloc_steal(r, r_crack_names.out.ctr->ctr1->array[0].result_name);

	/* Store the KVNO of the account, critical for some kerberos
	 * operations */
	r->out.kvno = ldb_msg_find_attr_as_uint(res->msgs[0], "msDS-KeyVersionNumber", 0);

	/* Store the account GUID. */
	r->out.account_guid = samdb_result_guid(res->msgs[0], "objectGUID");

	if (r->in.acct_type == ACB_SVRTRUST) {
		status = libnet_JoinSite(ctx, remote_ldb, r);
	}
	talloc_free(tmp_ctx);

	return status;
}
示例#22
0
/*
  load our replication partners
*/
NTSTATUS wreplsrv_load_partners(struct wreplsrv_service *service)
{
	struct wreplsrv_partner *partner;
	struct ldb_result *res = NULL;
	int ret;
	TALLOC_CTX *tmp_ctx;
	int i;
	uint64_t new_seqnumber;

	new_seqnumber = wins_config_db_get_seqnumber(service->config.ldb);

	/* if it's not the first run and nothing changed we're done */
	if (service->config.seqnumber != 0 && service->config.seqnumber == new_seqnumber) {
		return NT_STATUS_OK;
	}

	tmp_ctx = talloc_new(service);
	NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);

	service->config.seqnumber = new_seqnumber;

	/* find the record in the WINS database */
	ret = ldb_search(service->config.ldb, tmp_ctx, &res,
			 ldb_dn_new(tmp_ctx, service->config.ldb, "CN=PARTNERS"),
			 LDB_SCOPE_SUBTREE, NULL, "(objectClass=wreplPartner)");
	if (ret != LDB_SUCCESS) goto failed;

	/* first disable all existing partners */
	for (partner=service->partners; partner; partner = partner->next) {
		partner->type = WINSREPL_PARTNER_NONE;
	}

	for (i=0; i < res->count; i++) {
		const char *address;

		address	= ldb_msg_find_attr_as_string(res->msgs[i], "address", NULL);
		if (!address) {
			goto failed;
		}

		partner = wreplsrv_find_partner(service, address);
		if (partner) {
			if (partner->name != partner->address) {
				talloc_free(discard_const(partner->name));
			}
			partner->name = NULL;
			talloc_free(discard_const(partner->our_address));
			partner->our_address = NULL;

			/* force rescheduling of pulling */
			partner->pull.next_run = timeval_zero();
		} else {
			partner = talloc_zero(service, struct wreplsrv_partner);
			if (partner == NULL) goto failed;

			partner->service = service;
			partner->address = address;
			talloc_steal(partner, partner->address);

			DLIST_ADD_END(service->partners, partner, struct wreplsrv_partner *);
		}

		partner->name			= ldb_msg_find_attr_as_string(res->msgs[i], "name", partner->address);
		talloc_steal(partner, partner->name);
		partner->our_address		= ldb_msg_find_attr_as_string(res->msgs[i], "ourAddress", NULL);
		talloc_steal(partner, partner->our_address);

		partner->type			= ldb_msg_find_attr_as_uint(res->msgs[i], "type", WINSREPL_PARTNER_BOTH);
		partner->pull.interval		= ldb_msg_find_attr_as_uint(res->msgs[i], "pullInterval",
								    WINSREPL_DEFAULT_PULL_INTERVAL);
		partner->pull.retry_interval	= ldb_msg_find_attr_as_uint(res->msgs[i], "pullRetryInterval",
								    WINSREPL_DEFAULT_PULL_RETRY_INTERVAL);
		partner->push.change_count	= ldb_msg_find_attr_as_uint(res->msgs[i], "pushChangeCount",
								    WINSREPL_DEFAULT_PUSH_CHANGE_COUNT);
		partner->push.use_inform	= ldb_msg_find_attr_as_uint(res->msgs[i], "pushUseInform", true);

		DEBUG(3,("wreplsrv_load_partners: found partner: %s type: 0x%X\n",
			partner->address, partner->type));
	}

	DEBUG(2,("wreplsrv_load_partners: %u partners found: wins_config_db seqnumber %llu\n",
		res->count, (unsigned long long)service->config.seqnumber));

	talloc_free(tmp_ctx);
	return NT_STATUS_OK;
failed:
	talloc_free(tmp_ctx);
	return NT_STATUS_FOOBAR;
}
示例#23
0
/* Printer functions */
static WERROR sptr_EnumPrinters(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
				struct spoolss_EnumPrinters *r)
{
	struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context);
	struct ldb_message **msgs;
	int count;
	int i;
	union spoolss_PrinterInfo *info;

	count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL,
			       "(&(objectclass=printer))");

	if (count == 0) return WERR_OK;
	if (count < 0) return WERR_GENERAL_FAILURE;

	info = talloc_array(mem_ctx, union spoolss_PrinterInfo, count);
	W_ERROR_HAVE_NO_MEMORY(info);

	switch(r->in.level) {
	case 1:
		for (i = 0; i < count; i++) {
			info[i].info1.flags		= ldb_msg_find_attr_as_uint(msgs[i], "flags", 0);

			info[i].info1.name		= ldb_msg_find_attr_as_string(msgs[i], "name", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info1.name);

			info[i].info1.description	= ldb_msg_find_attr_as_string(msgs[i], "description", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info1.description);

			info[i].info1.comment		= ldb_msg_find_attr_as_string(msgs[i], "comment", NULL);
		}
		break;
	case 2:
		for (i = 0; i < count; i++) {
			info[i].info2.servername	= ldb_msg_find_attr_as_string(msgs[i], "servername", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername);

			info[i].info2.printername	= ldb_msg_find_attr_as_string(msgs[i], "printername", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername);

			info[i].info2.sharename		= ldb_msg_find_attr_as_string(msgs[i], "sharename", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info2.sharename);

			info[i].info2.portname		= ldb_msg_find_attr_as_string(msgs[i], "portname", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info2.portname);

			info[i].info2.drivername	= ldb_msg_find_attr_as_string(msgs[i], "drivername", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info2.drivername);

			info[i].info2.comment		= ldb_msg_find_attr_as_string(msgs[i], "comment", NULL);

			info[i].info2.location		= ldb_msg_find_attr_as_string(msgs[i], "location", NULL);

			info[i].info2.devmode		= NULL;

			info[i].info2.sepfile		= ldb_msg_find_attr_as_string(msgs[i], "sepfile", NULL);

			info[i].info2.printprocessor	= ldb_msg_find_attr_as_string(msgs[i], "printprocessor", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info2.printprocessor);

			info[i].info2.datatype		= ldb_msg_find_attr_as_string(msgs[i], "datatype", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info2.datatype);

			info[i].info2.parameters	= ldb_msg_find_attr_as_string(msgs[i], "parameters", NULL);

			info[i].info2.secdesc		= NULL;

			info[i].info2.attributes	= ldb_msg_find_attr_as_uint(msgs[i], "attributes", 0);
			info[i].info2.priority		= ldb_msg_find_attr_as_uint(msgs[i], "priority", 0);
			info[i].info2.defaultpriority	= ldb_msg_find_attr_as_uint(msgs[i], "defaultpriority", 0);
			info[i].info2.starttime		= ldb_msg_find_attr_as_uint(msgs[i], "starttime", 0);
			info[i].info2.untiltime		= ldb_msg_find_attr_as_uint(msgs[i], "untiltime", 0);
			info[i].info2.status		= ldb_msg_find_attr_as_uint(msgs[i], "status", 0);
			info[i].info2.cjobs		= ldb_msg_find_attr_as_uint(msgs[i], "cjobs", 0);
			info[i].info2.averageppm	= ldb_msg_find_attr_as_uint(msgs[i], "averageppm", 0);
		}
		break;
	case 4:
		for (i = 0; i < count; i++) {
			info[i].info4.printername	= ldb_msg_find_attr_as_string(msgs[i], "printername", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername);

			info[i].info4.servername	= ldb_msg_find_attr_as_string(msgs[i], "servername", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername);

			info[i].info4.attributes	= ldb_msg_find_attr_as_uint(msgs[i], "attributes", 0);
		}
		break;
	case 5:
		for (i = 0; i < count; i++) {
			info[i].info5.printername	= ldb_msg_find_attr_as_string(msgs[i], "name", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info5.printername);

			info[i].info5.portname		= ldb_msg_find_attr_as_string(msgs[i], "port", "");
			W_ERROR_HAVE_NO_MEMORY(info[i].info5.portname);

			info[i].info5.attributes	= ldb_msg_find_attr_as_uint(msgs[i], "attributes", 0);
			info[i].info5.device_not_selected_timeout = ldb_msg_find_attr_as_uint(msgs[i], "device_not_selected_timeout", 0);
			info[i].info5.transmission_retry_timeout  = ldb_msg_find_attr_as_uint(msgs[i], "transmission_retry_timeout", 0);
		}
		break;
	default:
		return WERR_UNKNOWN_LEVEL;
	}

	*r->out.info	= info;
	*r->out.count	= count;
	return WERR_OK;
}
/* add_record: add instancetype attribute */
static int instancetype_add(struct ldb_module *module, struct ldb_request *req)
{
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct ldb_request *down_req;
	struct ldb_message *msg;
	struct ldb_message_element *el;
	uint32_t instanceType;
	int ret;

	/* do not manipulate our control entries */
	if (ldb_dn_is_special(req->op.add.message->dn)) {
		return ldb_next_request(module, req);
	}

	ldb_debug(ldb, LDB_DEBUG_TRACE, "instancetype_add\n");

	el = ldb_msg_find_element(req->op.add.message, "instanceType");
	if (el != NULL) {
		if (el->num_values != 1) {
			ldb_set_errstring(ldb, "instancetype: the 'instanceType' attribute is single-valued!");
			return LDB_ERR_UNWILLING_TO_PERFORM;
		}

		instanceType = ldb_msg_find_attr_as_uint(req->op.add.message,
							 "instanceType", 0);
		if (!(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
			/*
			 * If we have no NC add operation (no TYPE_IS_NC_HEAD)
			 * then "instanceType" can only be "0" or "TYPE_WRITE".
			 */
			if ((instanceType != 0) &&
			    ((instanceType & INSTANCE_TYPE_WRITE) == 0)) {
				ldb_set_errstring(ldb, "instancetype: if TYPE_IS_NC_HEAD wasn't set, then only TYPE_WRITE or 0 are allowed!");
				return LDB_ERR_UNWILLING_TO_PERFORM;
			}
		} else {
			/*
			 * If we have a NC add operation then we need also the
			 * "TYPE_WRITE" flag in order to succeed,
			 * unless this NC is not instantiated
			*/
			if (!(instanceType & INSTANCE_TYPE_UNINSTANT) &&
			    !(instanceType & INSTANCE_TYPE_WRITE)) {
				ldb_set_errstring(ldb, "instancetype: if TYPE_IS_NC_HEAD was set, then also TYPE_WRITE is requested!");
				return LDB_ERR_UNWILLING_TO_PERFORM;
			}
		}

		/* we did only tests, so proceed with the original request */
		return ldb_next_request(module, req);
	}

	/* we have to copy the message as the caller might have it as a const */
	msg = ldb_msg_copy_shallow(req, req->op.add.message);
	if (msg == NULL) {
		return ldb_oom(ldb);
	}

	/*
	 * TODO: calculate correct instance type
	 */
	instanceType = INSTANCE_TYPE_WRITE;

	ret = samdb_msg_add_uint(ldb, msg, msg, "instanceType", instanceType);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	ret = ldb_build_add_req(&down_req, ldb, req,
				msg,
				req->controls,
				req, dsdb_next_callback,
				req);
	LDB_REQ_SET_LOCATION(down_req);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	/* go on with the call chain */
	return ldb_next_request(module, down_req);
}
示例#25
0
/*
  construct the parent GUID for an entry from a message
*/
static int construct_parent_guid(struct ldb_module *module,
				 struct ldb_message *msg, enum ldb_scope scope,
				 struct ldb_request *parent)
{
	struct ldb_result *res, *parent_res;
	const struct ldb_val *parent_guid;
	const char *attrs[] = { "instanceType", NULL };
	const char *attrs2[] = { "objectGUID", NULL };
	uint32_t instanceType;
	int ret;
	struct ldb_dn *parent_dn;
	struct ldb_val v;

	/* determine if the object is NC by instance type */
	ret = dsdb_module_search_dn(module, msg, &res, msg->dn, attrs,
	                            DSDB_FLAG_NEXT_MODULE |
	                            DSDB_SEARCH_SHOW_RECYCLED, parent);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	instanceType = ldb_msg_find_attr_as_uint(res->msgs[0],
						 "instanceType", 0);
	talloc_free(res);
	if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) {
		DEBUG(4,(__location__ ": Object %s is NC\n",
			 ldb_dn_get_linearized(msg->dn)));
		return LDB_SUCCESS;
	}
	parent_dn = ldb_dn_get_parent(msg, msg->dn);

	if (parent_dn == NULL) {
		DEBUG(4,(__location__ ": Failed to find parent for dn %s\n",
					 ldb_dn_get_linearized(msg->dn)));
		return LDB_SUCCESS;
	}
	ret = dsdb_module_search_dn(module, msg, &parent_res, parent_dn, attrs2,
	                            DSDB_FLAG_NEXT_MODULE |
	                            DSDB_SEARCH_SHOW_RECYCLED, parent);
	talloc_free(parent_dn);

	/* not NC, so the object should have a parent*/
	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
		return ldb_error(ldb_module_get_ctx(module), LDB_ERR_OPERATIONS_ERROR, 
				 talloc_asprintf(msg, "Parent dn for %s does not exist", 
						 ldb_dn_get_linearized(msg->dn)));
	} else if (ret != LDB_SUCCESS) {
		return ret;
	}

	parent_guid = ldb_msg_find_ldb_val(parent_res->msgs[0], "objectGUID");
	if (!parent_guid) {
		talloc_free(parent_res);
		return LDB_SUCCESS;
	}

	v = data_blob_dup_talloc(parent_res, *parent_guid);
	if (!v.data) {
		talloc_free(parent_res);
		return ldb_oom(ldb_module_get_ctx(module));
	}
	ret = ldb_msg_add_steal_value(msg, "parentGUID", &v);
	talloc_free(parent_res);
	return ret;
}
示例#26
0
_PUBLIC_ NTSTATUS authsam_make_user_info_dc(TALLOC_CTX *mem_ctx,
					   struct ldb_context *sam_ctx,
					   const char *netbios_name,
					   const char *domain_name,
					   struct ldb_dn *domain_dn, 
					   struct ldb_message *msg,
					   DATA_BLOB user_sess_key,
					   DATA_BLOB lm_sess_key,
					   struct auth_user_info_dc **_user_info_dc)
{
	NTSTATUS status;
	struct auth_user_info_dc *user_info_dc;
	struct auth_user_info *info;
	const char *str, *filter;
	/* SIDs for the account and his primary group */
	struct dom_sid *account_sid;
	const char *primary_group_string;
	const char *primary_group_dn;
	DATA_BLOB primary_group_blob;
	/* SID structures for the expanded group memberships */
	struct dom_sid *sids = NULL;
	unsigned int num_sids = 0, i;
	struct dom_sid *domain_sid;
	TALLOC_CTX *tmp_ctx;
	struct ldb_message_element *el;

	user_info_dc = talloc(mem_ctx, struct auth_user_info_dc);
	NT_STATUS_HAVE_NO_MEMORY(user_info_dc);

	tmp_ctx = talloc_new(user_info_dc);
	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(user_info_dc, user_info_dc);

	sids = talloc_array(user_info_dc, struct dom_sid, 2);
	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sids, user_info_dc);

	num_sids = 2;

	account_sid = samdb_result_dom_sid(user_info_dc, msg, "objectSid");
	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(account_sid, user_info_dc);

	status = dom_sid_split_rid(tmp_ctx, account_sid, &domain_sid, NULL);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(user_info_dc);
		return status;
	}

	sids[PRIMARY_USER_SID_INDEX] = *account_sid;
	sids[PRIMARY_GROUP_SID_INDEX] = *domain_sid;
	sid_append_rid(&sids[PRIMARY_GROUP_SID_INDEX], ldb_msg_find_attr_as_uint(msg, "primaryGroupID", ~0));

	/* Filter out builtin groups from this token.  We will search
	 * for builtin groups later, and not include them in the PAC
	 * on SamLogon validation info */
	filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(!(groupType:1.2.840.113556.1.4.803:=%u))(groupType:1.2.840.113556.1.4.803:=%u))", GROUP_TYPE_BUILTIN_LOCAL_GROUP, GROUP_TYPE_SECURITY_ENABLED);
	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(filter, user_info_dc);

	primary_group_string = dom_sid_string(tmp_ctx, &sids[PRIMARY_GROUP_SID_INDEX]);
	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(primary_group_string, user_info_dc);

	primary_group_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", primary_group_string);
	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(primary_group_dn, user_info_dc);

	primary_group_blob = data_blob_string_const(primary_group_dn);

	/* Expands the primary group - this function takes in
	 * memberOf-like values, so we fake one up with the
	 * <SID=S-...> format of DN and then let it expand
	 * them, as long as they meet the filter - so only
	 * domain groups, not builtin groups
	 *
	 * The primary group is still treated specially, so we set the
	 * 'only childs' flag to true
	 */
	status = dsdb_expand_nested_groups(sam_ctx, &primary_group_blob, true, filter,
					   user_info_dc, &sids, &num_sids);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(user_info_dc);
		return status;
	}

	/* Expands the additional groups */
	el = ldb_msg_find_element(msg, "memberOf");
	for (i = 0; el && i < el->num_values; i++) {
		/* This function takes in memberOf values and expands
		 * them, as long as they meet the filter - so only
		 * domain groups, not builtin groups */
		status = dsdb_expand_nested_groups(sam_ctx, &el->values[i], false, filter,
						   user_info_dc, &sids, &num_sids);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(user_info_dc);
			return status;
		}
	}

	user_info_dc->sids = sids;
	user_info_dc->num_sids = num_sids;

	user_info_dc->info = info = talloc_zero(user_info_dc, struct auth_user_info);
	NT_STATUS_HAVE_NO_MEMORY(user_info_dc->info);

	info->account_name = talloc_steal(info,
		ldb_msg_find_attr_as_string(msg, "sAMAccountName", NULL));

	info->domain_name = talloc_strdup(info, domain_name);
	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(info->domain_name,
		user_info_dc);

	str = ldb_msg_find_attr_as_string(msg, "displayName", "");
	info->full_name = talloc_strdup(info, str);
	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(info->full_name, user_info_dc);

	str = ldb_msg_find_attr_as_string(msg, "scriptPath", "");
	info->logon_script = talloc_strdup(info, str);
	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(info->logon_script,
		user_info_dc);

	str = ldb_msg_find_attr_as_string(msg, "profilePath", "");
	info->profile_path = talloc_strdup(info, str);
	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(info->profile_path,
		user_info_dc);

	str = ldb_msg_find_attr_as_string(msg, "homeDirectory", "");
	info->home_directory = talloc_strdup(info, str);
	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(info->home_directory,
		user_info_dc);

	str = ldb_msg_find_attr_as_string(msg, "homeDrive", "");
	info->home_drive = talloc_strdup(info, str);
	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(info->home_drive, user_info_dc);

	info->logon_server = talloc_strdup(info, netbios_name);
	NT_STATUS_HAVE_NO_MEMORY_AND_FREE(info->logon_server,
		user_info_dc);

	info->last_logon = samdb_result_nttime(msg, "lastLogon", 0);
	info->last_logoff = samdb_result_last_logoff(msg);
	info->acct_expiry = samdb_result_account_expires(msg);
	info->last_password_change = samdb_result_nttime(msg,
		"pwdLastSet", 0);
	info->allow_password_change
		= samdb_result_allow_password_change(sam_ctx, mem_ctx, 
			domain_dn, msg, "pwdLastSet");
	info->force_password_change
		= samdb_result_force_password_change(sam_ctx, mem_ctx,
			domain_dn, msg);
	info->logon_count = ldb_msg_find_attr_as_uint(msg, "logonCount", 0);
	info->bad_password_count = ldb_msg_find_attr_as_uint(msg, "badPwdCount",
		0);

	info->acct_flags = samdb_result_acct_flags(sam_ctx, mem_ctx,
							  msg, domain_dn);

	user_info_dc->user_session_key = data_blob_talloc(user_info_dc,
							 user_sess_key.data,
							 user_sess_key.length);
	if (user_sess_key.data) {
		NT_STATUS_HAVE_NO_MEMORY_AND_FREE(user_info_dc->user_session_key.data,
						  user_info_dc);
	}
	user_info_dc->lm_session_key = data_blob_talloc(user_info_dc,
						       lm_sess_key.data,
						       lm_sess_key.length);
	if (lm_sess_key.data) {
		NT_STATUS_HAVE_NO_MEMORY_AND_FREE(user_info_dc->lm_session_key.data,
						  user_info_dc);
	}

	if (info->acct_flags & ACB_SVRTRUST) {
		/* the SID_NT_ENTERPRISE_DCS SID gets added into the
		   PAC */
		user_info_dc->sids = talloc_realloc(user_info_dc,
						   user_info_dc->sids,
						   struct dom_sid,
						   user_info_dc->num_sids+1);
		NT_STATUS_HAVE_NO_MEMORY_AND_FREE(user_info_dc->sids, user_info_dc);
		user_info_dc->sids[user_info_dc->num_sids] = global_sid_Enterprise_DCs;
		user_info_dc->num_sids++;
	}
示例#27
0
文件: util_samr.c 项目: Arkhont/samba
NTSTATUS dsdb_lookup_rids(struct ldb_context *ldb,
			  TALLOC_CTX *mem_ctx,
			  const struct dom_sid *domain_sid,
			  unsigned int num_rids,
			  uint32_t *rids,
			  const char **names,
			  enum lsa_SidType *lsa_attrs)
{
	const char *attrs[] = { "sAMAccountType", "sAMAccountName", NULL };
	unsigned int i, num_mapped;

	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);

	num_mapped = 0;

	for (i=0; i<num_rids; i++) {
		struct ldb_message *msg;
		struct ldb_dn *dn;
		uint32_t attr;
		int rc;

		lsa_attrs[i] = SID_NAME_UNKNOWN;

		dn = ldb_dn_new_fmt(tmp_ctx, ldb, "<SID=%s>",
				    dom_sid_string(tmp_ctx,
						   dom_sid_add_rid(tmp_ctx, domain_sid,
								   rids[i])));
		if (dn == NULL) {
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}
		rc = dsdb_search_one(ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "samAccountName=*");
		if (rc == LDB_ERR_NO_SUCH_OBJECT) {
			continue;
		} else if (rc != LDB_SUCCESS) {
			talloc_free(tmp_ctx);
			return NT_STATUS_INTERNAL_DB_CORRUPTION;
		}

		names[i] = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
		if (names[i] == NULL) {
			DEBUG(10, ("no samAccountName\n"));
			continue;
		}
		talloc_steal(names, names[i]);
		attr = ldb_msg_find_attr_as_uint(msg, "samAccountType", 0);
		lsa_attrs[i] = ds_atype_map(attr);
		if (lsa_attrs[i] == SID_NAME_UNKNOWN) {
			continue;
		}
		num_mapped += 1;
	}
	talloc_free(tmp_ctx);

	if (num_mapped == 0) {
		return NT_STATUS_NONE_MAPPED;
	}
	if (num_mapped < num_rids) {
		return STATUS_SOME_UNMAPPED;
	}
	return NT_STATUS_OK;
}
示例#28
0
NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call,
				     TALLOC_CTX *mem_ctx,
				     uint32_t access_desired,
				     struct lsa_policy_state **_state)
{
	struct auth_session_info *session_info = dce_call->conn->auth_state.session_info;
	enum security_user_level security_level;
	struct lsa_policy_state *state;
	struct ldb_result *dom_res;
	const char *dom_attrs[] = {
		"objectSid", 
		"objectGUID", 
		"nTMixedDomain",
		"fSMORoleOwner",
		NULL
	};
	char *p;
	int ret;

	state = talloc_zero(mem_ctx, struct lsa_policy_state);
	if (!state) {
		return NT_STATUS_NO_MEMORY;
	}

	/* make sure the sam database is accessible */
	state->sam_ldb = samdb_connect(state,
				       dce_call->event_ctx,
				       dce_call->conn->dce_ctx->lp_ctx,
				       dce_call->conn->auth_state.session_info,
				       dce_call->conn->remote_address,
				       0);
	if (state->sam_ldb == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	/* and the privilege database */
	state->pdb = privilege_connect(state, dce_call->conn->dce_ctx->lp_ctx);
	if (state->pdb == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	/* work out the domain_dn - useful for so many calls its worth
	   fetching here */
	state->domain_dn = ldb_get_default_basedn(state->sam_ldb);
	if (!state->domain_dn) {
		return NT_STATUS_NO_MEMORY;		
	}

	/* work out the forest root_dn - useful for so many calls its worth
	   fetching here */
	state->forest_dn = ldb_get_root_basedn(state->sam_ldb);
	if (!state->forest_dn) {
		return NT_STATUS_NO_MEMORY;		
	}

	ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res,
			 state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
	if (ret != LDB_SUCCESS) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}
	if (dom_res->count != 1) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
	if (!state->domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");

	state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
	
	talloc_free(dom_res);

	state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);

	state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn);
	if (!state->domain_dns) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}
	p = strchr(state->domain_dns, '/');
	if (p) {
		*p = '\0';
	}

	state->forest_dns = ldb_dn_canonical_string(state, state->forest_dn);
	if (!state->forest_dns) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}
	p = strchr(state->forest_dns, '/');
	if (p) {
		*p = '\0';
	}

	/* work out the builtin_dn - useful for so many calls its worth
	   fetching here */
	state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
	if (!state->builtin_dn) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	/* work out the system_dn - useful for so many calls its worth
	   fetching here */
	state->system_dn = samdb_search_dn(state->sam_ldb, state,
					   state->domain_dn, "(&(objectClass=container)(cn=System))");
	if (!state->system_dn) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
	if (!state->builtin_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY);
	if (!state->nt_authority_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN);
	if (!state->creator_owner_domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN);
	if (!state->world_domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->sd = sddl_decode(state, DCESRV_LSA_POLICY_SD_SDDL,
				state->domain_sid);
	if (state->sd == NULL) {
		return NT_STATUS_NO_MEMORY;
	}
	state->sd->dacl->revision = SECURITY_ACL_REVISION_NT4;

	se_map_generic(&access_desired, &dcesrv_lsa_policy_mapping);
	security_acl_map_generic(state->sd->dacl, &dcesrv_lsa_policy_mapping);

	security_level = security_session_user_level(session_info, NULL);
	if (security_level >= SECURITY_SYSTEM) {
		/*
		 * The security descriptor doesn't allow system,
		 * but we want to allow system via ncalrpc as root.
		 */
		state->access_mask = access_desired;
		if (state->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
			state->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
			state->access_mask |= LSA_POLICY_ALL_ACCESS;
		}
	} else {
		NTSTATUS status;

		status = se_access_check(state->sd,
					 session_info->security_token,
					 access_desired,
					 &state->access_mask);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(2,("%s: access desired[0x%08X] rejected[0x%08X] - %s\n",
				 __func__,
				 (unsigned)access_desired,
				 (unsigned)state->access_mask,
				 nt_errstr(status)));
			return status;
		}
	}

	DEBUG(10,("%s: access desired[0x%08X] granted[0x%08X] - success.\n",
		  __func__,
		 (unsigned)access_desired,
		 (unsigned)state->access_mask));

	*_state = state;

	return NT_STATUS_OK;
}
示例#29
0
文件: lsa_init.c 项目: AllardJ/Tomato
NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
				     struct lsa_policy_state **_state)
{
	struct lsa_policy_state *state;
	struct ldb_result *dom_res;
	const char *dom_attrs[] = {
		"objectSid", 
		"objectGUID", 
		"nTMixedDomain",
		"fSMORoleOwner",
		NULL
	};
	char *p;
	int ret;

	state = talloc(mem_ctx, struct lsa_policy_state);
	if (!state) {
		return NT_STATUS_NO_MEMORY;
	}

	/* make sure the sam database is accessible */
	state->sam_ldb = samdb_connect(state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info); 
	if (state->sam_ldb == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	/* work out the domain_dn - useful for so many calls its worth
	   fetching here */
	state->domain_dn = ldb_get_default_basedn(state->sam_ldb);
	if (!state->domain_dn) {
		return NT_STATUS_NO_MEMORY;		
	}

	/* work out the forest root_dn - useful for so many calls its worth
	   fetching here */
	state->forest_dn = samdb_root_dn(state->sam_ldb);
	if (!state->forest_dn) {
		return NT_STATUS_NO_MEMORY;		
	}

	ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res,
			 state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
	if (ret != LDB_SUCCESS) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}
	if (dom_res->count != 1) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
	if (!state->domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");

	state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
	
	talloc_free(dom_res);

	state->domain_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);

	state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn);
	if (!state->domain_dns) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}
	p = strchr(state->domain_dns, '/');
	if (p) {
		*p = '\0';
	}

	state->forest_dns = ldb_dn_canonical_string(state, state->forest_dn);
	if (!state->forest_dns) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}
	p = strchr(state->forest_dns, '/');
	if (p) {
		*p = '\0';
	}

	/* work out the builtin_dn - useful for so many calls its worth
	   fetching here */
	state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
	if (!state->builtin_dn) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	/* work out the system_dn - useful for so many calls its worth
	   fetching here */
	state->system_dn = samdb_search_dn(state->sam_ldb, state,
					   state->domain_dn, "(&(objectClass=container)(cn=System))");
	if (!state->system_dn) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
	if (!state->builtin_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY);
	if (!state->nt_authority_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN);
	if (!state->creator_owner_domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN);
	if (!state->world_domain_sid) {
		return NT_STATUS_NO_SUCH_DOMAIN;		
	}

	*_state = state;

	return NT_STATUS_OK;
}
示例#30
0
文件: util_samr.c 项目: Arkhont/samba
/* Add a user, SAMR style, including the correct transaction
 * semantics.  Used by the SAMR server and by pdb_samba4 */
NTSTATUS dsdb_add_user(struct ldb_context *ldb,
		       TALLOC_CTX *mem_ctx,
		       const char *account_name,
		       uint32_t acct_flags,
		       struct dom_sid **sid,
		       struct ldb_dn **dn)
{
	const char *name;
	struct ldb_message *msg;
	int ret;
	const char *container, *obj_class=NULL;
	char *cn_name;
	size_t cn_name_len;

	const char *attrs[] = {
		"objectSid",
		"userAccountControl",
		NULL
	};

	uint32_t user_account_control;
	struct ldb_dn *account_dn;
	struct dom_sid *account_sid;

	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);

	/*
	 * Start a transaction, so we can query and do a subsequent atomic
	 * modify
	 */

	ret = ldb_transaction_start(ldb);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,("Failed to start a transaction for user creation: %s\n",
			 ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	/* check if the user already exists */
	name = samdb_search_string(ldb, tmp_ctx, NULL,
				   "sAMAccountName",
				   "(&(sAMAccountName=%s)(objectclass=user))",
				   ldb_binary_encode_string(tmp_ctx, account_name));
	if (name != NULL) {
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_USER_EXISTS;
	}

	cn_name = talloc_strdup(tmp_ctx, account_name);
	if (!cn_name) {
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	cn_name_len = strlen(cn_name);
	if (cn_name_len < 1) {
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	}

	msg = ldb_msg_new(tmp_ctx);
	if (msg == NULL) {
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	/* This must be one of these values *only* */
	if (acct_flags == ACB_NORMAL) {
		container = "CN=Users";
		obj_class = "user";

	} else if (acct_flags == ACB_WSTRUST) {
		if (cn_name[cn_name_len - 1] != '$') {
			ldb_transaction_cancel(ldb);
			return NT_STATUS_FOOBAR;
		}
		cn_name[cn_name_len - 1] = '\0';
		container = "CN=Computers";
		obj_class = "computer";

	} else if (acct_flags == ACB_SVRTRUST) {
		if (cn_name[cn_name_len - 1] != '$') {
			ldb_transaction_cancel(ldb);
			return NT_STATUS_FOOBAR;
		}
		cn_name[cn_name_len - 1] = '\0';
		container = "OU=Domain Controllers";
		obj_class = "computer";
	} else {
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* add core elements to the ldb_message for the user */
	msg->dn = ldb_dn_copy(msg, ldb_get_default_basedn(ldb));
	if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s,%s", cn_name, container)) {
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_FOOBAR;
	}

	ldb_msg_add_string(msg, "sAMAccountName", account_name);
	ldb_msg_add_string(msg, "objectClass", obj_class);

	/* create the user */
	ret = ldb_add(ldb, msg);
	switch (ret) {
	case LDB_SUCCESS:
		break;
	case LDB_ERR_ENTRY_ALREADY_EXISTS:
		ldb_transaction_cancel(ldb);
		DEBUG(0,("Failed to create user record %s: %s\n",
			 ldb_dn_get_linearized(msg->dn),
			 ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return NT_STATUS_USER_EXISTS;
	case LDB_ERR_UNWILLING_TO_PERFORM:
	case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
		ldb_transaction_cancel(ldb);
		DEBUG(0,("Failed to create user record %s: %s\n",
			 ldb_dn_get_linearized(msg->dn),
			 ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return NT_STATUS_ACCESS_DENIED;
	default:
		ldb_transaction_cancel(ldb);
		DEBUG(0,("Failed to create user record %s: %s\n",
			 ldb_dn_get_linearized(msg->dn),
			 ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	account_dn = msg->dn;

	/* retrieve the sid and account control bits for the user just created */
	ret = dsdb_search_one(ldb, tmp_ctx, &msg,
			      account_dn, LDB_SCOPE_BASE, attrs, 0, NULL);

	if (ret != LDB_SUCCESS) {
		ldb_transaction_cancel(ldb);
		DEBUG(0,("Can't locate the account we just created %s: %s\n",
			 ldb_dn_get_linearized(account_dn), ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}
	account_sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
	if (account_sid == NULL) {
		ldb_transaction_cancel(ldb);
		DEBUG(0,("Apparently we failed to get the objectSid of the just created account record %s\n",
			 ldb_dn_get_linearized(msg->dn)));
		talloc_free(tmp_ctx);
		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 = ldb_msg_find_attr_as_uint(msg, "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 |= ds_acb2uf(acct_flags);

	talloc_free(msg);
	msg = ldb_msg_new(tmp_ctx);
	if (msg == NULL) {
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	msg->dn = account_dn;

	if (samdb_msg_add_uint(ldb, tmp_ctx, msg,
			       "userAccountControl",
			       user_account_control) != LDB_SUCCESS) {
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	/* modify the samdb record */
	ret = dsdb_replace(ldb, msg, 0);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,("Failed to modify account record %s to set userAccountControl: %s\n",
			 ldb_dn_get_linearized(msg->dn),
			 ldb_errstring(ldb)));
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);

		/* we really need samdb.c to return NTSTATUS */
		return NT_STATUS_UNSUCCESSFUL;
	}

	ret = ldb_transaction_commit(ldb);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
			 ldb_dn_get_linearized(msg->dn),
			 ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}
	*dn = talloc_steal(mem_ctx, account_dn);
	*sid = talloc_steal(mem_ctx, account_sid);
	talloc_free(tmp_ctx);
	return NT_STATUS_OK;
}