Coverage Report

Created: 2026-02-14 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/passdb/pdb_ldap_util.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS Implementation.
3
   LDAP protocol helper functions for SAMBA
4
   Copyright (C) Jean François Micouleau 1998
5
   Copyright (C) Gerald Carter      2001-2003
6
   Copyright (C) Shahms King      2001
7
   Copyright (C) Andrew Bartlett    2002-2003
8
   Copyright (C) Stefan (metze) Metzmacher  2002-2003
9
10
   This program is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 3 of the License, or
13
   (at your option) any later version.
14
15
   This program is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
   GNU General Public License for more details.
19
20
   You should have received a copy of the GNU General Public License
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
23
*/
24
25
#include "includes.h"
26
#include "smbldap.h"
27
#include "passdb.h"
28
#include "passdb/pdb_ldap_util.h"
29
#include "passdb/pdb_ldap_schema.h"
30
#include "libcli/security/dom_sid.h"
31
32
/**********************************************************************
33
 Add the account-policies below the sambaDomain object to LDAP,
34
*********************************************************************/
35
36
static NTSTATUS add_new_domain_account_policies(struct smbldap_state *ldap_state,
37
            const char *domain_name)
38
0
{
39
0
  NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
40
0
  int i, rc;
41
0
  uint32_t policy_default;
42
0
  const char *policy_attr = NULL;
43
0
  char *dn = NULL;
44
0
  LDAPMod **mods = NULL;
45
0
  char *escape_domain_name;
46
47
0
  DEBUG(3,("add_new_domain_account_policies: Adding new account policies for domain\n"));
48
49
0
  escape_domain_name = escape_rdn_val_string_alloc(domain_name);
50
0
  if (!escape_domain_name) {
51
0
    DEBUG(0, ("Out of memory!\n"));
52
0
    return NT_STATUS_NO_MEMORY;
53
0
  }
54
55
0
  if (asprintf(&dn, "%s=%s,%s",
56
0
    get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
57
0
    escape_domain_name, lp_ldap_suffix()) < 0) {
58
0
    SAFE_FREE(escape_domain_name);
59
0
    return NT_STATUS_NO_MEMORY;
60
0
  }
61
62
0
  SAFE_FREE(escape_domain_name);
63
64
0
  for (i=1; decode_account_policy_name(i) != NULL; i++) {
65
0
    char *val = NULL;
66
67
0
    policy_attr = get_account_policy_attr(i);
68
0
    if (!policy_attr) {
69
0
      DEBUG(0,("add_new_domain_account_policies: ops. no policy!\n"));
70
0
      continue;
71
0
    }
72
73
0
    if (!account_policy_get_default(i, &policy_default)) {
74
0
      DEBUG(0,("add_new_domain_account_policies: failed to get default account policy\n"));
75
0
      SAFE_FREE(dn);
76
0
      return ntstatus;
77
0
    }
78
79
0
    DEBUG(10,("add_new_domain_account_policies: adding \"%s\" with value: %d\n", policy_attr, policy_default));
80
81
0
    if (asprintf(&val, "%d", policy_default) < 0) {
82
0
      SAFE_FREE(dn);
83
0
      return NT_STATUS_NO_MEMORY;
84
0
    }
85
86
0
    smbldap_set_mod( &mods, LDAP_MOD_REPLACE, policy_attr, val);
87
88
0
    rc = smbldap_modify(ldap_state, dn, mods);
89
90
0
    SAFE_FREE(val);
91
92
0
    if (rc!=LDAP_SUCCESS) {
93
0
      char *ld_error = NULL;
94
0
      ldap_get_option(smbldap_get_ldap(ldap_state),
95
0
          LDAP_OPT_ERROR_STRING, &ld_error);
96
0
      DEBUG(1,("add_new_domain_account_policies: failed to add account policies to dn= %s with: %s\n\t%s\n",
97
0
        dn, ldap_err2string(rc),
98
0
        ld_error ? ld_error : "unknown"));
99
0
      SAFE_FREE(ld_error);
100
0
      SAFE_FREE(dn);
101
0
      ldap_mods_free(mods, True);
102
0
      return ntstatus;
103
0
    }
104
0
  }
105
106
0
  SAFE_FREE(dn);
107
0
  ldap_mods_free(mods, True);
108
109
0
  return NT_STATUS_OK;
110
0
}
111
112
/**********************************************************************
113
 Add the sambaDomain to LDAP, so we don't have to search for this stuff
114
 again.  This is a once-add operation for now.
115
116
 TODO:  Add other attributes, and allow modification.
117
*********************************************************************/
118
119
static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
120
                                    const char *domain_name)
