コード例 #1
0
/*
  remember an established session key for a netr server authentication
  use a simple ldb structure
*/
NTSTATUS schannel_store_session_key_ldb(TALLOC_CTX *mem_ctx,
					struct ldb_context *ldb,
					struct creds_CredentialState *creds)
{
	struct ldb_message *msg;
	struct ldb_val val, seed, client_state, server_state;
	char *f;
	char *sct;
	int ret;

	f = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->negotiate_flags);

	if (f == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	sct = talloc_asprintf(mem_ctx, "%u", (unsigned int)creds->secure_channel_type);

	if (sct == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

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

	msg->dn = ldb_dn_new_fmt(msg, ldb, "computerName=%s", creds->computer_name);
	if ( ! msg->dn) {
		return NT_STATUS_NO_MEMORY;
	}

	val.data = creds->session_key;
	val.length = sizeof(creds->session_key);

	seed.data = creds->seed.data;
	seed.length = sizeof(creds->seed.data);

	client_state.data = creds->client.data;
	client_state.length = sizeof(creds->client.data);
	server_state.data = creds->server.data;
	server_state.length = sizeof(creds->server.data);

	ldb_msg_add_string(msg, "objectClass", "schannelState");
	ldb_msg_add_value(msg, "sessionKey", &val, NULL);
	ldb_msg_add_value(msg, "seed", &seed, NULL);
	ldb_msg_add_value(msg, "clientState", &client_state, NULL);
	ldb_msg_add_value(msg, "serverState", &server_state, NULL);
	ldb_msg_add_string(msg, "negotiateFlags", f);
	ldb_msg_add_string(msg, "secureChannelType", sct);
	ldb_msg_add_string(msg, "accountName", creds->account_name);
	ldb_msg_add_string(msg, "computerName", creds->computer_name);
	ldb_msg_add_string(msg, "flatname", creds->domain);
	samdb_msg_add_dom_sid(ldb, mem_ctx, msg, "objectSid", creds->sid);

	ldb_delete(ldb, msg->dn);

	ret = ldb_add(ldb, msg);

	if (ret != 0) {
		DEBUG(0,("Unable to add %s to session key db - %s\n", 
			 ldb_dn_get_linearized(msg->dn), ldb_errstring(ldb)));
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	return NT_STATUS_OK;
}
コード例 #2
0
ファイル: operational.c プロジェクト: AIdrifter/samba
/*
  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;
}
コード例 #3
0
ファイル: util_samr.c プロジェクト: AIdrifter/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,
		       const struct dom_sid *forced_sid,
		       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_LOCK_NOT_GRANTED;
	}

	/* 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 if (acct_flags == ACB_DOMTRUST) {
		DEBUG(3, ("Invalid account flags specified:  cannot create domain trusts via this interface (must use LSA CreateTrustedDomain calls\n"));
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	} else {
		DEBUG(3, ("Invalid account flags specified 0x%08X, must be exactly one of \n"
			  "ACB_NORMAL (0x%08X) ACB_WSTRUST (0x%08X) or ACB_SVRTRUST (0x%08X)\n",
			  acct_flags,
			  ACB_NORMAL, ACB_WSTRUST, ACB_SVRTRUST));
		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);

	/* This is only here for migrations using pdb_samba4, the
	 * caller and the samldb are responsible for ensuring it makes
	 * sense */
	if (forced_sid) {
		ret = samdb_msg_add_dom_sid(ldb, msg, msg, "objectSID", forced_sid);
		if (ret != LDB_SUCCESS) {
			ldb_transaction_cancel(ldb);
			talloc_free(tmp_ctx);
			return NT_STATUS_INTERNAL_ERROR;
		}
	}

	/* 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);
	if (sid) {
		*sid = talloc_steal(mem_ctx, account_sid);
	}
	talloc_free(tmp_ctx);
	return NT_STATUS_OK;
}