LCOV - code coverage report
Current view: top level - source4/dsdb/samdb/ldb_modules - managed_pwd.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 53 68 77.9 %
Date: 2024-05-31 13:13:24 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    msDS-ManagedPassword attribute for Group Managed Service Accounts
       4             : 
       5             :    Copyright (C) Catalyst.Net Ltd 2024
       6             : 
       7             :    This program is free software: you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation, either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <https://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include <talloc.h>
      23             : #include <ldb.h>
      24             : #include <ldb_module.h>
      25             : #include <ldb_errors.h>
      26             : #include <ldb_private.h>
      27             : #include "lib/crypto/gmsa.h"
      28             : #include "lib/util/time.h"
      29             : #include "librpc/gen_ndr/ndr_gkdi.h"
      30             : #include "librpc/gen_ndr/ndr_gmsa.h"
      31             : #include "dsdb/gmsa/util.h"
      32             : #include "dsdb/samdb/ldb_modules/managed_pwd.h"
      33             : #include "dsdb/samdb/ldb_modules/util.h"
      34             : #include "dsdb/samdb/samdb.h"
      35             : 
      36             : #undef strcasecmp
      37             : 
      38        4895 : static int gmsa_managed_password(struct ldb_context *const ldb,
      39             :                                  struct ldb_message *msg,
      40             :                                  struct ldb_request *req,
      41             :                                  struct ldb_reply *ares)
      42             : {
      43        4895 :         TALLOC_CTX *tmp_ctx = NULL;
      44        4895 :         const struct dsdb_encrypted_connection_state *conn_state = NULL;
      45        4895 :         int ret = LDB_SUCCESS;
      46        4895 :         NTSTATUS status = NT_STATUS_OK;
      47          12 :         NTTIME current_time;
      48        4895 :         struct gmsa_update *gmsa_update = NULL;
      49          12 :         struct gmsa_return_pwd return_pwd;
      50          12 :         bool ok;
      51             : 
      52             :         /*
      53             :          * Prevent viewing msDS-ManagedPassword over an insecure connection. The
      54             :          * opaque is added in the ldap backend init.
      55             :          */
      56        4895 :         conn_state = ldb_get_opaque(
      57             :                 ldb, DSDB_OPAQUE_ENCRYPTED_CONNECTION_STATE_NAME);
      58        4895 :         if (conn_state != NULL && !conn_state->using_encrypted_connection) {
      59           4 :                 ret = dsdb_werror(ldb,
      60             :                                   LDB_ERR_OPERATIONS_ERROR,
      61             :                                   WERR_DS_CONFIDENTIALITY_REQUIRED,
      62             :                                   "Viewing msDS-ManagedPassword requires an "
      63             :                                   "encrypted connection");
      64           4 :                 goto out;
      65             :         }
      66             : 
      67             :         {
      68             :                 /* Is the account a Group Managed Service Account? */
      69        4891 :                 const bool is_gmsa = dsdb_account_is_gmsa(ldb, msg);
      70        4891 :                 if (!is_gmsa) {
      71             :                         /* It’s not a GMSA — we’re done here. */
      72        4835 :                         ret = LDB_SUCCESS;
      73        4835 :                         goto out;
      74             :                 }
      75             :         }
      76             : 
      77             :         {
      78          56 :                 bool am_rodc = true;
      79             : 
      80             :                 /* Are we operating as an RODC? */
      81          56 :                 ret = samdb_rodc(ldb, &am_rodc);
      82          56 :                 if (ret != LDB_SUCCESS) {
      83           0 :                         DBG_WARNING("unable to tell if we are an RODC\n");
      84           0 :                         goto out;
      85             :                 }
      86             : 
      87          56 :                 if (am_rodc) {
      88             :                         /* TODO: forward the request to a writable DC. */
      89           0 :                         ret = ldb_error(
      90             :                                 ldb,
      91             :                                 LDB_ERR_OPERATIONS_ERROR,
      92             :                                 "msDS-ManagedPassword may only be viewed on a "
      93             :                                 "writeable DC, not an RODC");
      94           0 :                         goto out;
      95             :                 }
      96             :         }
      97             : 
      98          56 :         tmp_ctx = talloc_new(msg);
      99          56 :         if (tmp_ctx == NULL) {
     100           0 :                 ret = ldb_oom(ldb);
     101           0 :                 goto out;
     102             :         }
     103             : 
     104             :         {
     105           0 :                 struct dom_sid account_sid;
     106          56 :                 bool allowed_to_view = false;
     107             : 
     108          56 :                 ret = samdb_result_dom_sid_buf(msg, "objectSid", &account_sid);
     109          56 :                 if (ret) {
     110           7 :                         goto out;
     111             :                 }
     112             : 
     113          56 :                 ret = gmsa_allowed_to_view_managed_password(
     114             :                         tmp_ctx, ldb, msg, &account_sid, &allowed_to_view);
     115          56 :                 if (ret) {
     116           0 :                         goto out;
     117             :                 }
     118             : 
     119          56 :                 if (!allowed_to_view) {
     120             :                         /* Sorry, you can’t view the password. */
     121           7 :                         ret = LDB_SUCCESS;
     122           7 :                         goto out;
     123             :                 }
     124             :         }
     125             : 
     126          49 :         ok = dsdb_gmsa_current_time(ldb, &current_time);
     127          49 :         if (!ok) {
     128           0 :                 ret = ldb_operr(ldb);
     129           0 :                 goto out;
     130             :         }
     131             : 
     132          49 :         ret = gmsa_recalculate_managed_pwd(
     133             :                 tmp_ctx, ldb, msg, current_time, &gmsa_update, &return_pwd);
     134          49 :         if (ret) {
     135           0 :                 goto out;
     136             :         }
     137             : 
     138          49 :         SMB_ASSERT(return_pwd.new_pwd != NULL);
     139             : 
     140          49 :         if (gmsa_update != NULL) {
     141             :                 /*
     142             :                  * Return a control to indicate to the LDAP server that it needs
     143             :                  * to refresh the physical passwords — that is, the keys in the
     144             :                  * database, and the ManagedPasswordId attribute.
     145             :                  */
     146          10 :                 ret = ldb_reply_add_control(ares,
     147             :                                             DSDB_CONTROL_GMSA_UPDATE_OID,
     148             :                                             false,
     149             :                                             gmsa_update);
     150          10 :                 if (ret) {
     151             :                         /* Ignore the error. */
     152           0 :                         ret = LDB_SUCCESS;
     153             :                 } else {
     154             :                         /*
     155             :                          * Link the lifetime of the GMSA update control to that
     156             :                          * of the reply.
     157             :                          */
     158          10 :                         talloc_steal(ares, gmsa_update);
     159             :                 }
     160             :         }
     161             : 
     162             :         {
     163          49 :                 DATA_BLOB packed_blob = {};
     164             : 
     165          37 :                 status = gmsa_pack_managed_pwd(
     166             :                         tmp_ctx,
     167          49 :                         return_pwd.new_pwd->buf,
     168          49 :                         return_pwd.prev_pwd != NULL ? return_pwd.prev_pwd->buf
     169             :                                                     : NULL,
     170             :                         return_pwd.query_interval,
     171             :                         return_pwd.unchanged_interval,
     172             :                         &packed_blob);
     173          49 :                 if (!NT_STATUS_IS_OK(status)) {
     174           0 :                         ret = ldb_operr(ldb);
     175           0 :                         goto out;
     176             :                 }
     177             : 
     178          49 :                 ret = ldb_msg_add_steal_value(msg,
     179             :                                               "msDS-ManagedPassword",
     180             :                                               &packed_blob);
     181          49 :                 if (ret) {
     182           0 :                         goto out;
     183             :                 }
     184             :         }
     185             : 
     186        4883 : out:
     187        4895 :         TALLOC_FREE(tmp_ctx);
     188        4895 :         return ret;
     189             : }
     190             : 
     191        4895 : int constructed_msds_managed_password(struct ldb_module *module,
     192             :                                       struct ldb_message *msg,
     193             :                                       enum ldb_scope scope,
     194             :                                       struct ldb_request *parent,
     195             :                                       struct ldb_reply *ares)
     196             : {
     197        4895 :         return gmsa_managed_password(ldb_module_get_ctx(module),
     198             :                                      msg,
     199             :                                      parent,
     200             :                                      ares);
     201             : }

Generated by: LCOV version 1.14