121
0
{
122
0
  struct dom_sid_buf sid_string;
123
0
  fstring algorithmic_rid_base_string;
124
0
  char *filter = NULL;
125
0
  char *dn = NULL;
126
0
  LDAPMod **mods = NULL;
127
0
  int rc;
128
0
  LDAPMessage *result = NULL;
129
0
  int num_result;
130
0
  const char **attr_list;
131
0
  char *escape_domain_name;
132
133
  /* escape for filter */
134
0
  escape_domain_name = escape_ldap_string(talloc_tos(), domain_name);
135
0
  if (!escape_domain_name) {
136
0
    DEBUG(0, ("Out of memory!\n"));
137
0
    return NT_STATUS_NO_MEMORY;
138
0
  }
139
140
0
  if (asprintf(&filter, "(&(%s=%s)(objectclass=%s))",
141
0
    get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
142
0
      escape_domain_name, LDAP_OBJ_DOMINFO) < 0) {
143
0
    TALLOC_FREE(escape_domain_name);
144
0
    return NT_STATUS_NO_MEMORY;
145
0
  }
146
147
0
  TALLOC_FREE(escape_domain_name);
148
149
0
  attr_list = get_attr_list(NULL, dominfo_attr_list );
150
0
  rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result);
151
0
  TALLOC_FREE( attr_list );
152
0
  SAFE_FREE(filter);
153
154
0
  if (rc != LDAP_SUCCESS) {
155
0
    return NT_STATUS_UNSUCCESSFUL;
156
0
  }
157
158
0
  num_result = ldap_count_entries(smbldap_get_ldap(ldap_state), result);
159
160
0
  if (num_result > 1) {
161
0
    DEBUG (0, ("add_new_domain_info: More than domain with that name exists: bailing "
162
0
         "out!\n"));
163
0
    ldap_msgfree(result);
164
0
    return NT_STATUS_UNSUCCESSFUL;
165
0
  }
166
167
  /* Check if we need to add an entry */
168
0
  DEBUG(3,("add_new_domain_info: Adding new domain\n"));
169
170
  /* this time escape for DN */
171
0
  escape_domain_name = escape_rdn_val_string_alloc(domain_name);
172
0
  if (!escape_domain_name) {
173
0
    DEBUG(0, ("Out of memory!\n"));
174
0
    return NT_STATUS_NO_MEMORY;
175
0
  }
176
177
0
  if (asprintf(&dn, "%s=%s,%s",
178
0
         get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
179
0
         escape_domain_name, lp_ldap_suffix()) < 0) {
180
0
    SAFE_FREE(escape_domain_name);
181
0
    return NT_STATUS_NO_MEMORY;
182
0
  }
183
184
0
  SAFE_FREE(escape_domain_name);
185
186
  /* Free original search */
187
0
  ldap_msgfree(result);
188
189
  /* make the changes - the entry *must* not already have samba
190
   * attributes */
191
192
0
  smbldap_set_mod(&mods, LDAP_MOD_ADD,
193
0
      get_attr_key2string(dominfo_attr_list,
194
0
              LDAP_ATTR_DOMAIN),
195
0
      domain_name);
196
197
  /* If we don't have an entry, then ask secrets.tdb for what it thinks.
198
     It may choose to make it up */
199
200
0
  smbldap_set_mod(&mods, LDAP_MOD_ADD,
201
0
      get_attr_key2string(dominfo_attr_list,
202
0
              LDAP_ATTR_DOM_SID),
203
0
      dom_sid_str_buf(get_global_sam_sid(), &sid_string));
204
205
0
  slprintf(algorithmic_rid_base_string,
206
0
     sizeof(algorithmic_rid_base_string) - 1, "%i",
207
0
     algorithmic_rid_base());
208
0
  smbldap_set_mod(&mods, LDAP_MOD_ADD,
209
0
      get_attr_key2string(dominfo_attr_list,
210
0
              LDAP_ATTR_ALGORITHMIC_RID_BASE),
211
0
      algorithmic_rid_base_string);
212
0
  smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO);
213
214
  /* add the sambaNextUserRid attributes. */
215
216
0
  {
217
0
    uint32_t rid = BASE_RID;
218
0
    fstring rid_str;
219
220
0
    fstr_sprintf( rid_str, "%i", rid );
221
0
    DEBUG(10,("add_new_domain_info: setting next available user rid [%s]\n", rid_str));
222
0
    smbldap_set_mod(&mods, LDAP_MOD_ADD,
223
0
      get_attr_key2string(dominfo_attr_list,
224
0
              LDAP_ATTR_NEXT_USERRID),
225
0
      rid_str);
226
0
        }
