--- /dev/null
+/*
+ Unix SMB/CIFS implementation.
+ msDS-ManagedPassword attribute for Group Managed Service Accounts
+
+ Copyright (C) Catalyst.Net Ltd 2024
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include <talloc.h>
+#include <ldb.h>
+#include <ldb_module.h>
+#include <ldb_errors.h>
+#include <ldb_private.h>
+#include "lib/crypto/gmsa.h"
+#include "lib/util/time.h"
+#include "librpc/gen_ndr/ndr_gkdi.h"
+#include "librpc/gen_ndr/ndr_gmsa.h"
+#include "dsdb/gmsa/util.h"
+#include "dsdb/samdb/ldb_modules/managed_pwd.h"
+#include "dsdb/samdb/ldb_modules/util.h"
+#include "dsdb/samdb/samdb.h"
+
+#undef strcasecmp
+
+static int gmsa_managed_password(struct ldb_context *const ldb,
+ struct ldb_message *msg,
+ struct ldb_request *req,
+ struct ldb_reply *ares)
+{
+ TALLOC_CTX *tmp_ctx = NULL;
+ const struct dsdb_encrypted_connection_state *conn_state = NULL;
+ int ret = LDB_SUCCESS;
+ NTSTATUS status = NT_STATUS_OK;
+ NTTIME current_time;
+ struct gmsa_update *gmsa_update = NULL;
+ struct gmsa_return_pwd return_pwd;
+ bool ok;
+
+ /*
+ * Prevent viewing msDS-ManagedPassword over an insecure connection. The
+ * opaque is added in the ldap backend init.
+ */
+ conn_state = ldb_get_opaque(
+ ldb, DSDB_OPAQUE_ENCRYPTED_CONNECTION_STATE_NAME);
+ if (conn_state != NULL && !conn_state->using_encrypted_connection) {
+ ret = dsdb_werror(ldb,
+ LDB_ERR_OPERATIONS_ERROR,
+ WERR_DS_CONFIDENTIALITY_REQUIRED,
+ "Viewing msDS-ManagedPassword requires an "
+ "encrypted connection");
+ goto out;
+ }
+
+ {
+ /* Is the account a Group Managed Service Account? */
+ const bool is_gmsa = dsdb_account_is_gmsa(ldb, msg);
+ if (!is_gmsa) {
+ /* It’s not a GMSA — we’re done here. */
+ ret = LDB_SUCCESS;
+ goto out;
+ }
+ }
+
+ {
+ bool am_rodc = true;
+
+ /* Are we operating as an RODC? */
+ ret = samdb_rodc(ldb, &am_rodc);
+ if (ret != LDB_SUCCESS) {
+ DBG_WARNING("unable to tell if we are an RODC\n");
+ goto out;
+ }
+
+ if (am_rodc) {
+ /* TODO: forward the request to a writable DC. */
+ ret = ldb_error(
+ ldb,
+ LDB_ERR_OPERATIONS_ERROR,
+ "msDS-ManagedPassword may only be viewed on a "
+ "writeable DC, not an RODC");
+ goto out;
+ }
+ }
+
+ tmp_ctx = talloc_new(msg);
+ if (tmp_ctx == NULL) {
+ ret = ldb_oom(ldb);
+ goto out;
+ }
+
+ {
+ struct dom_sid account_sid;
+ bool allowed_to_view = false;
+
+ ret = samdb_result_dom_sid_buf(msg, "objectSid", &account_sid);
+ if (ret) {
+ goto out;
+ }
+
+ ret = gmsa_allowed_to_view_managed_password(
+ tmp_ctx, ldb, msg, &account_sid, &allowed_to_view);
+ if (ret) {
+ goto out;
+ }
+
+ if (!allowed_to_view) {
+ /* Sorry, you can’t view the password. */
+ goto out;
+ }
+ }
+
+ ok = dsdb_gmsa_current_time(ldb, ¤t_time);
+ if (!ok) {
+ ret = ldb_operr(ldb);
+ goto out;
+ }
+
+ ret = gmsa_recalculate_managed_pwd(
+ tmp_ctx, ldb, msg, current_time, &gmsa_update, &return_pwd);
+ if (ret) {
+ goto out;
+ }
+
+ SMB_ASSERT(return_pwd.new_pwd != NULL);
+
+ {
+ DATA_BLOB packed_blob = {};
+
+ status = gmsa_pack_managed_pwd(
+ tmp_ctx,
+ return_pwd.new_pwd->buf,
+ return_pwd.prev_pwd != NULL ? return_pwd.prev_pwd->buf
+ : NULL,
+ return_pwd.query_interval,
+ return_pwd.unchanged_interval,
+ &packed_blob);
+ if (!NT_STATUS_IS_OK(status)) {
+ ret = ldb_operr(ldb);
+ goto out;
+ }
+
+ ret = ldb_msg_add_steal_value(msg,
+ "msDS-ManagedPassword",
+ &packed_blob);
+ if (ret) {
+ goto out;
+ }
+ }
+
+out:
+ TALLOC_FREE(tmp_ctx);
+ return ret;
+}
+
+int constructed_msds_managed_password(struct ldb_module *module,
+ struct ldb_message *msg,
+ enum ldb_scope scope,
+ struct ldb_request *parent,
+ struct ldb_reply *ares)
+{
+ return gmsa_managed_password(ldb_module_get_ctx(module),
+ msg,
+ parent,
+ ares);
+}
--- /dev/null
+/*
+ Unix SMB/CIFS implementation.
+ msDS-ManagedPassword attribute for Group Managed Service Accounts
+
+ Copyright (C) Catalyst.Net Ltd 2024
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef DSDB_SAMDB_LDB_MODULES_MANAGED_PWD_H
+#define DSDB_SAMDB_LDB_MODULES_MANAGED_PWD_H
+
+#include <ldb.h>
+
+struct ldb_module;
+int constructed_msds_managed_password(struct ldb_module *module,
+ struct ldb_message *msg,
+ enum ldb_scope scope,
+ struct ldb_request *parent,
+ struct ldb_reply *ares);
+
+#endif /* DSDB_SAMDB_LDB_MODULES_MANAGED_PWD_H */
#include "librpc/gen_ndr/ndr_misc.h"
#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "dsdb/samdb/samdb.h"
+#include "dsdb/samdb/ldb_modules/managed_pwd.h"
#include "dsdb/samdb/ldb_modules/util.h"
#include "auth/auth.h"
NULL
};
+static const char *managed_password_computed_attrs[] = {
+ "msDS-GroupMSAMembership",
+ "msDS-ManagedPasswordId",
+ "msDS-ManagedPasswordInterval",
+ "msDS-ManagedPasswordPreviousId",
+ "objectClass",
+ "objectSid",
+ "whenCreated",
+ NULL,
+};
+
/*
a list of attribute names that are hidden, but can be searched for
using another (non-hidden) name to produce the correct result
{ "msDS-UserPasswordExpiryTimeComputed", "userAccountControl", user_password_expiry_time_computed_attrs,
construct_msds_user_password_expiry_time_computed },
{ "msDS-ResultantPSO", "objectClass", resultant_pso_computed_attrs,
- construct_resultant_pso }
+ construct_resultant_pso },
+ {"msDS-ManagedPassword",
+ NULL,
+ managed_password_computed_attrs,
+ constructed_msds_managed_password},
};