227
228
229
0
  rc = smbldap_add(ldap_state, dn, mods);
230
231
0
  if (rc!=LDAP_SUCCESS) {
232
0
    char *ld_error = NULL;
233
0
    ldap_get_option(smbldap_get_ldap(ldap_state),
234
0
        LDAP_OPT_ERROR_STRING, &ld_error);
235
0
    DEBUG(1,("add_new_domain_info: failed to add domain dn= %s with: %s\n\t%s\n",
236
0
       dn, ldap_err2string(rc),
237
0
       ld_error?ld_error:"unknown"));
238
0
    SAFE_FREE(ld_error);
239
0
    SAFE_FREE(dn);
240
0
    ldap_mods_free(mods, True);
241
0
    return NT_STATUS_UNSUCCESSFUL;
242
0
  }
243
244
0
  DEBUG(2,("add_new_domain_info: added: domain = %s in the LDAP database\n", domain_name));
245
0
  ldap_mods_free(mods, True);
246
0
  SAFE_FREE(dn);
247
0
  return NT_STATUS_OK;
248
0
}
249
250
/**********************************************************************
251
Search for the domain info entry
252
*********************************************************************/
253
254
NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
255
                                    LDAPMessage ** result, const char *domain_name,
256
                                    bool try_add)
257
0
{
258
0
  NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
259
0
  char *filter = NULL;
260
0
  int rc;
261
0
  const char **attr_list;
262
0
  int count;
263
0
  char *escape_domain_name;
264
265
0
  escape_domain_name = escape_ldap_string(talloc_tos(), domain_name);
266
0
  if (!escape_domain_name) {
267
0
    DEBUG(0, ("Out of memory!\n"));
268
0
    return NT_STATUS_NO_MEMORY;
269
0
  }
270
271
0
  if (asprintf(&filter, "(&(objectClass=%s)(%s=%s))",
272
0
    LDAP_OBJ_DOMINFO,
273
0
    get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
274
0
    escape_domain_name) < 0) {
275
0
    TALLOC_FREE(escape_domain_name);
276
0
    return NT_STATUS_NO_MEMORY;
277
0
  }
278
279
0
  TALLOC_FREE(escape_domain_name);
280
281
0
  DEBUG(2, ("smbldap_search_domain_info: Searching for:[%s]\n", filter));
282
283
0
  attr_list = get_attr_list( NULL, dominfo_attr_list );
284
0
  rc = smbldap_search_suffix(ldap_state, filter, attr_list , result);
285
0
  TALLOC_FREE( attr_list );
286
287
0
  if (rc != LDAP_SUCCESS) {
288
0
    DEBUG(2,("smbldap_search_domain_info: Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
289
0
    DEBUG(2,("smbldap_search_domain_info: Query was: %s, %s\n", lp_ldap_suffix(), filter));
290
0
    goto failed;
291
0
  }
292
293
0
  SAFE_FREE(filter);
294
295
0
  count = ldap_count_entries(smbldap_get_ldap(ldap_state), *result);
296
297
0
  if (count == 1) {
298
0
    return NT_STATUS_OK;
299
0
  }
300
301
0
  ldap_msgfree(*result);
302
0
  *result = NULL;
303
304
0
  if (count < 1) {
305
306
0
    DEBUG(3, ("smbldap_search_domain_info: Got no domain info entries for domain\n"));
307
308
0
    if (!try_add)
309
0
      goto failed;
310
311
0
    status = add_new_domain_info(ldap_state, domain_name);
312
0
    if (!NT_STATUS_IS_OK(status)) {
313
0
      DEBUG(0, ("smbldap_search_domain_info: Adding domain info for %s failed with %s\n",
314
0
        domain_name, nt_errstr(status)));
315
0
      goto failed;
316
0
    }
317
318
0
    status = add_new_domain_account_policies(ldap_state, domain_name);
319
0
    if (!NT_STATUS_IS_OK(status)) {
320
0
      DEBUG(0, ("smbldap_search_domain_info: Adding domain account policies for %s failed with %s\n",
321
0
        domain_name, nt_errstr(status)));
322
0
      goto failed;
323
0
    }
324
325
0
    return smbldap_search_domain_info(ldap_state, result, domain_name, False);
326
327
0
  }
328
329
0
  if (count > 1 ) {
330
331
0
    DEBUG(0, ("smbldap_search_domain_info: Got too many (%d) domain info entries for domain %s\n",
332
0
        count, domain_name));
333
0
    goto failed;
334
0
  }
335
336
0
failed:
337
0
  return status;
338
0
}