tevent: expose tevent_context_init_ops
[Samba/gebeck_regimport.git] / source3 / passdb / pdb_ldap.c
blob1ebfa15029899ed0989d966bf4e247262576ace0
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 Copyright (C) Simo Sorce 2006
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 /* TODO:
27 * persistent connections: if using NSS LDAP, many connections are made
28 * however, using only one within Samba would be nice
30 * Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
32 * Other LDAP based login attributes: accountExpires, etc.
33 * (should be the domain of Samba proper, but the sam_password/struct samu
34 * structures don't have fields for some of these attributes)
36 * SSL is done, but can't get the certificate based authentication to work
37 * against on my test platform (Linux 2.4, OpenLDAP 2.x)
40 /* NOTE: this will NOT work against an Active Directory server
41 * due to the fact that the two password fields cannot be retrieved
42 * from a server; recommend using security = domain in this situation
43 * and/or winbind
46 #include "includes.h"
47 #include "passdb.h"
48 #include "../libcli/auth/libcli_auth.h"
49 #include "secrets.h"
50 #include "idmap_cache.h"
51 #include "../libcli/security/security.h"
52 #include "../lib/util/util_pw.h"
53 #include "lib/winbind_util.h"
54 #include "librpc/gen_ndr/idmap.h"
56 #undef DBGC_CLASS
57 #define DBGC_CLASS DBGC_PASSDB
59 #include <lber.h>
60 #include <ldap.h>
63 #include "smbldap.h"
64 #include "passdb/pdb_ldap.h"
65 #include "passdb/pdb_nds.h"
66 #include "passdb/pdb_ipa.h"
67 #include "passdb/pdb_ldap_util.h"
68 #include "passdb/pdb_ldap_schema.h"
70 /**********************************************************************
71 Simple helper function to make stuff better readable
72 **********************************************************************/
74 LDAP *priv2ld(struct ldapsam_privates *priv)
76 return priv->smbldap_state->ldap_struct;
79 /**********************************************************************
80 Get the attribute name given a user schame version.
81 **********************************************************************/
83 static const char* get_userattr_key2string( int schema_ver, int key )
85 switch ( schema_ver ) {
86 case SCHEMAVER_SAMBAACCOUNT:
87 return get_attr_key2string( attrib_map_v22, key );
89 case SCHEMAVER_SAMBASAMACCOUNT:
90 return get_attr_key2string( attrib_map_v30, key );
92 default:
93 DEBUG(0,("get_userattr_key2string: unknown schema version specified\n"));
94 break;
96 return NULL;
99 /**********************************************************************
100 Return the list of attribute names given a user schema version.
101 **********************************************************************/
103 const char** get_userattr_list( TALLOC_CTX *mem_ctx, int schema_ver )
105 switch ( schema_ver ) {
106 case SCHEMAVER_SAMBAACCOUNT:
107 return get_attr_list( mem_ctx, attrib_map_v22 );
109 case SCHEMAVER_SAMBASAMACCOUNT:
110 return get_attr_list( mem_ctx, attrib_map_v30 );
111 default:
112 DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
113 break;
116 return NULL;
119 /**************************************************************************
120 Return the list of attribute names to delete given a user schema version.
121 **************************************************************************/
123 static const char** get_userattr_delete_list( TALLOC_CTX *mem_ctx,
124 int schema_ver )
126 switch ( schema_ver ) {
127 case SCHEMAVER_SAMBAACCOUNT:
128 return get_attr_list( mem_ctx,
129 attrib_map_to_delete_v22 );
131 case SCHEMAVER_SAMBASAMACCOUNT:
132 return get_attr_list( mem_ctx,
133 attrib_map_to_delete_v30 );
134 default:
135 DEBUG(0,("get_userattr_delete_list: unknown schema version specified!\n"));
136 break;
139 return NULL;
143 /*******************************************************************
144 Generate the LDAP search filter for the objectclass based on the
145 version of the schema we are using.
146 ******************************************************************/
148 static const char* get_objclass_filter( int schema_ver )
150 fstring objclass_filter;
151 char *result;
153 switch( schema_ver ) {
154 case SCHEMAVER_SAMBAACCOUNT:
155 fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT );
156 break;
157 case SCHEMAVER_SAMBASAMACCOUNT:
158 fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT );
159 break;
160 default:
161 DEBUG(0,("get_objclass_filter: Invalid schema version specified!\n"));
162 objclass_filter[0] = '\0';
163 break;
166 result = talloc_strdup(talloc_tos(), objclass_filter);
167 SMB_ASSERT(result != NULL);
168 return result;
171 /*****************************************************************
172 Scan a sequence number off OpenLDAP's syncrepl contextCSN
173 ******************************************************************/
175 static NTSTATUS ldapsam_get_seq_num(struct pdb_methods *my_methods, time_t *seq_num)
177 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
178 NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
179 LDAPMessage *msg = NULL;
180 LDAPMessage *entry = NULL;
181 TALLOC_CTX *mem_ctx;
182 char **values = NULL;
183 int rc, num_result, num_values, rid;
184 char *suffix = NULL;
185 char *tok;
186 const char *p;
187 const char **attrs;
189 /* Unfortunatly there is no proper way to detect syncrepl-support in
190 * smbldap_connect_system(). The syncrepl OIDs are submitted for publication
191 * but do not show up in the root-DSE yet. Neither we can query the
192 * subschema-context for the syncProviderSubentry or syncConsumerSubentry
193 * objectclass. Currently we require lp_ldap_suffix() to show up as
194 * namingContext. - Guenther
197 if (!lp_parm_bool(-1, "ldapsam", "syncrepl_seqnum", False)) {
198 return ntstatus;
201 if (!seq_num) {
202 DEBUG(3,("ldapsam_get_seq_num: no sequence_number\n"));
203 return ntstatus;
206 if (!smbldap_has_naming_context(ldap_state->smbldap_state->ldap_struct, lp_ldap_suffix())) {
207 DEBUG(3,("ldapsam_get_seq_num: DIT not configured to hold %s "
208 "as top-level namingContext\n", lp_ldap_suffix()));
209 return ntstatus;
212 mem_ctx = talloc_init("ldapsam_get_seq_num");
214 if (mem_ctx == NULL)
215 return NT_STATUS_NO_MEMORY;
217 if ((attrs = talloc_array(mem_ctx, const char *, 2)) == NULL) {
218 ntstatus = NT_STATUS_NO_MEMORY;
219 goto done;
222 /* if we got a syncrepl-rid (up to three digits long) we speak with a consumer */
223 rid = lp_parm_int(-1, "ldapsam", "syncrepl_rid", -1);
224 if (rid > 0) {
226 /* consumer syncreplCookie: */
227 /* csn=20050126161620Z#0000001#00#00000 */
228 attrs[0] = talloc_strdup(mem_ctx, "syncreplCookie");
229 attrs[1] = NULL;
230 suffix = talloc_asprintf(mem_ctx,
231 "cn=syncrepl%d,%s", rid, lp_ldap_suffix());
232 if (!suffix) {
233 ntstatus = NT_STATUS_NO_MEMORY;
234 goto done;
236 } else {
238 /* provider contextCSN */
239 /* 20050126161620Z#000009#00#000000 */
240 attrs[0] = talloc_strdup(mem_ctx, "contextCSN");
241 attrs[1] = NULL;
242 suffix = talloc_asprintf(mem_ctx,
243 "cn=ldapsync,%s", lp_ldap_suffix());
245 if (!suffix) {
246 ntstatus = NT_STATUS_NO_MEMORY;
247 goto done;
251 rc = smbldap_search(ldap_state->smbldap_state, suffix,
252 LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &msg);
254 if (rc != LDAP_SUCCESS) {
255 goto done;
258 num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg);
259 if (num_result != 1) {
260 DEBUG(3,("ldapsam_get_seq_num: Expected one entry, got %d\n", num_result));
261 goto done;
264 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg);
265 if (entry == NULL) {
266 DEBUG(3,("ldapsam_get_seq_num: Could not retrieve entry\n"));
267 goto done;
270 values = ldap_get_values(ldap_state->smbldap_state->ldap_struct, entry, attrs[0]);
271 if (values == NULL) {
272 DEBUG(3,("ldapsam_get_seq_num: no values\n"));
273 goto done;
276 num_values = ldap_count_values(values);
277 if (num_values == 0) {
278 DEBUG(3,("ldapsam_get_seq_num: not a single value\n"));
279 goto done;
282 p = values[0];
283 if (!next_token_talloc(mem_ctx, &p, &tok, "#")) {
284 DEBUG(0,("ldapsam_get_seq_num: failed to parse sequence number\n"));
285 goto done;
288 p = tok;
289 if (!strncmp(p, "csn=", strlen("csn=")))
290 p += strlen("csn=");
292 DEBUG(10,("ldapsam_get_seq_num: got %s: %s\n", attrs[0], p));
294 *seq_num = generalized_to_unix_time(p);
296 /* very basic sanity check */
297 if (*seq_num <= 0) {
298 DEBUG(3,("ldapsam_get_seq_num: invalid sequence number: %d\n",
299 (int)*seq_num));
300 goto done;
303 ntstatus = NT_STATUS_OK;
305 done:
306 if (values != NULL)
307 ldap_value_free(values);
308 if (msg != NULL)
309 ldap_msgfree(msg);
310 if (mem_ctx)
311 talloc_destroy(mem_ctx);
313 return ntstatus;
316 /*******************************************************************
317 Run the search by name.
318 ******************************************************************/
320 int ldapsam_search_suffix_by_name(struct ldapsam_privates *ldap_state,
321 const char *user,
322 LDAPMessage ** result,
323 const char **attr)
325 char *filter = NULL;
326 char *escape_user = escape_ldap_string(talloc_tos(), user);
327 int ret = -1;
329 if (!escape_user) {
330 return LDAP_NO_MEMORY;
334 * in the filter expression, replace %u with the real name
335 * so in ldap filter, %u MUST exist :-)
337 filter = talloc_asprintf(talloc_tos(), "(&%s%s)", "(uid=%u)",
338 get_objclass_filter(ldap_state->schema_ver));
339 if (!filter) {
340 TALLOC_FREE(escape_user);
341 return LDAP_NO_MEMORY;
344 * have to use this here because $ is filtered out
345 * in string_sub
348 filter = talloc_all_string_sub(talloc_tos(),
349 filter, "%u", escape_user);
350 TALLOC_FREE(escape_user);
351 if (!filter) {
352 return LDAP_NO_MEMORY;
355 ret = smbldap_search_suffix(ldap_state->smbldap_state,
356 filter, attr, result);
357 TALLOC_FREE(filter);
358 return ret;
361 /*******************************************************************
362 Run the search by rid.
363 ******************************************************************/
365 static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state,
366 uint32_t rid, LDAPMessage ** result,
367 const char **attr)
369 char *filter = NULL;
370 int rc;
372 filter = talloc_asprintf(talloc_tos(), "(&(rid=%i)%s)", rid,
373 get_objclass_filter(ldap_state->schema_ver));
374 if (!filter) {
375 return LDAP_NO_MEMORY;
378 rc = smbldap_search_suffix(ldap_state->smbldap_state,
379 filter, attr, result);
380 TALLOC_FREE(filter);
381 return rc;
384 /*******************************************************************
385 Run the search by SID.
386 ******************************************************************/
388 static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state,
389 const struct dom_sid *sid, LDAPMessage ** result,
390 const char **attr)
392 char *filter = NULL;
393 int rc;
394 fstring sid_string;
396 filter = talloc_asprintf(talloc_tos(), "(&(%s=%s)%s)",
397 get_userattr_key2string(ldap_state->schema_ver,
398 LDAP_ATTR_USER_SID),
399 sid_to_fstring(sid_string, sid),
400 get_objclass_filter(ldap_state->schema_ver));
401 if (!filter) {
402 return LDAP_NO_MEMORY;
405 rc = smbldap_search_suffix(ldap_state->smbldap_state,
406 filter, attr, result);
408 TALLOC_FREE(filter);
409 return rc;
412 /*******************************************************************
413 Delete complete object or objectclass and attrs from
414 object found in search_result depending on lp_ldap_delete_dn
415 ******************************************************************/
417 static int ldapsam_delete_entry(struct ldapsam_privates *priv,
418 TALLOC_CTX *mem_ctx,
419 LDAPMessage *entry,
420 const char *objectclass,
421 const char **attrs)
423 LDAPMod **mods = NULL;
424 char *name;
425 const char *dn;
426 BerElement *ptr = NULL;
428 dn = smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry);
429 if (dn == NULL) {
430 return LDAP_NO_MEMORY;
433 if (lp_ldap_delete_dn()) {
434 return smbldap_delete(priv->smbldap_state, dn);
437 /* Ok, delete only the SAM attributes */
439 for (name = ldap_first_attribute(priv2ld(priv), entry, &ptr);
440 name != NULL;
441 name = ldap_next_attribute(priv2ld(priv), entry, ptr)) {
442 const char **attrib;
444 /* We are only allowed to delete the attributes that
445 really exist. */
447 for (attrib = attrs; *attrib != NULL; attrib++) {
448 if (strequal(*attrib, name)) {
449 DEBUG(10, ("ldapsam_delete_entry: deleting "
450 "attribute %s\n", name));
451 smbldap_set_mod(&mods, LDAP_MOD_DELETE, name,
452 NULL);
455 ldap_memfree(name);
458 if (ptr != NULL) {
459 ber_free(ptr, 0);
462 smbldap_set_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
463 talloc_autofree_ldapmod(mem_ctx, mods);
465 return smbldap_modify(priv->smbldap_state, dn, mods);
468 static time_t ldapsam_get_entry_timestamp( struct ldapsam_privates *ldap_state, LDAPMessage * entry)
470 char *temp;
471 struct tm tm;
473 temp = smbldap_talloc_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
474 get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP),
475 talloc_tos());
476 if (!temp) {
477 return (time_t) 0;
480 if ( !strptime(temp, "%Y%m%d%H%M%SZ", &tm)) {
481 DEBUG(2,("ldapsam_get_entry_timestamp: strptime failed on: %s\n",
482 (char*)temp));
483 TALLOC_FREE(temp);
484 return (time_t) 0;
486 TALLOC_FREE(temp);
487 tzset();
488 return timegm(&tm);
491 /**********************************************************************
492 Initialize struct samu from an LDAP query.
493 (Based on init_sam_from_buffer in pdb_tdb.c)
494 *********************************************************************/
496 static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state,
497 struct samu * sampass,
498 LDAPMessage * entry)
500 time_t logon_time,
501 logoff_time,
502 kickoff_time,
503 pass_last_set_time,
504 pass_can_change_time,
505 ldap_entry_time,
506 bad_password_time;
507 char *username = NULL,
508 *domain = NULL,
509 *nt_username = NULL,
510 *fullname = NULL,
511 *homedir = NULL,
512 *dir_drive = NULL,
513 *logon_script = NULL,
514 *profile_path = NULL,
515 *acct_desc = NULL,
516 *workstations = NULL,
517 *munged_dial = NULL;
518 uint32_t user_rid;
519 uint8 smblmpwd[LM_HASH_LEN],
520 smbntpwd[NT_HASH_LEN];
521 bool use_samba_attrs = True;
522 uint32_t acct_ctrl = 0;
523 uint16_t logon_divs;
524 uint16_t bad_password_count = 0,
525 logon_count = 0;
526 uint32_t hours_len;
527 uint8 hours[MAX_HOURS_LEN];
528 char *temp = NULL;
529 struct login_cache cache_entry;
530 uint32_t pwHistLen;
531 bool expand_explicit = lp_passdb_expand_explicit();
532 bool ret = false;
533 TALLOC_CTX *ctx = talloc_init("init_sam_from_ldap");
535 if (!ctx) {
536 return false;
538 if (sampass == NULL || ldap_state == NULL || entry == NULL) {
539 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
540 goto fn_exit;
543 if (priv2ld(ldap_state) == NULL) {
544 DEBUG(0, ("init_sam_from_ldap: ldap_state->smbldap_state->"
545 "ldap_struct is NULL!\n"));
546 goto fn_exit;
549 if (!(username = smbldap_talloc_first_attribute(priv2ld(ldap_state),
550 entry,
551 "uid",
552 ctx))) {
553 DEBUG(1, ("init_sam_from_ldap: No uid attribute found for "
554 "this user!\n"));
555 goto fn_exit;
558 DEBUG(2, ("init_sam_from_ldap: Entry found for user: %s\n", username));
560 nt_username = talloc_strdup(ctx, username);
561 if (!nt_username) {
562 goto fn_exit;
565 domain = talloc_strdup(ctx, ldap_state->domain_name);
566 if (!domain) {
567 goto fn_exit;
570 pdb_set_username(sampass, username, PDB_SET);
572 pdb_set_domain(sampass, domain, PDB_DEFAULT);
573 pdb_set_nt_username(sampass, nt_username, PDB_SET);
575 /* deal with different attributes between the schema first */
577 if ( ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ) {
578 if ((temp = smbldap_talloc_single_attribute(
579 ldap_state->smbldap_state->ldap_struct,
580 entry,
581 get_userattr_key2string(ldap_state->schema_ver,
582 LDAP_ATTR_USER_SID),
583 ctx))!=NULL) {
584 pdb_set_user_sid_from_string(sampass, temp, PDB_SET);
586 } else {
587 if ((temp = smbldap_talloc_single_attribute(
588 ldap_state->smbldap_state->ldap_struct,
589 entry,
590 get_userattr_key2string(ldap_state->schema_ver,
591 LDAP_ATTR_USER_RID),
592 ctx))!=NULL) {
593 user_rid = (uint32_t)atol(temp);
594 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
598 if (IS_SAM_DEFAULT(sampass, PDB_USERSID)) {
599 DEBUG(1, ("init_sam_from_ldap: no %s or %s attribute found for this user %s\n",
600 get_userattr_key2string(ldap_state->schema_ver,
601 LDAP_ATTR_USER_SID),
602 get_userattr_key2string(ldap_state->schema_ver,
603 LDAP_ATTR_USER_RID),
604 username));
605 return False;
608 temp = smbldap_talloc_single_attribute(
609 ldap_state->smbldap_state->ldap_struct,
610 entry,
611 get_userattr_key2string(ldap_state->schema_ver,
612 LDAP_ATTR_PWD_LAST_SET),
613 ctx);
614 if (temp) {
615 pass_last_set_time = (time_t) atol(temp);
616 pdb_set_pass_last_set_time(sampass,
617 pass_last_set_time, PDB_SET);
620 temp = smbldap_talloc_single_attribute(
621 ldap_state->smbldap_state->ldap_struct,
622 entry,
623 get_userattr_key2string(ldap_state->schema_ver,
624 LDAP_ATTR_LOGON_TIME),
625 ctx);
626 if (temp) {
627 logon_time = (time_t) atol(temp);
628 pdb_set_logon_time(sampass, logon_time, PDB_SET);
631 temp = smbldap_talloc_single_attribute(
632 ldap_state->smbldap_state->ldap_struct,
633 entry,
634 get_userattr_key2string(ldap_state->schema_ver,
635 LDAP_ATTR_LOGOFF_TIME),
636 ctx);
637 if (temp) {
638 logoff_time = (time_t) atol(temp);
639 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
642 temp = smbldap_talloc_single_attribute(
643 ldap_state->smbldap_state->ldap_struct,
644 entry,
645 get_userattr_key2string(ldap_state->schema_ver,
646 LDAP_ATTR_KICKOFF_TIME),
647 ctx);
648 if (temp) {
649 kickoff_time = (time_t) atol(temp);
650 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
653 temp = smbldap_talloc_single_attribute(
654 ldap_state->smbldap_state->ldap_struct,
655 entry,
656 get_userattr_key2string(ldap_state->schema_ver,
657 LDAP_ATTR_PWD_CAN_CHANGE),
658 ctx);
659 if (temp) {
660 pass_can_change_time = (time_t) atol(temp);
661 pdb_set_pass_can_change_time(sampass,
662 pass_can_change_time, PDB_SET);
665 /* recommend that 'gecos' and 'displayName' should refer to the same
666 * attribute OID. userFullName depreciated, only used by Samba
667 * primary rules of LDAP: don't make a new attribute when one is already defined
668 * that fits your needs; using cn then displayName rather than 'userFullName'
671 fullname = smbldap_talloc_single_attribute(
672 ldap_state->smbldap_state->ldap_struct,
673 entry,
674 get_userattr_key2string(ldap_state->schema_ver,
675 LDAP_ATTR_DISPLAY_NAME),
676 ctx);
677 if (fullname) {
678 pdb_set_fullname(sampass, fullname, PDB_SET);
679 } else {
680 fullname = smbldap_talloc_single_attribute(
681 ldap_state->smbldap_state->ldap_struct,
682 entry,
683 get_userattr_key2string(ldap_state->schema_ver,
684 LDAP_ATTR_CN),
685 ctx);
686 if (fullname) {
687 pdb_set_fullname(sampass, fullname, PDB_SET);
691 dir_drive = smbldap_talloc_single_attribute(
692 ldap_state->smbldap_state->ldap_struct,
693 entry,
694 get_userattr_key2string(ldap_state->schema_ver,
695 LDAP_ATTR_HOME_DRIVE),
696 ctx);
697 if (dir_drive) {
698 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
699 } else {
700 pdb_set_dir_drive( sampass, lp_logon_drive(), PDB_DEFAULT );
703 homedir = smbldap_talloc_single_attribute(
704 ldap_state->smbldap_state->ldap_struct,
705 entry,
706 get_userattr_key2string(ldap_state->schema_ver,
707 LDAP_ATTR_HOME_PATH),
708 ctx);
709 if (homedir) {
710 if (expand_explicit) {
711 homedir = talloc_sub_basic(ctx,
712 username,
713 domain,
714 homedir);
715 if (!homedir) {
716 goto fn_exit;
719 pdb_set_homedir(sampass, homedir, PDB_SET);
720 } else {
721 pdb_set_homedir(sampass,
722 talloc_sub_basic(ctx, username, domain,
723 lp_logon_home()),
724 PDB_DEFAULT);
727 logon_script = smbldap_talloc_single_attribute(
728 ldap_state->smbldap_state->ldap_struct,
729 entry,
730 get_userattr_key2string(ldap_state->schema_ver,
731 LDAP_ATTR_LOGON_SCRIPT),
732 ctx);
733 if (logon_script) {
734 if (expand_explicit) {
735 logon_script = talloc_sub_basic(ctx,
736 username,
737 domain,
738 logon_script);
739 if (!logon_script) {
740 goto fn_exit;
743 pdb_set_logon_script(sampass, logon_script, PDB_SET);
744 } else {
745 pdb_set_logon_script(sampass,
746 talloc_sub_basic(ctx, username, domain,
747 lp_logon_script()),
748 PDB_DEFAULT );
751 profile_path = smbldap_talloc_single_attribute(
752 ldap_state->smbldap_state->ldap_struct,
753 entry,
754 get_userattr_key2string(ldap_state->schema_ver,
755 LDAP_ATTR_PROFILE_PATH),
756 ctx);
757 if (profile_path) {
758 if (expand_explicit) {
759 profile_path = talloc_sub_basic(ctx,
760 username,
761 domain,
762 profile_path);
763 if (!profile_path) {
764 goto fn_exit;
767 pdb_set_profile_path(sampass, profile_path, PDB_SET);
768 } else {
769 pdb_set_profile_path(sampass,
770 talloc_sub_basic(ctx, username, domain,
771 lp_logon_path()),
772 PDB_DEFAULT );
775 acct_desc = smbldap_talloc_single_attribute(
776 ldap_state->smbldap_state->ldap_struct,
777 entry,
778 get_userattr_key2string(ldap_state->schema_ver,
779 LDAP_ATTR_DESC),
780 ctx);
781 if (acct_desc) {
782 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
785 workstations = smbldap_talloc_single_attribute(
786 ldap_state->smbldap_state->ldap_struct,
787 entry,
788 get_userattr_key2string(ldap_state->schema_ver,
789 LDAP_ATTR_USER_WKS),
790 ctx);
791 if (workstations) {
792 pdb_set_workstations(sampass, workstations, PDB_SET);
795 munged_dial = smbldap_talloc_single_attribute(
796 ldap_state->smbldap_state->ldap_struct,
797 entry,
798 get_userattr_key2string(ldap_state->schema_ver,
799 LDAP_ATTR_MUNGED_DIAL),
800 ctx);
801 if (munged_dial) {
802 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
805 /* FIXME: hours stuff should be cleaner */
807 logon_divs = 168;
808 hours_len = 21;
809 memset(hours, 0xff, hours_len);
811 if (ldap_state->is_nds_ldap) {
812 char *user_dn;
813 size_t pwd_len;
814 char clear_text_pw[512];
816 /* Make call to Novell eDirectory ldap extension to get clear text password.
817 NOTE: This will only work if we have an SSL connection to eDirectory. */
818 user_dn = smbldap_talloc_dn(ctx, ldap_state->smbldap_state->ldap_struct, entry);
819 if (user_dn != NULL) {
820 DEBUG(3, ("init_sam_from_ldap: smbldap_talloc_dn(ctx, %s) returned '%s'\n", username, user_dn));
822 pwd_len = sizeof(clear_text_pw);
823 if (pdb_nds_get_password(ldap_state->smbldap_state, user_dn, &pwd_len, clear_text_pw) == LDAP_SUCCESS) {
824 nt_lm_owf_gen(clear_text_pw, smbntpwd, smblmpwd);
825 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET)) {
826 TALLOC_FREE(user_dn);
827 return False;
829 ZERO_STRUCT(smblmpwd);
830 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET)) {
831 TALLOC_FREE(user_dn);
832 return False;
834 ZERO_STRUCT(smbntpwd);
835 use_samba_attrs = False;
838 TALLOC_FREE(user_dn);
840 } else {
841 DEBUG(0, ("init_sam_from_ldap: failed to get user_dn for '%s'\n", username));
845 if (use_samba_attrs) {
846 temp = smbldap_talloc_single_attribute(
847 ldap_state->smbldap_state->ldap_struct,
848 entry,
849 get_userattr_key2string(ldap_state->schema_ver,
850 LDAP_ATTR_LMPW),
851 ctx);
852 if (temp) {
853 pdb_gethexpwd(temp, smblmpwd);
854 memset((char *)temp, '\0', strlen(temp)+1);
855 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET)) {
856 goto fn_exit;
858 ZERO_STRUCT(smblmpwd);
861 temp = smbldap_talloc_single_attribute(
862 ldap_state->smbldap_state->ldap_struct,
863 entry,
864 get_userattr_key2string(ldap_state->schema_ver,
865 LDAP_ATTR_NTPW),
866 ctx);
867 if (temp) {
868 pdb_gethexpwd(temp, smbntpwd);
869 memset((char *)temp, '\0', strlen(temp)+1);
870 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET)) {
871 goto fn_exit;
873 ZERO_STRUCT(smbntpwd);
877 pwHistLen = 0;
879 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
880 if (pwHistLen > 0){
881 uint8 *pwhist = NULL;
882 int i;
883 char *history_string = talloc_array(ctx, char,
884 MAX_PW_HISTORY_LEN*64);
886 if (!history_string) {
887 goto fn_exit;
890 pwHistLen = MIN(pwHistLen, MAX_PW_HISTORY_LEN);
892 pwhist = talloc_array(ctx, uint8,
893 pwHistLen * PW_HISTORY_ENTRY_LEN);
894 if (pwhist == NULL) {
895 DEBUG(0, ("init_sam_from_ldap: talloc failed!\n"));
896 goto fn_exit;
898 memset(pwhist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
900 if (smbldap_get_single_attribute(
901 ldap_state->smbldap_state->ldap_struct,
902 entry,
903 get_userattr_key2string(ldap_state->schema_ver,
904 LDAP_ATTR_PWD_HISTORY),
905 history_string,
906 MAX_PW_HISTORY_LEN*64)) {
907 bool hex_failed = false;
908 for (i = 0; i < pwHistLen; i++){
909 /* Get the 16 byte salt. */
910 if (!pdb_gethexpwd(&history_string[i*64],
911 &pwhist[i*PW_HISTORY_ENTRY_LEN])) {
912 hex_failed = true;
913 break;
915 /* Get the 16 byte MD5 hash of salt+passwd. */
916 if (!pdb_gethexpwd(&history_string[(i*64)+32],
917 &pwhist[(i*PW_HISTORY_ENTRY_LEN)+
918 PW_HISTORY_SALT_LEN])) {
919 hex_failed = True;
920 break;
923 if (hex_failed) {
924 DEBUG(2,("init_sam_from_ldap: Failed to get password history for user %s\n",
925 username));
926 memset(pwhist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
929 if (!pdb_set_pw_history(sampass, pwhist, pwHistLen, PDB_SET)){
930 goto fn_exit;
934 temp = smbldap_talloc_single_attribute(
935 ldap_state->smbldap_state->ldap_struct,
936 entry,
937 get_userattr_key2string(ldap_state->schema_ver,
938 LDAP_ATTR_ACB_INFO),
939 ctx);
940 if (temp) {
941 acct_ctrl = pdb_decode_acct_ctrl(temp);
943 if (acct_ctrl == 0) {
944 acct_ctrl |= ACB_NORMAL;
947 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
948 } else {
949 acct_ctrl |= ACB_NORMAL;
952 pdb_set_hours_len(sampass, hours_len, PDB_SET);
953 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
955 temp = smbldap_talloc_single_attribute(
956 ldap_state->smbldap_state->ldap_struct,
957 entry,
958 get_userattr_key2string(ldap_state->schema_ver,
959 LDAP_ATTR_BAD_PASSWORD_COUNT),
960 ctx);
961 if (temp) {
962 bad_password_count = (uint32_t) atol(temp);
963 pdb_set_bad_password_count(sampass,
964 bad_password_count, PDB_SET);
967 temp = smbldap_talloc_single_attribute(
968 ldap_state->smbldap_state->ldap_struct,
969 entry,
970 get_userattr_key2string(ldap_state->schema_ver,
971 LDAP_ATTR_BAD_PASSWORD_TIME),
972 ctx);
973 if (temp) {
974 bad_password_time = (time_t) atol(temp);
975 pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
979 temp = smbldap_talloc_single_attribute(
980 ldap_state->smbldap_state->ldap_struct,
981 entry,
982 get_userattr_key2string(ldap_state->schema_ver,
983 LDAP_ATTR_LOGON_COUNT),
984 ctx);
985 if (temp) {
986 logon_count = (uint32_t) atol(temp);
987 pdb_set_logon_count(sampass, logon_count, PDB_SET);
990 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
992 temp = smbldap_talloc_single_attribute(
993 ldap_state->smbldap_state->ldap_struct,
994 entry,
995 get_userattr_key2string(ldap_state->schema_ver,
996 LDAP_ATTR_LOGON_HOURS),
997 ctx);
998 if (temp) {
999 pdb_gethexhours(temp, hours);
1000 memset((char *)temp, '\0', strlen(temp) +1);
1001 pdb_set_hours(sampass, hours, hours_len, PDB_SET);
1002 ZERO_STRUCT(hours);
1005 if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
1006 struct passwd unix_pw;
1007 bool have_uid = false;
1008 bool have_gid = false;
1009 struct dom_sid mapped_gsid;
1010 const struct dom_sid *primary_gsid;
1011 struct unixid id;
1013 ZERO_STRUCT(unix_pw);
1015 unix_pw.pw_name = username;
1016 unix_pw.pw_passwd = discard_const_p(char, "x");
1018 temp = smbldap_talloc_single_attribute(
1019 priv2ld(ldap_state),
1020 entry,
1021 "uidNumber",
1022 ctx);
1023 if (temp) {
1024 /* We've got a uid, feed the cache */
1025 unix_pw.pw_uid = strtoul(temp, NULL, 10);
1026 have_uid = true;
1028 temp = smbldap_talloc_single_attribute(
1029 priv2ld(ldap_state),
1030 entry,
1031 "gidNumber",
1032 ctx);
1033 if (temp) {
1034 /* We've got a uid, feed the cache */
1035 unix_pw.pw_gid = strtoul(temp, NULL, 10);
1036 have_gid = true;
1038 unix_pw.pw_gecos = smbldap_talloc_single_attribute(
1039 priv2ld(ldap_state),
1040 entry,
1041 "gecos",
1042 ctx);
1043 if (unix_pw.pw_gecos) {
1044 unix_pw.pw_gecos = fullname;
1046 unix_pw.pw_dir = smbldap_talloc_single_attribute(
1047 priv2ld(ldap_state),
1048 entry,
1049 "homeDirectory",
1050 ctx);
1051 if (unix_pw.pw_dir) {
1052 unix_pw.pw_dir = discard_const_p(char, "");
1054 unix_pw.pw_shell = smbldap_talloc_single_attribute(
1055 priv2ld(ldap_state),
1056 entry,
1057 "loginShell",
1058 ctx);
1059 if (unix_pw.pw_shell) {
1060 unix_pw.pw_shell = discard_const_p(char, "");
1063 if (have_uid && have_gid) {
1064 sampass->unix_pw = tcopy_passwd(sampass, &unix_pw);
1065 } else {
1066 sampass->unix_pw = Get_Pwnam_alloc(sampass, unix_pw.pw_name);
1069 if (sampass->unix_pw == NULL) {
1070 DEBUG(0,("init_sam_from_ldap: Failed to find Unix account for %s\n",
1071 pdb_get_username(sampass)));
1072 goto fn_exit;
1075 id.id = sampass->unix_pw->pw_uid;
1076 id.type = ID_TYPE_UID;
1078 idmap_cache_set_sid2unixid(pdb_get_user_sid(sampass), &id);
1080 gid_to_sid(&mapped_gsid, sampass->unix_pw->pw_gid);
1081 primary_gsid = pdb_get_group_sid(sampass);
1082 if (primary_gsid && dom_sid_equal(primary_gsid, &mapped_gsid)) {
1083 id.id = sampass->unix_pw->pw_gid;
1084 id.type = ID_TYPE_GID;
1086 idmap_cache_set_sid2unixid(primary_gsid, &id);
1090 /* check the timestamp of the cache vs ldap entry */
1091 if (!(ldap_entry_time = ldapsam_get_entry_timestamp(ldap_state,
1092 entry))) {
1093 ret = true;
1094 goto fn_exit;
1097 /* see if we have newer updates */
1098 if (!login_cache_read(sampass, &cache_entry)) {
1099 DEBUG (9, ("No cache entry, bad count = %u, bad time = %u\n",
1100 (unsigned int)pdb_get_bad_password_count(sampass),
1101 (unsigned int)pdb_get_bad_password_time(sampass)));
1102 ret = true;
1103 goto fn_exit;
1106 DEBUG(7, ("ldap time is %u, cache time is %u, bad time = %u\n",
1107 (unsigned int)ldap_entry_time,
1108 (unsigned int)cache_entry.entry_timestamp,
1109 (unsigned int)cache_entry.bad_password_time));
1111 if (ldap_entry_time > cache_entry.entry_timestamp) {
1112 /* cache is older than directory , so
1113 we need to delete the entry but allow the
1114 fields to be written out */
1115 login_cache_delentry(sampass);
1116 } else {
1117 /* read cache in */
1118 pdb_set_acct_ctrl(sampass,
1119 pdb_get_acct_ctrl(sampass) |
1120 (cache_entry.acct_ctrl & ACB_AUTOLOCK),
1121 PDB_SET);
1122 pdb_set_bad_password_count(sampass,
1123 cache_entry.bad_password_count,
1124 PDB_SET);
1125 pdb_set_bad_password_time(sampass,
1126 cache_entry.bad_password_time,
1127 PDB_SET);
1130 ret = true;
1132 fn_exit:
1134 TALLOC_FREE(ctx);
1135 return ret;
1138 /**********************************************************************
1139 Initialize the ldap db from a struct samu. Called on update.
1140 (Based on init_buffer_from_sam in pdb_tdb.c)
1141 *********************************************************************/
1143 static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state,
1144 LDAPMessage *existing,
1145 LDAPMod *** mods, struct samu * sampass,
1146 bool (*need_update)(const struct samu *,
1147 enum pdb_elements))
1149 char *temp = NULL;
1150 uint32_t rid;
1152 if (mods == NULL || sampass == NULL) {
1153 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1154 return False;
1157 *mods = NULL;
1160 * took out adding "objectclass: sambaAccount"
1161 * do this on a per-mod basis
1163 if (need_update(sampass, PDB_USERNAME)) {
1164 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1165 "uid", pdb_get_username(sampass));
1166 if (ldap_state->is_nds_ldap) {
1167 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1168 "cn", pdb_get_username(sampass));
1169 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1170 "sn", pdb_get_username(sampass));
1174 DEBUG(2, ("init_ldap_from_sam: Setting entry for user: %s\n", pdb_get_username(sampass)));
1176 /* only update the RID if we actually need to */
1177 if (need_update(sampass, PDB_USERSID)) {
1178 fstring sid_string;
1179 const struct dom_sid *user_sid = pdb_get_user_sid(sampass);
1181 switch ( ldap_state->schema_ver ) {
1182 case SCHEMAVER_SAMBAACCOUNT:
1183 if (!sid_peek_check_rid(&ldap_state->domain_sid, user_sid, &rid)) {
1184 DEBUG(1, ("init_ldap_from_sam: User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
1185 sid_string_dbg(user_sid),
1186 sid_string_dbg(
1187 &ldap_state->domain_sid)));
1188 return False;
1190 if (asprintf(&temp, "%i", rid) < 0) {
1191 return false;
1193 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1194 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID),
1195 temp);
1196 SAFE_FREE(temp);
1197 break;
1199 case SCHEMAVER_SAMBASAMACCOUNT:
1200 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1201 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
1202 sid_to_fstring(sid_string, user_sid));
1203 break;
1205 default:
1206 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
1207 break;
1211 /* we don't need to store the primary group RID - so leaving it
1212 'free' to hang off the unix primary group makes life easier */
1214 if (need_update(sampass, PDB_GROUPSID)) {
1215 fstring sid_string;
1216 const struct dom_sid *group_sid = pdb_get_group_sid(sampass);
1218 switch ( ldap_state->schema_ver ) {
1219 case SCHEMAVER_SAMBAACCOUNT:
1220 if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) {
1221 DEBUG(1, ("init_ldap_from_sam: User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
1222 sid_string_dbg(group_sid),
1223 sid_string_dbg(
1224 &ldap_state->domain_sid)));
1225 return False;
1228 if (asprintf(&temp, "%i", rid) < 0) {
1229 return false;
1231 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1232 get_userattr_key2string(ldap_state->schema_ver,
1233 LDAP_ATTR_PRIMARY_GROUP_RID), temp);
1234 SAFE_FREE(temp);
1235 break;
1237 case SCHEMAVER_SAMBASAMACCOUNT:
1238 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1239 get_userattr_key2string(ldap_state->schema_ver,
1240 LDAP_ATTR_PRIMARY_GROUP_SID), sid_to_fstring(sid_string, group_sid));
1241 break;
1243 default:
1244 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
1245 break;
1250 /* displayName, cn, and gecos should all be the same
1251 * most easily accomplished by giving them the same OID
1252 * gecos isn't set here b/c it should be handled by the
1253 * add-user script
1254 * We change displayName only and fall back to cn if
1255 * it does not exist.
1258 if (need_update(sampass, PDB_FULLNAME))
1259 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1260 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME),
1261 pdb_get_fullname(sampass));
1263 if (need_update(sampass, PDB_ACCTDESC))
1264 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1265 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC),
1266 pdb_get_acct_desc(sampass));
1268 if (need_update(sampass, PDB_WORKSTATIONS))
1269 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1270 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS),
1271 pdb_get_workstations(sampass));
1273 if (need_update(sampass, PDB_MUNGEDDIAL))
1274 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1275 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_MUNGED_DIAL),
1276 pdb_get_munged_dial(sampass));
1278 if (need_update(sampass, PDB_SMBHOME))
1279 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1280 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH),
1281 pdb_get_homedir(sampass));
1283 if (need_update(sampass, PDB_DRIVE))
1284 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1285 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE),
1286 pdb_get_dir_drive(sampass));
1288 if (need_update(sampass, PDB_LOGONSCRIPT))
1289 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1290 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT),
1291 pdb_get_logon_script(sampass));
1293 if (need_update(sampass, PDB_PROFILE))
1294 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1295 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH),
1296 pdb_get_profile_path(sampass));
1298 if (asprintf(&temp, "%li", (long int)pdb_get_logon_time(sampass)) < 0) {
1299 return false;
1301 if (need_update(sampass, PDB_LOGONTIME))
1302 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1303 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp);
1304 SAFE_FREE(temp);
1306 if (asprintf(&temp, "%li", (long int)pdb_get_logoff_time(sampass)) < 0) {
1307 return false;
1309 if (need_update(sampass, PDB_LOGOFFTIME))
1310 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1311 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp);
1312 SAFE_FREE(temp);
1314 if (asprintf(&temp, "%li", (long int)pdb_get_kickoff_time(sampass)) < 0) {
1315 return false;
1317 if (need_update(sampass, PDB_KICKOFFTIME))
1318 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1319 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp);
1320 SAFE_FREE(temp);
1322 if (asprintf(&temp, "%li", (long int)pdb_get_pass_can_change_time_noncalc(sampass)) < 0) {
1323 return false;
1325 if (need_update(sampass, PDB_CANCHANGETIME))
1326 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1327 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp);
1328 SAFE_FREE(temp);
1330 if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))
1331 || (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
1333 if (need_update(sampass, PDB_LMPASSWD)) {
1334 const uchar *lm_pw = pdb_get_lanman_passwd(sampass);
1335 if (lm_pw) {
1336 char pwstr[34];
1337 pdb_sethexpwd(pwstr, lm_pw,
1338 pdb_get_acct_ctrl(sampass));
1339 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1340 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW),
1341 pwstr);
1342 } else {
1343 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1344 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW),
1345 NULL);
1348 if (need_update(sampass, PDB_NTPASSWD)) {
1349 const uchar *nt_pw = pdb_get_nt_passwd(sampass);
1350 if (nt_pw) {
1351 char pwstr[34];
1352 pdb_sethexpwd(pwstr, nt_pw,
1353 pdb_get_acct_ctrl(sampass));
1354 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1355 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW),
1356 pwstr);
1357 } else {
1358 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1359 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW),
1360 NULL);
1364 if (need_update(sampass, PDB_PWHISTORY)) {
1365 char *pwstr = NULL;
1366 uint32_t pwHistLen = 0;
1367 pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);
1369 pwstr = SMB_MALLOC_ARRAY(char, 1024);
1370 if (!pwstr) {
1371 return false;
1373 if (pwHistLen == 0) {
1374 /* Remove any password history from the LDAP store. */
1375 memset(pwstr, '0', 64); /* NOTE !!!! '0' *NOT '\0' */
1376 pwstr[64] = '\0';
1377 } else {
1378 int i;
1379 uint32_t currHistLen = 0;
1380 const uint8 *pwhist = pdb_get_pw_history(sampass, &currHistLen);
1381 if (pwhist != NULL) {
1382 /* We can only store (1024-1/64 password history entries. */
1383 pwHistLen = MIN(pwHistLen, ((1024-1)/64));
1384 for (i=0; i< pwHistLen && i < currHistLen; i++) {
1385 /* Store the salt. */
1386 pdb_sethexpwd(&pwstr[i*64], &pwhist[i*PW_HISTORY_ENTRY_LEN], 0);
1387 /* Followed by the md5 hash of salt + md4 hash */
1388 pdb_sethexpwd(&pwstr[(i*64)+32],
1389 &pwhist[(i*PW_HISTORY_ENTRY_LEN)+PW_HISTORY_SALT_LEN], 0);
1390 DEBUG(100, ("pwstr=%s\n", pwstr));
1394 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1395 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_HISTORY),
1396 pwstr);
1397 SAFE_FREE(pwstr);
1400 if (need_update(sampass, PDB_PASSLASTSET)) {
1401 if (asprintf(&temp, "%li",
1402 (long int)pdb_get_pass_last_set_time(sampass)) < 0) {
1403 return false;
1405 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1406 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET),
1407 temp);
1408 SAFE_FREE(temp);
1412 if (need_update(sampass, PDB_HOURS)) {
1413 const uint8 *hours = pdb_get_hours(sampass);
1414 if (hours) {
1415 char hourstr[44];
1416 pdb_sethexhours(hourstr, hours);
1417 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct,
1418 existing,
1419 mods,
1420 get_userattr_key2string(ldap_state->schema_ver,
1421 LDAP_ATTR_LOGON_HOURS),
1422 hourstr);
1426 if (need_update(sampass, PDB_ACCTCTRL))
1427 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
1428 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO),
1429 pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass), NEW_PW_FORMAT_SPACE_PADDED_LEN));
1431 /* password lockout cache:
1432 - If we are now autolocking or clearing, we write to ldap
1433 - If we are clearing, we delete the cache entry
1434 - If the count is > 0, we update the cache
1436 This even means when autolocking, we cache, just in case the
1437 update doesn't work, and we have to cache the autolock flag */
1439 if (need_update(sampass, PDB_BAD_PASSWORD_COUNT)) /* &&
1440 need_update(sampass, PDB_BAD_PASSWORD_TIME)) */ {
1441 uint16_t badcount = pdb_get_bad_password_count(sampass);
1442 time_t badtime = pdb_get_bad_password_time(sampass);
1443 uint32_t pol;
1444 pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &pol);
1446 DEBUG(3, ("updating bad password fields, policy=%u, count=%u, time=%u\n",
1447 (unsigned int)pol, (unsigned int)badcount, (unsigned int)badtime));
1449 if ((badcount >= pol) || (badcount == 0)) {
1450 DEBUG(7, ("making mods to update ldap, count=%u, time=%u\n",
1451 (unsigned int)badcount, (unsigned int)badtime));
1452 if (asprintf(&temp, "%li", (long)badcount) < 0) {
1453 return false;
1455 smbldap_make_mod(
1456 ldap_state->smbldap_state->ldap_struct,
1457 existing, mods,
1458 get_userattr_key2string(
1459 ldap_state->schema_ver,
1460 LDAP_ATTR_BAD_PASSWORD_COUNT),
1461 temp);
1462 SAFE_FREE(temp);
1464 if (asprintf(&temp, "%li", (long int)badtime) < 0) {
1465 return false;
1467 smbldap_make_mod(
1468 ldap_state->smbldap_state->ldap_struct,
1469 existing, mods,
1470 get_userattr_key2string(
1471 ldap_state->schema_ver,
1472 LDAP_ATTR_BAD_PASSWORD_TIME),
1473 temp);
1474 SAFE_FREE(temp);
1476 if (badcount == 0) {
1477 DEBUG(7, ("bad password count is reset, deleting login cache entry for %s\n", pdb_get_nt_username(sampass)));
1478 login_cache_delentry(sampass);
1479 } else {
1480 struct login_cache cache_entry;
1482 cache_entry.entry_timestamp = time(NULL);
1483 cache_entry.acct_ctrl = pdb_get_acct_ctrl(sampass);
1484 cache_entry.bad_password_count = badcount;
1485 cache_entry.bad_password_time = badtime;
1487 DEBUG(7, ("Updating bad password count and time in login cache\n"));
1488 login_cache_write(sampass, &cache_entry);
1492 return True;
1495 /**********************************************************************
1496 End enumeration of the LDAP password list.
1497 *********************************************************************/
1499 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1501 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1502 if (ldap_state->result) {
1503 ldap_msgfree(ldap_state->result);
1504 ldap_state->result = NULL;
1508 static void append_attr(TALLOC_CTX *mem_ctx, const char ***attr_list,
1509 const char *new_attr)
1511 int i;
1513 if (new_attr == NULL) {
1514 return;
1517 for (i=0; (*attr_list)[i] != NULL; i++) {
1521 (*attr_list) = talloc_realloc(mem_ctx, (*attr_list),
1522 const char *, i+2);
1523 SMB_ASSERT((*attr_list) != NULL);
1524 (*attr_list)[i] = talloc_strdup((*attr_list), new_attr);
1525 (*attr_list)[i+1] = NULL;
1528 static void ldapsam_add_unix_attributes(TALLOC_CTX *mem_ctx,
1529 const char ***attr_list)
1531 append_attr(mem_ctx, attr_list, "uidNumber");
1532 append_attr(mem_ctx, attr_list, "gidNumber");
1533 append_attr(mem_ctx, attr_list, "homeDirectory");
1534 append_attr(mem_ctx, attr_list, "loginShell");
1535 append_attr(mem_ctx, attr_list, "gecos");
1538 /**********************************************************************
1539 Get struct samu entry from LDAP by username.
1540 *********************************************************************/
1542 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, struct samu *user, const char *sname)
1544 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1545 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1546 LDAPMessage *result = NULL;
1547 LDAPMessage *entry = NULL;
1548 int count;
1549 const char ** attr_list;
1550 int rc;
1552 attr_list = get_userattr_list( user, ldap_state->schema_ver );
1553 append_attr(user, &attr_list,
1554 get_userattr_key2string(ldap_state->schema_ver,
1555 LDAP_ATTR_MOD_TIMESTAMP));
1556 ldapsam_add_unix_attributes(user, &attr_list);
1557 rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result,
1558 attr_list);
1559 TALLOC_FREE( attr_list );
1561 if ( rc != LDAP_SUCCESS )
1562 return NT_STATUS_NO_SUCH_USER;
1564 count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1566 if (count < 1) {
1567 DEBUG(4, ("ldapsam_getsampwnam: Unable to locate user [%s] count=%d\n", sname, count));
1568 ldap_msgfree(result);
1569 return NT_STATUS_NO_SUCH_USER;
1570 } else if (count > 1) {
1571 DEBUG(1, ("ldapsam_getsampwnam: Duplicate entries for this user [%s] Failing. count=%d\n", sname, count));
1572 ldap_msgfree(result);
1573 return NT_STATUS_NO_SUCH_USER;
1576 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1577 if (entry) {
1578 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1579 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
1580 ldap_msgfree(result);
1581 return NT_STATUS_NO_SUCH_USER;
1583 pdb_set_backend_private_data(user, result, NULL,
1584 my_methods, PDB_CHANGED);
1585 talloc_autofree_ldapmsg(user, result);
1586 ret = NT_STATUS_OK;
1587 } else {
1588 ldap_msgfree(result);
1590 return ret;
1593 static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state,
1594 const struct dom_sid *sid, LDAPMessage **result)
1596 int rc = -1;
1597 const char ** attr_list;
1598 uint32_t rid;
1600 switch ( ldap_state->schema_ver ) {
1601 case SCHEMAVER_SAMBASAMACCOUNT: {
1602 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1603 if (tmp_ctx == NULL) {
1604 return LDAP_NO_MEMORY;
1607 attr_list = get_userattr_list(tmp_ctx,
1608 ldap_state->schema_ver);
1609 append_attr(tmp_ctx, &attr_list,
1610 get_userattr_key2string(
1611 ldap_state->schema_ver,
1612 LDAP_ATTR_MOD_TIMESTAMP));
1613 ldapsam_add_unix_attributes(tmp_ctx, &attr_list);
1614 rc = ldapsam_search_suffix_by_sid(ldap_state, sid,
1615 result, attr_list);
1616 TALLOC_FREE(tmp_ctx);
1618 if ( rc != LDAP_SUCCESS )
1619 return rc;
1620 break;
1623 case SCHEMAVER_SAMBAACCOUNT:
1624 if (!sid_peek_check_rid(&ldap_state->domain_sid, sid, &rid)) {
1625 return rc;
1628 attr_list = get_userattr_list(NULL,
1629 ldap_state->schema_ver);
1630 rc = ldapsam_search_suffix_by_rid(ldap_state, rid, result, attr_list );
1631 TALLOC_FREE( attr_list );
1633 if ( rc != LDAP_SUCCESS )
1634 return rc;
1635 break;
1637 return rc;
1640 /**********************************************************************
1641 Get struct samu entry from LDAP by SID.
1642 *********************************************************************/
1644 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const struct dom_sid *sid)
1646 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1647 LDAPMessage *result = NULL;
1648 LDAPMessage *entry = NULL;
1649 int count;
1650 int rc;
1652 rc = ldapsam_get_ldap_user_by_sid(ldap_state,
1653 sid, &result);
1654 if (rc != LDAP_SUCCESS)
1655 return NT_STATUS_NO_SUCH_USER;
1657 count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1659 if (count < 1) {
1660 DEBUG(4, ("ldapsam_getsampwsid: Unable to locate SID [%s] "
1661 "count=%d\n", sid_string_dbg(sid), count));
1662 ldap_msgfree(result);
1663 return NT_STATUS_NO_SUCH_USER;
1664 } else if (count > 1) {
1665 DEBUG(1, ("ldapsam_getsampwsid: More than one user with SID "
1666 "[%s]. Failing. count=%d\n", sid_string_dbg(sid),
1667 count));
1668 ldap_msgfree(result);
1669 return NT_STATUS_NO_SUCH_USER;
1672 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1673 if (!entry) {
1674 ldap_msgfree(result);
1675 return NT_STATUS_NO_SUCH_USER;
1678 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1679 DEBUG(1,("ldapsam_getsampwsid: init_sam_from_ldap failed!\n"));
1680 ldap_msgfree(result);
1681 return NT_STATUS_NO_SUCH_USER;
1684 pdb_set_backend_private_data(user, result, NULL,
1685 my_methods, PDB_CHANGED);
1686 talloc_autofree_ldapmsg(user, result);
1687 return NT_STATUS_OK;
1690 /********************************************************************
1691 Do the actual modification - also change a plaintext passord if
1692 it it set.
1693 **********************************************************************/
1695 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
1696 struct samu *newpwd, char *dn,
1697 LDAPMod **mods, int ldap_op,
1698 bool (*need_update)(const struct samu *, enum pdb_elements))
1700 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1701 int rc;
1703 if (!newpwd || !dn) {
1704 return NT_STATUS_INVALID_PARAMETER;
1707 if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) &&
1708 (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) &&
1709 need_update(newpwd, PDB_PLAINTEXT_PW) &&
1710 (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
1711 BerElement *ber;
1712 struct berval *bv;
1713 char *retoid = NULL;
1714 struct berval *retdata = NULL;
1715 char *utf8_password;
1716 char *utf8_dn;
1717 size_t converted_size;
1718 int ret;
1720 if (!ldap_state->is_nds_ldap) {
1722 if (!smbldap_has_extension(ldap_state->smbldap_state->ldap_struct,
1723 LDAP_EXOP_MODIFY_PASSWD)) {
1724 DEBUG(2, ("ldap password change requested, but LDAP "
1725 "server does not support it -- ignoring\n"));
1726 return NT_STATUS_OK;
1730 if (!push_utf8_talloc(talloc_tos(), &utf8_password,
1731 pdb_get_plaintext_passwd(newpwd),
1732 &converted_size))
1734 return NT_STATUS_NO_MEMORY;
1737 if (!push_utf8_talloc(talloc_tos(), &utf8_dn, dn, &converted_size)) {
1738 TALLOC_FREE(utf8_password);
1739 return NT_STATUS_NO_MEMORY;
1742 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
1743 DEBUG(0,("ber_alloc_t returns NULL\n"));
1744 TALLOC_FREE(utf8_password);
1745 TALLOC_FREE(utf8_dn);
1746 return NT_STATUS_UNSUCCESSFUL;
1749 if ((ber_printf (ber, "{") < 0) ||
1750 (ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID,
1751 utf8_dn) < 0)) {
1752 DEBUG(0,("ldapsam_modify_entry: ber_printf returns a "
1753 "value <0\n"));
1754 ber_free(ber,1);
1755 TALLOC_FREE(utf8_dn);
1756 TALLOC_FREE(utf8_password);
1757 return NT_STATUS_UNSUCCESSFUL;
1760 if ((utf8_password != NULL) && (*utf8_password != '\0')) {
1761 ret = ber_printf(ber, "ts}",
1762 LDAP_TAG_EXOP_MODIFY_PASSWD_NEW,
1763 utf8_password);
1764 } else {
1765 ret = ber_printf(ber, "}");
1768 if (ret < 0) {
1769 DEBUG(0,("ldapsam_modify_entry: ber_printf returns a "
1770 "value <0\n"));
1771 ber_free(ber,1);
1772 TALLOC_FREE(utf8_dn);
1773 TALLOC_FREE(utf8_password);
1774 return NT_STATUS_UNSUCCESSFUL;
1777 if ((rc = ber_flatten (ber, &bv))<0) {
1778 DEBUG(0,("ldapsam_modify_entry: ber_flatten returns a value <0\n"));
1779 ber_free(ber,1);
1780 TALLOC_FREE(utf8_dn);
1781 TALLOC_FREE(utf8_password);
1782 return NT_STATUS_UNSUCCESSFUL;
1785 TALLOC_FREE(utf8_dn);
1786 TALLOC_FREE(utf8_password);
1787 ber_free(ber, 1);
1789 if (!ldap_state->is_nds_ldap) {
1790 rc = smbldap_extended_operation(ldap_state->smbldap_state,
1791 LDAP_EXOP_MODIFY_PASSWD,
1792 bv, NULL, NULL, &retoid,
1793 &retdata);
1794 } else {
1795 rc = pdb_nds_set_password(ldap_state->smbldap_state, dn,
1796 pdb_get_plaintext_passwd(newpwd));
1798 if (rc != LDAP_SUCCESS) {
1799 char *ld_error = NULL;
1801 if (rc == LDAP_OBJECT_CLASS_VIOLATION) {
1802 DEBUG(3, ("Could not set userPassword "
1803 "attribute due to an objectClass "
1804 "violation -- ignoring\n"));
1805 ber_bvfree(bv);
1806 return NT_STATUS_OK;
1809 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1810 &ld_error);
1811 DEBUG(0,("ldapsam_modify_entry: LDAP Password could not be changed for user %s: %s\n\t%s\n",
1812 pdb_get_username(newpwd), ldap_err2string(rc), ld_error?ld_error:"unknown"));
1813 SAFE_FREE(ld_error);
1814 ber_bvfree(bv);
1815 #if defined(LDAP_CONSTRAINT_VIOLATION)
1816 if (rc == LDAP_CONSTRAINT_VIOLATION)
1817 return NT_STATUS_PASSWORD_RESTRICTION;
1818 #endif
1819 return NT_STATUS_UNSUCCESSFUL;
1820 } else {
1821 DEBUG(3,("ldapsam_modify_entry: LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
1822 #ifdef DEBUG_PASSWORD
1823 DEBUG(100,("ldapsam_modify_entry: LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd)));
1824 #endif
1825 if (retdata)
1826 ber_bvfree(retdata);
1827 if (retoid)
1828 ldap_memfree(retoid);
1830 ber_bvfree(bv);
1833 if (!mods) {
1834 DEBUG(5,("ldapsam_modify_entry: mods is empty: nothing to modify\n"));
1835 /* may be password change below however */
1836 } else {
1837 switch(ldap_op) {
1838 case LDAP_MOD_ADD:
1839 if (ldap_state->is_nds_ldap) {
1840 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1841 "objectclass",
1842 "inetOrgPerson");
1843 } else {
1844 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1845 "objectclass",
1846 LDAP_OBJ_ACCOUNT);
1848 rc = smbldap_add(ldap_state->smbldap_state,
1849 dn, mods);
1850 break;
1851 case LDAP_MOD_REPLACE:
1852 rc = smbldap_modify(ldap_state->smbldap_state,
1853 dn ,mods);
1854 break;
1855 default:
1856 DEBUG(0,("ldapsam_modify_entry: Wrong LDAP operation type: %d!\n",
1857 ldap_op));
1858 return NT_STATUS_INVALID_PARAMETER;
1861 if (rc!=LDAP_SUCCESS) {
1862 return NT_STATUS_UNSUCCESSFUL;
1866 return NT_STATUS_OK;
1869 /**********************************************************************
1870 Delete entry from LDAP for username.
1871 *********************************************************************/
1873 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods,
1874 struct samu * sam_acct)
1876 struct ldapsam_privates *priv =
1877 (struct ldapsam_privates *)my_methods->private_data;
1878 const char *sname;
1879 int rc;
1880 LDAPMessage *msg, *entry;
1881 NTSTATUS result = NT_STATUS_NO_MEMORY;
1882 const char **attr_list;
1883 TALLOC_CTX *mem_ctx;
1885 if (!sam_acct) {
1886 DEBUG(0, ("ldapsam_delete_sam_account: sam_acct was NULL!\n"));
1887 return NT_STATUS_INVALID_PARAMETER;
1890 sname = pdb_get_username(sam_acct);
1892 DEBUG(3, ("ldapsam_delete_sam_account: Deleting user %s from "
1893 "LDAP.\n", sname));
1895 mem_ctx = talloc_new(NULL);
1896 if (mem_ctx == NULL) {
1897 DEBUG(0, ("talloc_new failed\n"));
1898 goto done;
1901 attr_list = get_userattr_delete_list(mem_ctx, priv->schema_ver );
1902 if (attr_list == NULL) {
1903 goto done;
1906 rc = ldapsam_search_suffix_by_name(priv, sname, &msg, attr_list);
1908 if ((rc != LDAP_SUCCESS) ||
1909 (ldap_count_entries(priv2ld(priv), msg) != 1) ||
1910 ((entry = ldap_first_entry(priv2ld(priv), msg)) == NULL)) {
1911 DEBUG(5, ("Could not find user %s\n", sname));
1912 result = NT_STATUS_NO_SUCH_USER;
1913 goto done;
1916 rc = ldapsam_delete_entry(
1917 priv, mem_ctx, entry,
1918 priv->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ?
1919 LDAP_OBJ_SAMBASAMACCOUNT : LDAP_OBJ_SAMBAACCOUNT,
1920 attr_list);
1922 result = (rc == LDAP_SUCCESS) ?
1923 NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
1925 done:
1926 TALLOC_FREE(mem_ctx);
1927 return result;
1930 /**********************************************************************
1931 Update struct samu.
1932 *********************************************************************/
1934 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struct samu * newpwd)
1936 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1937 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1938 int rc = 0;
1939 char *dn;
1940 LDAPMessage *result = NULL;
1941 LDAPMessage *entry = NULL;
1942 LDAPMod **mods = NULL;
1943 const char **attr_list;
1945 result = (LDAPMessage *)pdb_get_backend_private_data(newpwd, my_methods);
1946 if (!result) {
1947 attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
1948 if (pdb_get_username(newpwd) == NULL) {
1949 return NT_STATUS_INVALID_PARAMETER;
1951 rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list );
1952 TALLOC_FREE( attr_list );
1953 if (rc != LDAP_SUCCESS) {
1954 return NT_STATUS_UNSUCCESSFUL;
1956 pdb_set_backend_private_data(newpwd, result, NULL,
1957 my_methods, PDB_CHANGED);
1958 talloc_autofree_ldapmsg(newpwd, result);
1961 if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
1962 DEBUG(0, ("ldapsam_update_sam_account: No user to modify!\n"));
1963 return NT_STATUS_UNSUCCESSFUL;
1966 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1967 dn = smbldap_talloc_dn(talloc_tos(), ldap_state->smbldap_state->ldap_struct, entry);
1968 if (!dn) {
1969 return NT_STATUS_UNSUCCESSFUL;
1972 DEBUG(4, ("ldapsam_update_sam_account: user %s to be modified has dn: %s\n", pdb_get_username(newpwd), dn));
1974 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
1975 pdb_element_is_changed)) {
1976 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1977 TALLOC_FREE(dn);
1978 if (mods != NULL)
1979 ldap_mods_free(mods,True);
1980 return NT_STATUS_UNSUCCESSFUL;
1983 if ((lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_ONLY)
1984 && (mods == NULL)) {
1985 DEBUG(4,("ldapsam_update_sam_account: mods is empty: nothing to update for user: %s\n",
1986 pdb_get_username(newpwd)));
1987 TALLOC_FREE(dn);
1988 return NT_STATUS_OK;
1991 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, pdb_element_is_changed);
1993 if (mods != NULL) {
1994 ldap_mods_free(mods,True);
1997 TALLOC_FREE(dn);
2000 * We need to set the backend private data to NULL here. For example
2001 * setuserinfo level 25 does a pdb_update_sam_account twice on the
2002 * same one, and with the explicit delete / add logic for attribute
2003 * values the second time we would use the wrong "old" value which
2004 * does not exist in LDAP anymore. Thus the LDAP server would refuse
2005 * the update.
2006 * The existing LDAPMessage is still being auto-freed by the
2007 * destructor.
2009 pdb_set_backend_private_data(newpwd, NULL, NULL, my_methods,
2010 PDB_CHANGED);
2012 if (!NT_STATUS_IS_OK(ret)) {
2013 return ret;
2016 DEBUG(2, ("ldapsam_update_sam_account: successfully modified uid = %s in the LDAP database\n",
2017 pdb_get_username(newpwd)));
2018 return NT_STATUS_OK;
2021 /***************************************************************************
2022 Renames a struct samu
2023 - The "rename user script" has full responsibility for changing everything
2024 ***************************************************************************/
2026 static NTSTATUS ldapsam_del_groupmem(struct pdb_methods *my_methods,
2027 TALLOC_CTX *tmp_ctx,
2028 uint32_t group_rid,
2029 uint32_t member_rid);
2031 static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
2032 TALLOC_CTX *mem_ctx,
2033 struct samu *user,
2034 struct dom_sid **pp_sids,
2035 gid_t **pp_gids,
2036 uint32_t *p_num_groups);
2038 static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
2039 struct samu *old_acct,
2040 const char *newname)
2042 const char *oldname;
2043 int rc;
2044 char *rename_script = NULL;
2045 fstring oldname_lower, newname_lower;
2047 if (!old_acct) {
2048 DEBUG(0, ("ldapsam_rename_sam_account: old_acct was NULL!\n"));
2049 return NT_STATUS_INVALID_PARAMETER;
2051 if (!newname) {
2052 DEBUG(0, ("ldapsam_rename_sam_account: newname was NULL!\n"));
2053 return NT_STATUS_INVALID_PARAMETER;
2056 oldname = pdb_get_username(old_acct);
2058 /* rename the posix user */
2059 rename_script = talloc_strdup(talloc_tos(), lp_renameuser_script());
2060 if (rename_script == NULL) {
2061 return NT_STATUS_NO_MEMORY;
2064 if (!(*rename_script)) {
2065 TALLOC_FREE(rename_script);
2066 return NT_STATUS_ACCESS_DENIED;
2069 DEBUG (3, ("ldapsam_rename_sam_account: Renaming user %s to %s.\n",
2070 oldname, newname));
2072 /* We have to allow the account name to end with a '$'.
2073 Also, follow the semantics in _samr_create_user() and lower case the
2074 posix name but preserve the case in passdb */
2076 fstrcpy( oldname_lower, oldname );
2077 strlower_m( oldname_lower );
2078 fstrcpy( newname_lower, newname );
2079 strlower_m( newname_lower );
2080 rename_script = realloc_string_sub2(rename_script,
2081 "%unew",
2082 newname_lower,
2083 true,
2084 true);
2085 if (!rename_script) {
2086 return NT_STATUS_NO_MEMORY;
2088 rename_script = realloc_string_sub2(rename_script,
2089 "%uold",
2090 oldname_lower,
2091 true,
2092 true);
2093 rc = smbrun(rename_script, NULL);
2095 DEBUG(rc ? 0 : 3,("Running the command `%s' gave %d\n",
2096 rename_script, rc));
2098 TALLOC_FREE(rename_script);
2100 if (rc == 0) {
2101 smb_nscd_flush_user_cache();
2104 if (rc)
2105 return NT_STATUS_UNSUCCESSFUL;
2107 return NT_STATUS_OK;
2110 /**********************************************************************
2111 Add struct samu to LDAP.
2112 *********************************************************************/
2114 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct samu * newpwd)
2116 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2117 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2118 int rc;
2119 LDAPMessage *result = NULL;
2120 LDAPMessage *entry = NULL;
2121 LDAPMod **mods = NULL;
2122 int ldap_op = LDAP_MOD_REPLACE;
2123 uint32_t num_result;
2124 const char **attr_list;
2125 char *escape_user = NULL;
2126 const char *username = pdb_get_username(newpwd);
2127 const struct dom_sid *sid = pdb_get_user_sid(newpwd);
2128 char *filter = NULL;
2129 char *dn = NULL;
2130 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2131 TALLOC_CTX *ctx = talloc_init("ldapsam_add_sam_account");
2133 if (!ctx) {
2134 return NT_STATUS_NO_MEMORY;
2137 if (!username || !*username) {
2138 DEBUG(0, ("ldapsam_add_sam_account: Cannot add user without a username!\n"));
2139 status = NT_STATUS_INVALID_PARAMETER;
2140 goto fn_exit;
2143 /* free this list after the second search or in case we exit on failure */
2144 attr_list = get_userattr_list(ctx, ldap_state->schema_ver);
2146 rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list);
2148 if (rc != LDAP_SUCCESS) {
2149 goto fn_exit;
2152 if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
2153 DEBUG(0,("ldapsam_add_sam_account: User '%s' already in the base, with samba attributes\n",
2154 username));
2155 goto fn_exit;
2157 ldap_msgfree(result);
2158 result = NULL;
2160 if (pdb_element_is_set_or_changed(newpwd, PDB_USERSID)) {
2161 rc = ldapsam_get_ldap_user_by_sid(ldap_state,
2162 sid, &result);
2163 if (rc == LDAP_SUCCESS) {
2164 if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
2165 DEBUG(0,("ldapsam_add_sam_account: SID '%s' "
2166 "already in the base, with samba "
2167 "attributes\n", sid_string_dbg(sid)));
2168 goto fn_exit;
2170 ldap_msgfree(result);
2171 result = NULL;
2175 /* does the entry already exist but without a samba attributes?
2176 we need to return the samba attributes here */
2178 escape_user = escape_ldap_string(talloc_tos(), username);
2179 filter = talloc_strdup(attr_list, "(uid=%u)");
2180 if (!filter) {
2181 status = NT_STATUS_NO_MEMORY;
2182 goto fn_exit;
2184 filter = talloc_all_string_sub(attr_list, filter, "%u", escape_user);
2185 TALLOC_FREE(escape_user);
2186 if (!filter) {
2187 status = NT_STATUS_NO_MEMORY;
2188 goto fn_exit;
2191 rc = smbldap_search_suffix(ldap_state->smbldap_state,
2192 filter, attr_list, &result);
2193 if ( rc != LDAP_SUCCESS ) {
2194 goto fn_exit;
2197 num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
2199 if (num_result > 1) {
2200 DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
2201 goto fn_exit;
2204 /* Check if we need to update an existing entry */
2205 if (num_result == 1) {
2206 DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n"));
2207 ldap_op = LDAP_MOD_REPLACE;
2208 entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
2209 dn = smbldap_talloc_dn(ctx, ldap_state->smbldap_state->ldap_struct, entry);
2210 if (!dn) {
2211 status = NT_STATUS_NO_MEMORY;
2212 goto fn_exit;
2215 } else if (ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT) {
2217 /* There might be a SID for this account already - say an idmap entry */
2219 filter = talloc_asprintf(ctx,
2220 "(&(%s=%s)(|(objectClass=%s)(objectClass=%s)))",
2221 get_userattr_key2string(ldap_state->schema_ver,
2222 LDAP_ATTR_USER_SID),
2223 sid_string_talloc(ctx, sid),
2224 LDAP_OBJ_IDMAP_ENTRY,
2225 LDAP_OBJ_SID_ENTRY);
2226 if (!filter) {
2227 status = NT_STATUS_NO_MEMORY;
2228 goto fn_exit;
2231 /* free old result before doing a new search */
2232 if (result != NULL) {
2233 ldap_msgfree(result);
2234 result = NULL;
2236 rc = smbldap_search_suffix(ldap_state->smbldap_state,
2237 filter, attr_list, &result);
2239 if ( rc != LDAP_SUCCESS ) {
2240 goto fn_exit;
2243 num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
2245 if (num_result > 1) {
2246 DEBUG (0, ("ldapsam_add_sam_account: More than one user with specified Sid exists: bailing out!\n"));
2247 goto fn_exit;
2250 /* Check if we need to update an existing entry */
2251 if (num_result == 1) {
2253 DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n"));
2254 ldap_op = LDAP_MOD_REPLACE;
2255 entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
2256 dn = smbldap_talloc_dn (ctx, ldap_state->smbldap_state->ldap_struct, entry);
2257 if (!dn) {
2258 status = NT_STATUS_NO_MEMORY;
2259 goto fn_exit;
2264 if (num_result == 0) {
2265 char *escape_username;
2266 /* Check if we need to add an entry */
2267 DEBUG(3,("ldapsam_add_sam_account: Adding new user\n"));
2268 ldap_op = LDAP_MOD_ADD;
2270 escape_username = escape_rdn_val_string_alloc(username);
2271 if (!escape_username) {
2272 status = NT_STATUS_NO_MEMORY;
2273 goto fn_exit;
2276 if (username[strlen(username)-1] == '$') {
2277 dn = talloc_asprintf(ctx,
2278 "uid=%s,%s",
2279 escape_username,
2280 lp_ldap_machine_suffix());
2281 } else {
2282 dn = talloc_asprintf(ctx,
2283 "uid=%s,%s",
2284 escape_username,
2285 lp_ldap_user_suffix());
2288 SAFE_FREE(escape_username);
2289 if (!dn) {
2290 status = NT_STATUS_NO_MEMORY;
2291 goto fn_exit;
2295 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2296 pdb_element_is_set_or_changed)) {
2297 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
2298 if (mods != NULL) {
2299 ldap_mods_free(mods, true);
2301 goto fn_exit;
2304 if (mods == NULL) {
2305 DEBUG(0,("ldapsam_add_sam_account: mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
2306 goto fn_exit;
2308 switch ( ldap_state->schema_ver ) {
2309 case SCHEMAVER_SAMBAACCOUNT:
2310 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBAACCOUNT);
2311 break;
2312 case SCHEMAVER_SAMBASAMACCOUNT:
2313 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBASAMACCOUNT);
2314 break;
2315 default:
2316 DEBUG(0,("ldapsam_add_sam_account: invalid schema version specified\n"));
2317 break;
2320 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, pdb_element_is_set_or_changed);
2321 if (!NT_STATUS_IS_OK(ret)) {
2322 DEBUG(0,("ldapsam_add_sam_account: failed to modify/add user with uid = %s (dn = %s)\n",
2323 pdb_get_username(newpwd),dn));
2324 ldap_mods_free(mods, true);
2325 goto fn_exit;
2328 DEBUG(2,("ldapsam_add_sam_account: added: uid == %s in the LDAP database\n", pdb_get_username(newpwd)));
2329 ldap_mods_free(mods, true);
2331 status = NT_STATUS_OK;
2333 fn_exit:
2335 TALLOC_FREE(ctx);
2336 if (result) {
2337 ldap_msgfree(result);
2339 return status;
2342 /**********************************************************************
2343 *********************************************************************/
2345 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
2346 const char *filter,
2347 LDAPMessage ** result)
2349 int scope = LDAP_SCOPE_SUBTREE;
2350 int rc;
2351 const char **attr_list;
2353 attr_list = get_attr_list(NULL, groupmap_attr_list);
2354 rc = smbldap_search(ldap_state->smbldap_state,
2355 lp_ldap_suffix (), scope,
2356 filter, attr_list, 0, result);
2357 TALLOC_FREE(attr_list);
2359 return rc;
2362 /**********************************************************************
2363 *********************************************************************/
2365 static bool init_group_from_ldap(struct ldapsam_privates *ldap_state,
2366 GROUP_MAP *map, LDAPMessage *entry)
2368 char *temp = NULL;
2369 TALLOC_CTX *ctx = talloc_init("init_group_from_ldap");
2371 if (ldap_state == NULL || map == NULL || entry == NULL ||
2372 ldap_state->smbldap_state->ldap_struct == NULL) {
2373 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
2374 TALLOC_FREE(ctx);
2375 return false;
2378 temp = smbldap_talloc_single_attribute(
2379 ldap_state->smbldap_state->ldap_struct,
2380 entry,
2381 get_attr_key2string(groupmap_attr_list,
2382 LDAP_ATTR_GIDNUMBER),
2383 ctx);
2384 if (!temp) {
2385 DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n",
2386 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GIDNUMBER)));
2387 TALLOC_FREE(ctx);
2388 return false;
2390 DEBUG(2, ("init_group_from_ldap: Entry found for group: %s\n", temp));
2392 map->gid = (gid_t)atol(temp);
2394 TALLOC_FREE(temp);
2395 temp = smbldap_talloc_single_attribute(
2396 ldap_state->smbldap_state->ldap_struct,
2397 entry,
2398 get_attr_key2string(groupmap_attr_list,
2399 LDAP_ATTR_GROUP_SID),
2400 ctx);
2401 if (!temp) {
2402 DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n",
2403 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID)));
2404 TALLOC_FREE(ctx);
2405 return false;
2408 if (!string_to_sid(&map->sid, temp)) {
2409 DEBUG(1, ("SID string [%s] could not be read as a valid SID\n", temp));
2410 TALLOC_FREE(ctx);
2411 return false;
2414 TALLOC_FREE(temp);
2415 temp = smbldap_talloc_single_attribute(
2416 ldap_state->smbldap_state->ldap_struct,
2417 entry,
2418 get_attr_key2string(groupmap_attr_list,
2419 LDAP_ATTR_GROUP_TYPE),
2420 ctx);
2421 if (!temp) {
2422 DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n",
2423 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE)));
2424 TALLOC_FREE(ctx);
2425 return false;
2427 map->sid_name_use = (enum lsa_SidType)atol(temp);
2429 if ((map->sid_name_use < SID_NAME_USER) ||
2430 (map->sid_name_use > SID_NAME_UNKNOWN)) {
2431 DEBUG(0, ("init_group_from_ldap: Unknown Group type: %d\n", map->sid_name_use));
2432 TALLOC_FREE(ctx);
2433 return false;
2436 TALLOC_FREE(temp);
2437 temp = smbldap_talloc_single_attribute(
2438 ldap_state->smbldap_state->ldap_struct,
2439 entry,
2440 get_attr_key2string(groupmap_attr_list,
2441 LDAP_ATTR_DISPLAY_NAME),
2442 ctx);
2443 if (!temp) {
2444 temp = smbldap_talloc_single_attribute(
2445 ldap_state->smbldap_state->ldap_struct,
2446 entry,
2447 get_attr_key2string(groupmap_attr_list,
2448 LDAP_ATTR_CN),
2449 ctx);
2450 if (!temp) {
2451 DEBUG(0, ("init_group_from_ldap: Attributes cn not found either \
2452 for gidNumber(%lu)\n",(unsigned long)map->gid));
2453 TALLOC_FREE(ctx);
2454 return false;
2457 map->nt_name = talloc_strdup(map, temp);
2458 if (!map->nt_name) {
2459 TALLOC_FREE(ctx);
2460 return false;
2463 TALLOC_FREE(temp);
2464 temp = smbldap_talloc_single_attribute(
2465 ldap_state->smbldap_state->ldap_struct,
2466 entry,
2467 get_attr_key2string(groupmap_attr_list,
2468 LDAP_ATTR_DESC),
2469 ctx);
2470 if (!temp) {
2471 temp = talloc_strdup(ctx, "");
2472 if (!temp) {
2473 TALLOC_FREE(ctx);
2474 return false;
2477 map->comment = talloc_strdup(map, temp);
2478 if (!map->comment) {
2479 TALLOC_FREE(ctx);
2480 return false;
2483 if (lp_parm_bool(-1, "ldapsam", "trusted", false)) {
2484 struct unixid id;
2485 id.id = map->gid;
2486 id.type = ID_TYPE_GID;
2488 idmap_cache_set_sid2unixid(&map->sid, &id);
2491 TALLOC_FREE(ctx);
2492 return true;
2495 /**********************************************************************
2496 *********************************************************************/
2498 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
2499 const char *filter,
2500 GROUP_MAP *map)
2502 struct ldapsam_privates *ldap_state =
2503 (struct ldapsam_privates *)methods->private_data;
2504 LDAPMessage *result = NULL;
2505 LDAPMessage *entry = NULL;
2506 int count;
2508 if (ldapsam_search_one_group(ldap_state, filter, &result)
2509 != LDAP_SUCCESS) {
2510 return NT_STATUS_NO_SUCH_GROUP;
2513 count = ldap_count_entries(priv2ld(ldap_state), result);
2515 if (count < 1) {
2516 DEBUG(4, ("ldapsam_getgroup: Did not find group, filter was "
2517 "%s\n", filter));
2518 ldap_msgfree(result);
2519 return NT_STATUS_NO_SUCH_GROUP;
2522 if (count > 1) {
2523 DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: "
2524 "count=%d\n", filter, count));
2525 ldap_msgfree(result);
2526 return NT_STATUS_NO_SUCH_GROUP;
2529 entry = ldap_first_entry(priv2ld(ldap_state), result);
2531 if (!entry) {
2532 ldap_msgfree(result);
2533 return NT_STATUS_UNSUCCESSFUL;
2536 if (!init_group_from_ldap(ldap_state, map, entry)) {
2537 DEBUG(1, ("ldapsam_getgroup: init_group_from_ldap failed for "
2538 "group filter %s\n", filter));
2539 ldap_msgfree(result);
2540 return NT_STATUS_NO_SUCH_GROUP;
2543 ldap_msgfree(result);
2544 return NT_STATUS_OK;
2547 /**********************************************************************
2548 *********************************************************************/
2550 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
2551 struct dom_sid sid)
2553 char *filter = NULL;
2554 NTSTATUS status;
2555 fstring tmp;
2557 if (asprintf(&filter, "(&(objectClass=%s)(%s=%s))",
2558 LDAP_OBJ_GROUPMAP,
2559 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID),
2560 sid_to_fstring(tmp, &sid)) < 0) {
2561 return NT_STATUS_NO_MEMORY;
2564 status = ldapsam_getgroup(methods, filter, map);
2565 SAFE_FREE(filter);
2566 return status;
2569 /**********************************************************************
2570 *********************************************************************/
2572 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
2573 gid_t gid)
2575 char *filter = NULL;
2576 NTSTATUS status;
2578 if (asprintf(&filter, "(&(objectClass=%s)(%s=%lu))",
2579 LDAP_OBJ_GROUPMAP,
2580 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
2581 (unsigned long)gid) < 0) {
2582 return NT_STATUS_NO_MEMORY;
2585 status = ldapsam_getgroup(methods, filter, map);
2586 SAFE_FREE(filter);
2587 return status;
2590 /**********************************************************************
2591 *********************************************************************/
2593 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
2594 const char *name)
2596 char *filter = NULL;
2597 char *escape_name = escape_ldap_string(talloc_tos(), name);
2598 NTSTATUS status;
2600 if (!escape_name) {
2601 return NT_STATUS_NO_MEMORY;
2604 if (asprintf(&filter, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))",
2605 LDAP_OBJ_GROUPMAP,
2606 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), escape_name,
2607 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN),
2608 escape_name) < 0) {
2609 TALLOC_FREE(escape_name);
2610 return NT_STATUS_NO_MEMORY;
2613 TALLOC_FREE(escape_name);
2614 status = ldapsam_getgroup(methods, filter, map);
2615 SAFE_FREE(filter);
2616 return status;
2619 static bool ldapsam_extract_rid_from_entry(LDAP *ldap_struct,
2620 LDAPMessage *entry,
2621 const struct dom_sid *domain_sid,
2622 uint32_t *rid)
2624 fstring str;
2625 struct dom_sid sid;
2627 if (!smbldap_get_single_attribute(ldap_struct, entry, "sambaSID",
2628 str, sizeof(str)-1)) {
2629 DEBUG(10, ("Could not find sambaSID attribute\n"));
2630 return False;
2633 if (!string_to_sid(&sid, str)) {
2634 DEBUG(10, ("Could not convert string %s to sid\n", str));
2635 return False;
2638 if (dom_sid_compare_domain(&sid, domain_sid) != 0) {
2639 DEBUG(10, ("SID %s is not in expected domain %s\n",
2640 str, sid_string_dbg(domain_sid)));
2641 return False;
2644 if (!sid_peek_rid(&sid, rid)) {
2645 DEBUG(10, ("Could not peek into RID\n"));
2646 return False;
2649 return True;
2652 static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
2653 TALLOC_CTX *mem_ctx,
2654 const struct dom_sid *group,
2655 uint32_t **pp_member_rids,
2656 size_t *p_num_members)
2658 struct ldapsam_privates *ldap_state =
2659 (struct ldapsam_privates *)methods->private_data;
2660 struct smbldap_state *conn = ldap_state->smbldap_state;
2661 const char *id_attrs[] = { "memberUid", "gidNumber", NULL };
2662 const char *sid_attrs[] = { "sambaSID", NULL };
2663 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2664 LDAPMessage *result = NULL;
2665 LDAPMessage *entry;
2666 char *filter;
2667 char **values = NULL;
2668 char **memberuid;
2669 char *gidstr;
2670 int rc, count;
2672 *pp_member_rids = NULL;
2673 *p_num_members = 0;
2675 filter = talloc_asprintf(mem_ctx,
2676 "(&(objectClass=%s)"
2677 "(objectClass=%s)"
2678 "(sambaSID=%s))",
2679 LDAP_OBJ_POSIXGROUP,
2680 LDAP_OBJ_GROUPMAP,
2681 sid_string_talloc(mem_ctx, group));
2682 if (filter == NULL) {
2683 ret = NT_STATUS_NO_MEMORY;
2684 goto done;
2687 rc = smbldap_search(conn, lp_ldap_suffix(),
2688 LDAP_SCOPE_SUBTREE, filter, id_attrs, 0,
2689 &result);
2691 if (rc != LDAP_SUCCESS)
2692 goto done;
2694 talloc_autofree_ldapmsg(mem_ctx, result);
2696 count = ldap_count_entries(conn->ldap_struct, result);
2698 if (count > 1) {
2699 DEBUG(1, ("Found more than one groupmap entry for %s\n",
2700 sid_string_dbg(group)));
2701 ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
2702 goto done;
2705 if (count == 0) {
2706 ret = NT_STATUS_NO_SUCH_GROUP;
2707 goto done;
2710 entry = ldap_first_entry(conn->ldap_struct, result);
2711 if (entry == NULL)
2712 goto done;
2714 gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", mem_ctx);
2715 if (!gidstr) {
2716 DEBUG (0, ("ldapsam_enum_group_members: Unable to find the group's gid!\n"));
2717 ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
2718 goto done;
2721 values = ldap_get_values(conn->ldap_struct, entry, "memberUid");
2723 if ((values != NULL) && (values[0] != NULL)) {
2725 filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(|", LDAP_OBJ_SAMBASAMACCOUNT);
2726 if (filter == NULL) {
2727 ret = NT_STATUS_NO_MEMORY;
2728 goto done;
2731 for (memberuid = values; *memberuid != NULL; memberuid += 1) {
2732 char *escape_memberuid;
2734 escape_memberuid = escape_ldap_string(talloc_tos(),
2735 *memberuid);
2736 if (escape_memberuid == NULL) {
2737 ret = NT_STATUS_NO_MEMORY;
2738 goto done;
2741 filter = talloc_asprintf_append_buffer(filter, "(uid=%s)", escape_memberuid);
2742 TALLOC_FREE(escape_memberuid);
2743 if (filter == NULL) {
2744 ret = NT_STATUS_NO_MEMORY;
2745 goto done;
2749 filter = talloc_asprintf_append_buffer(filter, "))");
2750 if (filter == NULL) {
2751 ret = NT_STATUS_NO_MEMORY;
2752 goto done;
2755 rc = smbldap_search(conn, lp_ldap_suffix(),
2756 LDAP_SCOPE_SUBTREE, filter, sid_attrs, 0,
2757 &result);
2759 if (rc != LDAP_SUCCESS)
2760 goto done;
2762 count = ldap_count_entries(conn->ldap_struct, result);
2763 DEBUG(10,("ldapsam_enum_group_members: found %d accounts\n", count));
2765 talloc_autofree_ldapmsg(mem_ctx, result);
2767 for (entry = ldap_first_entry(conn->ldap_struct, result);
2768 entry != NULL;
2769 entry = ldap_next_entry(conn->ldap_struct, entry))
2771 char *sidstr;
2772 struct dom_sid sid;
2773 uint32_t rid;
2775 sidstr = smbldap_talloc_single_attribute(conn->ldap_struct,
2776 entry, "sambaSID",
2777 mem_ctx);
2778 if (!sidstr) {
2779 DEBUG(0, ("Severe DB error, %s can't miss the sambaSID"
2780 "attribute\n", LDAP_OBJ_SAMBASAMACCOUNT));
2781 ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
2782 goto done;
2785 if (!string_to_sid(&sid, sidstr))
2786 goto done;
2788 if (!sid_check_is_in_our_domain(&sid)) {
2789 DEBUG(0, ("Inconsistent SAM -- group member uid not "
2790 "in our domain\n"));
2791 ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
2792 goto done;
2795 sid_peek_rid(&sid, &rid);
2797 if (!add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
2798 p_num_members)) {
2799 ret = NT_STATUS_NO_MEMORY;
2800 goto done;
2805 filter = talloc_asprintf(mem_ctx,
2806 "(&(objectClass=%s)"
2807 "(gidNumber=%s))",
2808 LDAP_OBJ_SAMBASAMACCOUNT,
2809 gidstr);
2811 rc = smbldap_search(conn, lp_ldap_suffix(),
2812 LDAP_SCOPE_SUBTREE, filter, sid_attrs, 0,
2813 &result);
2815 if (rc != LDAP_SUCCESS)
2816 goto done;
2818 talloc_autofree_ldapmsg(mem_ctx, result);
2820 for (entry = ldap_first_entry(conn->ldap_struct, result);
2821 entry != NULL;
2822 entry = ldap_next_entry(conn->ldap_struct, entry))
2824 uint32_t rid;
2826 if (!ldapsam_extract_rid_from_entry(conn->ldap_struct,
2827 entry,
2828 get_global_sam_sid(),
2829 &rid)) {
2830 DEBUG(0, ("Severe DB error, %s can't miss the samba SID" "attribute\n", LDAP_OBJ_SAMBASAMACCOUNT));
2831 ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
2832 goto done;
2835 if (!add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
2836 p_num_members)) {
2837 ret = NT_STATUS_NO_MEMORY;
2838 goto done;
2842 ret = NT_STATUS_OK;
2844 done:
2846 if (values)
2847 ldap_value_free(values);
2849 return ret;
2852 static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
2853 TALLOC_CTX *mem_ctx,
2854 struct samu *user,
2855 struct dom_sid **pp_sids,
2856 gid_t **pp_gids,
2857 uint32_t *p_num_groups)
2859 struct ldapsam_privates *ldap_state =
2860 (struct ldapsam_privates *)methods->private_data;
2861 struct smbldap_state *conn = ldap_state->smbldap_state;
2862 char *filter;
2863 const char *attrs[] = { "gidNumber", "sambaSID", NULL };
2864 char *escape_name;
2865 int rc, count;
2866 LDAPMessage *result = NULL;
2867 LDAPMessage *entry;
2868 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2869 uint32_t num_sids;
2870 uint32_t num_gids;
2871 char *gidstr;
2872 gid_t primary_gid = -1;
2874 *pp_sids = NULL;
2875 num_sids = 0;
2877 if (pdb_get_username(user) == NULL) {
2878 return NT_STATUS_INVALID_PARAMETER;
2881 escape_name = escape_ldap_string(talloc_tos(), pdb_get_username(user));
2882 if (escape_name == NULL)
2883 return NT_STATUS_NO_MEMORY;
2885 if (user->unix_pw) {
2886 primary_gid = user->unix_pw->pw_gid;
2887 } else {
2888 /* retrieve the users primary gid */
2889 filter = talloc_asprintf(mem_ctx,
2890 "(&(objectClass=%s)(uid=%s))",
2891 LDAP_OBJ_SAMBASAMACCOUNT,
2892 escape_name);
2893 if (filter == NULL) {
2894 ret = NT_STATUS_NO_MEMORY;
2895 goto done;
2898 rc = smbldap_search(conn, lp_ldap_suffix(),
2899 LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
2901 if (rc != LDAP_SUCCESS)
2902 goto done;
2904 talloc_autofree_ldapmsg(mem_ctx, result);
2906 count = ldap_count_entries(priv2ld(ldap_state), result);
2908 switch (count) {
2909 case 0:
2910 DEBUG(1, ("User account [%s] not found!\n", pdb_get_username(user)));
2911 ret = NT_STATUS_NO_SUCH_USER;
2912 goto done;
2913 case 1:
2914 entry = ldap_first_entry(priv2ld(ldap_state), result);
2916 gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", mem_ctx);
2917 if (!gidstr) {
2918 DEBUG (1, ("Unable to find the member's gid!\n"));
2919 ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
2920 goto done;
2922 primary_gid = strtoul(gidstr, NULL, 10);
2923 break;
2924 default:
2925 DEBUG(1, ("found more than one account with the same user name ?!\n"));
2926 ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
2927 goto done;
2931 filter = talloc_asprintf(mem_ctx,
2932 "(&(objectClass=%s)(|(memberUid=%s)(gidNumber=%u)))",
2933 LDAP_OBJ_POSIXGROUP, escape_name, (unsigned int)primary_gid);
2934 if (filter == NULL) {
2935 ret = NT_STATUS_NO_MEMORY;
2936 goto done;
2939 rc = smbldap_search(conn, lp_ldap_suffix(),
2940 LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
2942 if (rc != LDAP_SUCCESS)
2943 goto done;
2945 talloc_autofree_ldapmsg(mem_ctx, result);
2947 num_gids = 0;
2948 *pp_gids = NULL;
2950 num_sids = 0;
2951 *pp_sids = NULL;
2953 /* We need to add the primary group as the first gid/sid */
2955 if (!add_gid_to_array_unique(mem_ctx, primary_gid, pp_gids, &num_gids)) {
2956 ret = NT_STATUS_NO_MEMORY;
2957 goto done;
2960 /* This sid will be replaced later */
2962 ret = add_sid_to_array_unique(mem_ctx, &global_sid_NULL, pp_sids,
2963 &num_sids);
2964 if (!NT_STATUS_IS_OK(ret)) {
2965 goto done;
2968 for (entry = ldap_first_entry(conn->ldap_struct, result);
2969 entry != NULL;
2970 entry = ldap_next_entry(conn->ldap_struct, entry))
2972 fstring str;
2973 struct dom_sid sid;
2974 gid_t gid;
2975 char *end;
2977 if (!smbldap_get_single_attribute(conn->ldap_struct,
2978 entry, "sambaSID",
2979 str, sizeof(str)-1))
2980 continue;
2982 if (!string_to_sid(&sid, str))
2983 goto done;
2985 if (!smbldap_get_single_attribute(conn->ldap_struct,
2986 entry, "gidNumber",
2987 str, sizeof(str)-1))
2988 continue;
2990 gid = strtoul(str, &end, 10);
2992 if (PTR_DIFF(end, str) != strlen(str))
2993 goto done;
2995 if (gid == primary_gid) {
2996 sid_copy(&(*pp_sids)[0], &sid);
2997 } else {
2998 if (!add_gid_to_array_unique(mem_ctx, gid, pp_gids,
2999 &num_gids)) {
3000 ret = NT_STATUS_NO_MEMORY;
3001 goto done;
3003 ret = add_sid_to_array_unique(mem_ctx, &sid, pp_sids,
3004 &num_sids);
3005 if (!NT_STATUS_IS_OK(ret)) {
3006 goto done;
3011 if (dom_sid_compare(&global_sid_NULL, &(*pp_sids)[0]) == 0) {
3012 DEBUG(3, ("primary group of [%s] not found\n",
3013 pdb_get_username(user)));
3014 ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
3015 goto done;
3018 *p_num_groups = num_sids;
3020 ret = NT_STATUS_OK;
3022 done:
3024 TALLOC_FREE(escape_name);
3025 return ret;
3028 /**********************************************************************
3029 * Augment a posixGroup object with a sambaGroupMapping domgroup
3030 *********************************************************************/
3032 static NTSTATUS ldapsam_map_posixgroup(TALLOC_CTX *mem_ctx,
3033 struct ldapsam_privates *ldap_state,
3034 GROUP_MAP *map)
3036 const char *filter, *dn;
3037 LDAPMessage *msg, *entry;
3038 LDAPMod **mods;
3039 int rc;
3041 filter = talloc_asprintf(mem_ctx,
3042 "(&(objectClass=%s)(gidNumber=%u))",
3043 LDAP_OBJ_POSIXGROUP, (unsigned int)map->gid);
3044 if (filter == NULL) {
3045 return NT_STATUS_NO_MEMORY;
3048 rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
3049 get_attr_list(mem_ctx, groupmap_attr_list),
3050 &msg);
3051 talloc_autofree_ldapmsg(mem_ctx, msg);
3053 if ((rc != LDAP_SUCCESS) ||
3054 (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) != 1) ||
3055 ((entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg)) == NULL)) {
3056 return NT_STATUS_NO_SUCH_GROUP;
3059 dn = smbldap_talloc_dn(mem_ctx, ldap_state->smbldap_state->ldap_struct, entry);
3060 if (dn == NULL) {
3061 return NT_STATUS_NO_MEMORY;
3064 mods = NULL;
3065 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass",
3066 LDAP_OBJ_GROUPMAP);
3067 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaSid",
3068 sid_string_talloc(mem_ctx, &map->sid));
3069 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaGroupType",
3070 talloc_asprintf(mem_ctx, "%d", map->sid_name_use));
3071 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "displayName",
3072 map->nt_name);
3073 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "description",
3074 map->comment);
3075 talloc_autofree_ldapmod(mem_ctx, mods);
3077 rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
3078 if (rc != LDAP_SUCCESS) {
3079 return NT_STATUS_ACCESS_DENIED;
3082 return NT_STATUS_OK;
3085 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
3086 GROUP_MAP *map)
3088 struct ldapsam_privates *ldap_state =
3089 (struct ldapsam_privates *)methods->private_data;
3090 LDAPMessage *msg = NULL;
3091 LDAPMod **mods = NULL;
3092 const char *attrs[] = { NULL };
3093 char *filter;
3095 char *dn;
3096 TALLOC_CTX *mem_ctx;
3097 NTSTATUS result;
3099 struct dom_sid sid;
3101 int rc;
3103 mem_ctx = talloc_new(NULL);
3104 if (mem_ctx == NULL) {
3105 DEBUG(0, ("talloc_new failed\n"));
3106 return NT_STATUS_NO_MEMORY;
3109 filter = talloc_asprintf(mem_ctx, "(sambaSid=%s)",
3110 sid_string_talloc(mem_ctx, &map->sid));
3111 if (filter == NULL) {
3112 result = NT_STATUS_NO_MEMORY;
3113 goto done;
3116 rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_suffix(),
3117 LDAP_SCOPE_SUBTREE, filter, attrs, True, &msg);
3118 talloc_autofree_ldapmsg(mem_ctx, msg);
3120 if ((rc == LDAP_SUCCESS) &&
3121 (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) > 0)) {
3123 DEBUG(3, ("SID %s already present in LDAP, refusing to add "
3124 "group mapping entry\n", sid_string_dbg(&map->sid)));
3125 result = NT_STATUS_GROUP_EXISTS;
3126 goto done;
3129 switch (map->sid_name_use) {
3131 case SID_NAME_DOM_GRP:
3132 /* To map a domain group we need to have a posix group
3133 to attach to. */
3134 result = ldapsam_map_posixgroup(mem_ctx, ldap_state, map);
3135 goto done;
3136 break;
3138 case SID_NAME_ALIAS:
3139 if (!sid_check_is_in_our_domain(&map->sid)
3140 && !sid_check_is_in_builtin(&map->sid) )
3142 DEBUG(3, ("Refusing to map sid %s as an alias, not in our domain\n",
3143 sid_string_dbg(&map->sid)));
3144 result = NT_STATUS_INVALID_PARAMETER;
3145 goto done;
3147 break;
3149 default:
3150 DEBUG(3, ("Got invalid use '%s' for mapping\n",
3151 sid_type_lookup(map->sid_name_use)));
3152 result = NT_STATUS_INVALID_PARAMETER;
3153 goto done;
3156 /* Domain groups have been mapped in a separate routine, we have to
3157 * create an alias now */
3159 if (map->gid == -1) {
3160 DEBUG(10, ("Refusing to map gid==-1\n"));
3161 result = NT_STATUS_INVALID_PARAMETER;
3162 goto done;
3165 if (pdb_gid_to_sid(map->gid, &sid)) {
3166 DEBUG(3, ("Gid %u is already mapped to SID %s, refusing to "
3167 "add\n", (unsigned int)map->gid, sid_string_dbg(&sid)));
3168 result = NT_STATUS_GROUP_EXISTS;
3169 goto done;
3172 /* Ok, enough checks done. It's still racy to go ahead now, but that's
3173 * the best we can get out of LDAP. */
3175 dn = talloc_asprintf(mem_ctx, "sambaSid=%s,%s",
3176 sid_string_talloc(mem_ctx, &map->sid),
3177 lp_ldap_group_suffix());
3178 if (dn == NULL) {
3179 result = NT_STATUS_NO_MEMORY;
3180 goto done;
3183 mods = NULL;
3185 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "objectClass",
3186 LDAP_OBJ_SID_ENTRY);
3187 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "objectClass",
3188 LDAP_OBJ_GROUPMAP);
3189 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "sambaSid",
3190 sid_string_talloc(mem_ctx, &map->sid));
3191 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "sambaGroupType",
3192 talloc_asprintf(mem_ctx, "%d", map->sid_name_use));
3193 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "displayName",
3194 map->nt_name);
3195 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "description",
3196 map->comment);
3197 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "gidNumber",
3198 talloc_asprintf(mem_ctx, "%u", (unsigned int)map->gid));
3199 talloc_autofree_ldapmod(mem_ctx, mods);
3201 rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
3203 result = (rc == LDAP_SUCCESS) ?
3204 NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
3206 done:
3207 TALLOC_FREE(mem_ctx);
3208 return result;
3211 /**********************************************************************
3212 * Update a group mapping entry. We're quite strict about what can be changed:
3213 * Only the description and displayname may be changed. It simply does not
3214 * make any sense to change the SID, gid or the type in a mapping.
3215 *********************************************************************/
3217 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
3218 GROUP_MAP *map)
3220 struct ldapsam_privates *ldap_state =
3221 (struct ldapsam_privates *)methods->private_data;
3222 int rc;
3223 const char *filter, *dn;
3224 LDAPMessage *msg = NULL;
3225 LDAPMessage *entry = NULL;
3226 LDAPMod **mods = NULL;
3227 TALLOC_CTX *mem_ctx;
3228 NTSTATUS result;
3230 mem_ctx = talloc_new(NULL);
3231 if (mem_ctx == NULL) {
3232 DEBUG(0, ("talloc_new failed\n"));
3233 return NT_STATUS_NO_MEMORY;
3236 /* Make 100% sure that sid, gid and type are not changed by looking up
3237 * exactly the values we're given in LDAP. */
3239 filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)"
3240 "(sambaSid=%s)(gidNumber=%u)"
3241 "(sambaGroupType=%d))",
3242 LDAP_OBJ_GROUPMAP,
3243 sid_string_talloc(mem_ctx, &map->sid),
3244 (unsigned int)map->gid, map->sid_name_use);
3245 if (filter == NULL) {
3246 result = NT_STATUS_NO_MEMORY;
3247 goto done;
3250 rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
3251 get_attr_list(mem_ctx, groupmap_attr_list),
3252 &msg);
3253 talloc_autofree_ldapmsg(mem_ctx, msg);
3255 if ((rc != LDAP_SUCCESS) ||
3256 (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) != 1) ||
3257 ((entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg)) == NULL)) {
3258 result = NT_STATUS_NO_SUCH_GROUP;
3259 goto done;
3262 dn = smbldap_talloc_dn(mem_ctx, ldap_state->smbldap_state->ldap_struct, entry);
3264 if (dn == NULL) {
3265 result = NT_STATUS_NO_MEMORY;
3266 goto done;
3269 mods = NULL;
3270 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "displayName",
3271 map->nt_name);
3272 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "description",
3273 map->comment);
3274 talloc_autofree_ldapmod(mem_ctx, mods);
3276 if (mods == NULL) {
3277 DEBUG(4, ("ldapsam_update_group_mapping_entry: mods is empty: "
3278 "nothing to do\n"));
3279 result = NT_STATUS_OK;
3280 goto done;
3283 rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
3285 if (rc != LDAP_SUCCESS) {
3286 result = NT_STATUS_ACCESS_DENIED;
3287 goto done;
3290 DEBUG(2, ("ldapsam_update_group_mapping_entry: successfully modified "
3291 "group %lu in LDAP\n", (unsigned long)map->gid));
3293 result = NT_STATUS_OK;
3295 done:
3296 TALLOC_FREE(mem_ctx);
3297 return result;
3300 /**********************************************************************
3301 *********************************************************************/
3303 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
3304 struct dom_sid sid)
3306 struct ldapsam_privates *priv =
3307 (struct ldapsam_privates *)methods->private_data;
3308 LDAPMessage *msg, *entry;
3309 int rc;
3310 NTSTATUS result;
3311 TALLOC_CTX *mem_ctx;
3312 char *filter;
3314 mem_ctx = talloc_new(NULL);
3315 if (mem_ctx == NULL) {
3316 DEBUG(0, ("talloc_new failed\n"));
3317 return NT_STATUS_NO_MEMORY;
3320 filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=%s))",
3321 LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID,
3322 sid_string_talloc(mem_ctx, &sid));
3323 if (filter == NULL) {
3324 result = NT_STATUS_NO_MEMORY;
3325 goto done;
3327 rc = smbldap_search_suffix(priv->smbldap_state, filter,
3328 get_attr_list(mem_ctx, groupmap_attr_list),
3329 &msg);
3330 talloc_autofree_ldapmsg(mem_ctx, msg);
3332 if ((rc != LDAP_SUCCESS) ||
3333 (ldap_count_entries(priv2ld(priv), msg) != 1) ||
3334 ((entry = ldap_first_entry(priv2ld(priv), msg)) == NULL)) {
3335 result = NT_STATUS_NO_SUCH_GROUP;
3336 goto done;
3339 rc = ldapsam_delete_entry(priv, mem_ctx, entry, LDAP_OBJ_GROUPMAP,
3340 get_attr_list(mem_ctx,
3341 groupmap_attr_list_to_delete));
3343 if ((rc == LDAP_NAMING_VIOLATION) ||
3344 (rc == LDAP_NOT_ALLOWED_ON_RDN) ||
3345 (rc == LDAP_OBJECT_CLASS_VIOLATION)) {
3346 const char *attrs[] = { "sambaGroupType", "description",
3347 "displayName", "sambaSIDList",
3348 NULL };
3350 /* Second try. Don't delete the sambaSID attribute, this is
3351 for "old" entries that are tacked on a winbind
3352 sambaIdmapEntry. */
3354 rc = ldapsam_delete_entry(priv, mem_ctx, entry,
3355 LDAP_OBJ_GROUPMAP, attrs);
3358 if ((rc == LDAP_NAMING_VIOLATION) ||
3359 (rc == LDAP_NOT_ALLOWED_ON_RDN) ||
3360 (rc == LDAP_OBJECT_CLASS_VIOLATION)) {
3361 const char *attrs[] = { "sambaGroupType", "description",
3362 "displayName", "sambaSIDList",
3363 "gidNumber", NULL };
3365 /* Third try. This is a post-3.0.21 alias (containing only
3366 * sambaSidEntry and sambaGroupMapping classes), we also have
3367 * to delete the gidNumber attribute, only the sambaSidEntry
3368 * remains */
3370 rc = ldapsam_delete_entry(priv, mem_ctx, entry,
3371 LDAP_OBJ_GROUPMAP, attrs);
3374 result = (rc == LDAP_SUCCESS) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3376 done:
3377 TALLOC_FREE(mem_ctx);
3378 return result;
3381 /**********************************************************************
3382 *********************************************************************/
3384 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
3385 bool update)
3387 struct ldapsam_privates *ldap_state =
3388 (struct ldapsam_privates *)my_methods->private_data;
3389 char *filter = NULL;
3390 int rc;
3391 const char **attr_list;
3393 filter = talloc_asprintf(NULL, "(objectclass=%s)", LDAP_OBJ_GROUPMAP);
3394 if (!filter) {
3395 return NT_STATUS_NO_MEMORY;
3397 attr_list = get_attr_list( NULL, groupmap_attr_list );
3398 rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_suffix(),
3399 LDAP_SCOPE_SUBTREE, filter,
3400 attr_list, 0, &ldap_state->result);
3401 TALLOC_FREE(attr_list);
3403 if (rc != LDAP_SUCCESS) {
3404 DEBUG(0, ("ldapsam_setsamgrent: LDAP search failed: %s\n",
3405 ldap_err2string(rc)));
3406 DEBUG(3, ("ldapsam_setsamgrent: Query was: %s, %s\n",
3407 lp_ldap_suffix(), filter));
3408 ldap_msgfree(ldap_state->result);
3409 ldap_state->result = NULL;
3410 TALLOC_FREE(filter);
3411 return NT_STATUS_UNSUCCESSFUL;
3414 TALLOC_FREE(filter);
3416 DEBUG(2, ("ldapsam_setsamgrent: %d entries in the base!\n",
3417 ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
3418 ldap_state->result)));
3420 ldap_state->entry =
3421 ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
3422 ldap_state->result);
3423 ldap_state->index = 0;
3425 return NT_STATUS_OK;
3428 /**********************************************************************
3429 *********************************************************************/
3431 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
3433 ldapsam_endsampwent(my_methods);
3436 /**********************************************************************
3437 *********************************************************************/
3439 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
3440 GROUP_MAP *map)
3442 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
3443 struct ldapsam_privates *ldap_state =
3444 (struct ldapsam_privates *)my_methods->private_data;
3445 bool bret = False;
3447 while (!bret) {
3448 if (!ldap_state->entry)
3449 return ret;
3451 ldap_state->index++;
3452 bret = init_group_from_ldap(ldap_state, map,
3453 ldap_state->entry);
3455 ldap_state->entry =
3456 ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
3457 ldap_state->entry);
3460 return NT_STATUS_OK;
3463 /**********************************************************************
3464 *********************************************************************/
3466 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
3467 const struct dom_sid *domsid, enum lsa_SidType sid_name_use,
3468 GROUP_MAP ***pp_rmap,
3469 size_t *p_num_entries,
3470 bool unix_only)
3472 GROUP_MAP *map = NULL;
3473 size_t entries = 0;
3475 *p_num_entries = 0;
3476 *pp_rmap = NULL;
3478 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
3479 DEBUG(0, ("ldapsam_enum_group_mapping: Unable to open "
3480 "passdb\n"));
3481 return NT_STATUS_ACCESS_DENIED;
3484 while (true) {
3486 map = talloc_zero(NULL, GROUP_MAP);
3487 if (!map) {
3488 return NT_STATUS_NO_MEMORY;
3491 if (!NT_STATUS_IS_OK(ldapsam_getsamgrent(methods, map))) {
3492 TALLOC_FREE(map);
3493 break;
3496 if (sid_name_use != SID_NAME_UNKNOWN &&
3497 sid_name_use != map->sid_name_use) {
3498 DEBUG(11,("ldapsam_enum_group_mapping: group %s is "
3499 "not of the requested type\n",
3500 map->nt_name));
3501 continue;
3503 if (unix_only == ENUM_ONLY_MAPPED && map->gid == -1) {
3504 DEBUG(11,("ldapsam_enum_group_mapping: group %s is "
3505 "non mapped\n", map->nt_name));
3506 continue;
3509 *pp_rmap = talloc_realloc(NULL, *pp_rmap,
3510 GROUP_MAP *, entries + 1);
3511 if (!(*pp_rmap)) {
3512 DEBUG(0,("ldapsam_enum_group_mapping: Unable to "
3513 "enlarge group map!\n"));
3514 return NT_STATUS_UNSUCCESSFUL;
3517 (*pp_rmap)[entries] = talloc_move((*pp_rmap), &map);
3519 entries += 1;
3522 ldapsam_endsamgrent(methods);
3524 *p_num_entries = entries;
3526 return NT_STATUS_OK;
3529 static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
3530 const struct dom_sid *alias,
3531 const struct dom_sid *member,
3532 int modop)
3534 struct ldapsam_privates *ldap_state =
3535 (struct ldapsam_privates *)methods->private_data;
3536 char *dn = NULL;
3537 LDAPMessage *result = NULL;
3538 LDAPMessage *entry = NULL;
3539 int count;
3540 LDAPMod **mods = NULL;
3541 int rc;
3542 enum lsa_SidType type = SID_NAME_USE_NONE;
3543 fstring tmp;
3545 char *filter = NULL;
3547 if (sid_check_is_in_builtin(alias)) {
3548 type = SID_NAME_ALIAS;
3551 if (sid_check_is_in_our_domain(alias)) {
3552 type = SID_NAME_ALIAS;
3555 if (type == SID_NAME_USE_NONE) {
3556 DEBUG(5, ("SID %s is neither in builtin nor in our domain!\n",
3557 sid_string_dbg(alias)));
3558 return NT_STATUS_NO_SUCH_ALIAS;
3561 if (asprintf(&filter,
3562 "(&(objectClass=%s)(sambaSid=%s)(sambaGroupType=%d))",
3563 LDAP_OBJ_GROUPMAP, sid_to_fstring(tmp, alias),
3564 type) < 0) {
3565 return NT_STATUS_NO_MEMORY;
3568 if (ldapsam_search_one_group(ldap_state, filter,
3569 &result) != LDAP_SUCCESS) {
3570 SAFE_FREE(filter);
3571 return NT_STATUS_NO_SUCH_ALIAS;
3574 count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
3575 result);
3577 if (count < 1) {
3578 DEBUG(4, ("ldapsam_modify_aliasmem: Did not find alias\n"));
3579 ldap_msgfree(result);
3580 SAFE_FREE(filter);
3581 return NT_STATUS_NO_SUCH_ALIAS;
3584 if (count > 1) {
3585 DEBUG(1, ("ldapsam_modify_aliasmem: Duplicate entries for "
3586 "filter %s: count=%d\n", filter, count));
3587 ldap_msgfree(result);
3588 SAFE_FREE(filter);
3589 return NT_STATUS_NO_SUCH_ALIAS;
3592 SAFE_FREE(filter);
3594 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
3595 result);
3597 if (!entry) {
3598 ldap_msgfree(result);
3599 return NT_STATUS_UNSUCCESSFUL;
3602 dn = smbldap_talloc_dn(talloc_tos(), ldap_state->smbldap_state->ldap_struct, entry);
3603 if (!dn) {
3604 ldap_msgfree(result);
3605 return NT_STATUS_UNSUCCESSFUL;
3608 smbldap_set_mod(&mods, modop,
3609 get_attr_key2string(groupmap_attr_list,
3610 LDAP_ATTR_SID_LIST),
3611 sid_to_fstring(tmp, member));
3613 rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
3615 ldap_mods_free(mods, True);
3616 ldap_msgfree(result);
3617 TALLOC_FREE(dn);
3619 if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
3620 return NT_STATUS_MEMBER_IN_ALIAS;
3623 if (rc == LDAP_NO_SUCH_ATTRIBUTE) {
3624 return NT_STATUS_MEMBER_NOT_IN_ALIAS;
3627 if (rc != LDAP_SUCCESS) {
3628 return NT_STATUS_UNSUCCESSFUL;
3631 return NT_STATUS_OK;
3634 static NTSTATUS ldapsam_add_aliasmem(struct pdb_methods *methods,
3635 const struct dom_sid *alias,
3636 const struct dom_sid *member)
3638 return ldapsam_modify_aliasmem(methods, alias, member, LDAP_MOD_ADD);
3641 static NTSTATUS ldapsam_del_aliasmem(struct pdb_methods *methods,
3642 const struct dom_sid *alias,
3643 const struct dom_sid *member)
3645 return ldapsam_modify_aliasmem(methods, alias, member,
3646 LDAP_MOD_DELETE);
3649 static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
3650 const struct dom_sid *alias,
3651 TALLOC_CTX *mem_ctx,
3652 struct dom_sid **pp_members,
3653 size_t *p_num_members)
3655 struct ldapsam_privates *ldap_state =
3656 (struct ldapsam_privates *)methods->private_data;
3657 LDAPMessage *result = NULL;
3658 LDAPMessage *entry = NULL;
3659 int count;
3660 char **values = NULL;
3661 int i;
3662 char *filter = NULL;
3663 uint32_t num_members = 0;
3664 enum lsa_SidType type = SID_NAME_USE_NONE;
3665 fstring tmp;
3667 *pp_members = NULL;
3668 *p_num_members = 0;
3670 if (sid_check_is_in_builtin(alias)) {
3671 type = SID_NAME_ALIAS;
3674 if (sid_check_is_in_our_domain(alias)) {
3675 type = SID_NAME_ALIAS;
3678 if (type == SID_NAME_USE_NONE) {
3679 DEBUG(5, ("SID %s is neither in builtin nor in our domain!\n",
3680 sid_string_dbg(alias)));
3681 return NT_STATUS_NO_SUCH_ALIAS;
3684 if (asprintf(&filter,
3685 "(&(objectClass=%s)(sambaSid=%s)(sambaGroupType=%d))",
3686 LDAP_OBJ_GROUPMAP, sid_to_fstring(tmp, alias),
3687 type) < 0) {
3688 return NT_STATUS_NO_MEMORY;
3691 if (ldapsam_search_one_group(ldap_state, filter,
3692 &result) != LDAP_SUCCESS) {
3693 SAFE_FREE(filter);
3694 return NT_STATUS_NO_SUCH_ALIAS;
3697 count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
3698 result);
3700 if (count < 1) {
3701 DEBUG(4, ("ldapsam_enum_aliasmem: Did not find alias\n"));
3702 ldap_msgfree(result);
3703 SAFE_FREE(filter);
3704 return NT_STATUS_NO_SUCH_ALIAS;
3707 if (count > 1) {
3708 DEBUG(1, ("ldapsam_enum_aliasmem: Duplicate entries for "
3709 "filter %s: count=%d\n", filter, count));
3710 ldap_msgfree(result);
3711 SAFE_FREE(filter);
3712 return NT_STATUS_NO_SUCH_ALIAS;
3715 SAFE_FREE(filter);
3717 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
3718 result);
3720 if (!entry) {
3721 ldap_msgfree(result);
3722 return NT_STATUS_UNSUCCESSFUL;
3725 values = ldap_get_values(ldap_state->smbldap_state->ldap_struct,
3726 entry,
3727 get_attr_key2string(groupmap_attr_list,
3728 LDAP_ATTR_SID_LIST));
3730 if (values == NULL) {
3731 ldap_msgfree(result);
3732 return NT_STATUS_OK;
3735 count = ldap_count_values(values);
3737 for (i=0; i<count; i++) {
3738 struct dom_sid member;
3739 NTSTATUS status;
3741 if (!string_to_sid(&member, values[i]))
3742 continue;
3744 status = add_sid_to_array(mem_ctx, &member, pp_members,
3745 &num_members);
3746 if (!NT_STATUS_IS_OK(status)) {
3747 ldap_value_free(values);
3748 ldap_msgfree(result);
3749 return status;
3753 *p_num_members = num_members;
3754 ldap_value_free(values);
3755 ldap_msgfree(result);
3757 return NT_STATUS_OK;
3760 static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
3761 TALLOC_CTX *mem_ctx,
3762 const struct dom_sid *domain_sid,
3763 const struct dom_sid *members,
3764 size_t num_members,
3765 uint32_t **pp_alias_rids,
3766 size_t *p_num_alias_rids)
3768 struct ldapsam_privates *ldap_state =
3769 (struct ldapsam_privates *)methods->private_data;
3770 LDAP *ldap_struct;
3772 const char *attrs[] = { LDAP_ATTRIBUTE_SID, NULL };
3774 LDAPMessage *result = NULL;
3775 LDAPMessage *entry = NULL;
3776 int i;
3777 int rc;
3778 char *filter;
3779 enum lsa_SidType type = SID_NAME_USE_NONE;
3780 bool is_builtin = false;
3781 bool sid_added = false;
3783 *pp_alias_rids = NULL;
3784 *p_num_alias_rids = 0;
3786 if (sid_check_is_builtin(domain_sid)) {
3787 is_builtin = true;
3788 type = SID_NAME_ALIAS;
3791 if (sid_check_is_domain(domain_sid)) {
3792 type = SID_NAME_ALIAS;
3795 if (type == SID_NAME_USE_NONE) {
3796 DEBUG(5, ("SID %s is neither builtin nor domain!\n",
3797 sid_string_dbg(domain_sid)));
3798 return NT_STATUS_UNSUCCESSFUL;
3801 if (num_members == 0) {
3802 return NT_STATUS_OK;
3805 filter = talloc_asprintf(mem_ctx,
3806 "(&(objectclass=%s)(sambaGroupType=%d)(|",
3807 LDAP_OBJ_GROUPMAP, type);
3809 for (i=0; i<num_members; i++)
3810 filter = talloc_asprintf(mem_ctx, "%s(sambaSIDList=%s)",
3811 filter,
3812 sid_string_talloc(mem_ctx,
3813 &members[i]));
3815 filter = talloc_asprintf(mem_ctx, "%s))", filter);
3817 if (filter == NULL) {
3818 return NT_STATUS_NO_MEMORY;
3821 if (is_builtin &&
3822 ldap_state->search_cache.filter &&
3823 strcmp(ldap_state->search_cache.filter, filter) == 0) {
3824 filter = talloc_move(filter, &ldap_state->search_cache.filter);
3825 result = ldap_state->search_cache.result;
3826 ldap_state->search_cache.result = NULL;
3827 } else {
3828 rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_suffix(),
3829 LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
3830 if (rc != LDAP_SUCCESS) {
3831 return NT_STATUS_UNSUCCESSFUL;
3833 talloc_autofree_ldapmsg(filter, result);
3836 ldap_struct = ldap_state->smbldap_state->ldap_struct;
3838 for (entry = ldap_first_entry(ldap_struct, result);
3839 entry != NULL;
3840 entry = ldap_next_entry(ldap_struct, entry))
3842 fstring sid_str;
3843 struct dom_sid sid;
3844 uint32_t rid;
3846 if (!smbldap_get_single_attribute(ldap_struct, entry,
3847 LDAP_ATTRIBUTE_SID,
3848 sid_str,
3849 sizeof(sid_str)-1))
3850 continue;
3852 if (!string_to_sid(&sid, sid_str))
3853 continue;
3855 if (!sid_peek_check_rid(domain_sid, &sid, &rid))
3856 continue;
3858 sid_added = true;
3860 if (!add_rid_to_array_unique(mem_ctx, rid, pp_alias_rids,
3861 p_num_alias_rids)) {
3862 return NT_STATUS_NO_MEMORY;
3866 if (!is_builtin && !sid_added) {
3867 TALLOC_FREE(ldap_state->search_cache.filter);
3869 * Note: result is a talloc child of filter because of the
3870 * talloc_autofree_ldapmsg() usage
3872 ldap_state->search_cache.filter = talloc_move(ldap_state, &filter);
3873 ldap_state->search_cache.result = result;
3876 return NT_STATUS_OK;
3879 static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
3880 enum pdb_policy_type type,
3881 uint32_t value)
3883 NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
3884 int rc;
3885 LDAPMod **mods = NULL;
3886 fstring value_string;
3887 const char *policy_attr = NULL;
3889 struct ldapsam_privates *ldap_state =
3890 (struct ldapsam_privates *)methods->private_data;
3892 DEBUG(10,("ldapsam_set_account_policy_in_ldap\n"));
3894 if (!ldap_state->domain_dn) {
3895 return NT_STATUS_INVALID_PARAMETER;
3898 policy_attr = get_account_policy_attr(type);
3899 if (policy_attr == NULL) {
3900 DEBUG(0,("ldapsam_set_account_policy_in_ldap: invalid "
3901 "policy\n"));
3902 return ntstatus;
3905 slprintf(value_string, sizeof(value_string) - 1, "%i", value);
3907 smbldap_set_mod(&mods, LDAP_MOD_REPLACE, policy_attr, value_string);
3909 rc = smbldap_modify(ldap_state->smbldap_state, ldap_state->domain_dn,
3910 mods);
3912 ldap_mods_free(mods, True);
3914 if (rc != LDAP_SUCCESS) {
3915 return ntstatus;
3918 if (!cache_account_policy_set(type, value)) {
3919 DEBUG(0,("ldapsam_set_account_policy_in_ldap: failed to "
3920 "update local tdb cache\n"));
3921 return ntstatus;
3924 return NT_STATUS_OK;
3927 static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods,
3928 enum pdb_policy_type type,
3929 uint32_t value)
3931 return ldapsam_set_account_policy_in_ldap(methods, type,
3932 value);
3935 static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods,
3936 enum pdb_policy_type type,
3937 uint32_t *value)
3939 NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
3940 LDAPMessage *result = NULL;
3941 LDAPMessage *entry = NULL;
3942 int count;
3943 int rc;
3944 char **vals = NULL;
3945 char *filter;
3946 const char *policy_attr = NULL;
3948 struct ldapsam_privates *ldap_state =
3949 (struct ldapsam_privates *)methods->private_data;
3951 const char *attrs[2];
3953 DEBUG(10,("ldapsam_get_account_policy_from_ldap\n"));
3955 if (!ldap_state->domain_dn) {
3956 return NT_STATUS_INVALID_PARAMETER;
3959 policy_attr = get_account_policy_attr(type);
3960 if (!policy_attr) {
3961 DEBUG(0,("ldapsam_get_account_policy_from_ldap: invalid "
3962 "policy index: %d\n", type));
3963 return ntstatus;
3966 attrs[0] = policy_attr;
3967 attrs[1] = NULL;
3969 filter = talloc_asprintf(talloc_tos(), "(objectClass=%s)", LDAP_OBJ_DOMINFO);
3970 if (filter == NULL) {
3971 return NT_STATUS_NO_MEMORY;
3973 rc = smbldap_search(ldap_state->smbldap_state, ldap_state->domain_dn,
3974 LDAP_SCOPE_BASE, filter, attrs, 0,
3975 &result);
3976 TALLOC_FREE(filter);
3977 if (rc != LDAP_SUCCESS) {
3978 return ntstatus;
3981 count = ldap_count_entries(priv2ld(ldap_state), result);
3982 if (count < 1) {
3983 goto out;
3986 entry = ldap_first_entry(priv2ld(ldap_state), result);
3987 if (entry == NULL) {
3988 goto out;
3991 vals = ldap_get_values(priv2ld(ldap_state), entry, policy_attr);
3992 if (vals == NULL) {
3993 goto out;
3996 *value = (uint32_t)atol(vals[0]);
3998 ntstatus = NT_STATUS_OK;
4000 out:
4001 if (vals)
4002 ldap_value_free(vals);
4003 ldap_msgfree(result);
4005 return ntstatus;
4008 /* wrapper around ldapsam_get_account_policy_from_ldap(), handles tdb as cache
4010 - if user hasn't decided to use account policies inside LDAP just reuse the
4011 old tdb values
4013 - if there is a valid cache entry, return that
4014 - if there is an LDAP entry, update cache and return
4015 - otherwise set to default, update cache and return
4017 Guenther
4019 static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods,
4020 enum pdb_policy_type type,
4021 uint32_t *value)
4023 NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
4025 if (cache_account_policy_get(type, value)) {
4026 DEBUG(11,("ldapsam_get_account_policy: got valid value from "
4027 "cache\n"));
4028 return NT_STATUS_OK;
4031 ntstatus = ldapsam_get_account_policy_from_ldap(methods, type,
4032 value);
4033 if (NT_STATUS_IS_OK(ntstatus)) {
4034 goto update_cache;
4037 DEBUG(10,("ldapsam_get_account_policy: failed to retrieve from "
4038 "ldap\n"));
4040 #if 0
4041 /* should we automagically migrate old tdb value here ? */
4042 if (account_policy_get(type, value))
4043 goto update_ldap;
4045 DEBUG(10,("ldapsam_get_account_policy: no tdb for %d, trying "
4046 "default\n", type));
4047 #endif
4049 if (!account_policy_get_default(type, value)) {
4050 return ntstatus;
4053 /* update_ldap: */
4055 ntstatus = ldapsam_set_account_policy(methods, type, *value);
4056 if (!NT_STATUS_IS_OK(ntstatus)) {
4057 return ntstatus;
4060 update_cache:
4062 if (!cache_account_policy_set(type, *value)) {
4063 DEBUG(0,("ldapsam_get_account_policy: failed to update local "
4064 "tdb as a cache\n"));
4065 return NT_STATUS_UNSUCCESSFUL;
4068 return NT_STATUS_OK;
4071 static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
4072 const struct dom_sid *domain_sid,
4073 int num_rids,
4074 uint32_t *rids,
4075 const char **names,
4076 enum lsa_SidType *attrs)
4078 struct ldapsam_privates *ldap_state =
4079 (struct ldapsam_privates *)methods->private_data;
4080 LDAPMessage *msg = NULL;
4081 LDAPMessage *entry;
4082 char *allsids = NULL;
4083 int i, rc, num_mapped;
4084 NTSTATUS result = NT_STATUS_NO_MEMORY;
4085 TALLOC_CTX *mem_ctx;
4086 LDAP *ld;
4087 bool is_builtin;
4089 mem_ctx = talloc_new(NULL);
4090 if (mem_ctx == NULL) {
4091 DEBUG(0, ("talloc_new failed\n"));
4092 goto done;
4095 if (!sid_check_is_builtin(domain_sid) &&
4096 !sid_check_is_domain(domain_sid)) {
4097 result = NT_STATUS_INVALID_PARAMETER;
4098 goto done;
4101 if (num_rids == 0) {
4102 result = NT_STATUS_NONE_MAPPED;
4103 goto done;
4106 for (i=0; i<num_rids; i++)
4107 attrs[i] = SID_NAME_UNKNOWN;
4109 allsids = talloc_strdup(mem_ctx, "");
4110 if (allsids == NULL) {
4111 goto done;
4114 for (i=0; i<num_rids; i++) {
4115 struct dom_sid sid;
4116 sid_compose(&sid, domain_sid, rids[i]);
4117 allsids = talloc_asprintf_append_buffer(
4118 allsids, "(sambaSid=%s)",
4119 sid_string_talloc(mem_ctx, &sid));
4120 if (allsids == NULL) {
4121 goto done;
4125 /* First look for users */
4128 char *filter;
4129 const char *ldap_attrs[] = { "uid", "sambaSid", NULL };
4131 filter = talloc_asprintf(
4132 mem_ctx, ("(&(objectClass=%s)(|%s))"),
4133 LDAP_OBJ_SAMBASAMACCOUNT, allsids);
4135 if (filter == NULL) {
4136 goto done;
4139 rc = smbldap_search(ldap_state->smbldap_state,
4140 lp_ldap_user_suffix(),
4141 LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
4142 &msg);
4143 talloc_autofree_ldapmsg(mem_ctx, msg);
4146 if (rc != LDAP_SUCCESS)
4147 goto done;
4149 ld = ldap_state->smbldap_state->ldap_struct;
4150 num_mapped = 0;
4152 for (entry = ldap_first_entry(ld, msg);
4153 entry != NULL;
4154 entry = ldap_next_entry(ld, entry)) {
4155 uint32_t rid;
4156 int rid_index;
4157 const char *name;
4159 if (!ldapsam_extract_rid_from_entry(ld, entry, domain_sid,
4160 &rid)) {
4161 DEBUG(2, ("Could not find sid from ldap entry\n"));
4162 continue;
4165 name = smbldap_talloc_single_attribute(ld, entry, "uid",
4166 names);
4167 if (name == NULL) {
4168 DEBUG(2, ("Could not retrieve uid attribute\n"));
4169 continue;
4172 for (rid_index = 0; rid_index < num_rids; rid_index++) {
4173 if (rid == rids[rid_index])
4174 break;
4177 if (rid_index == num_rids) {
4178 DEBUG(2, ("Got a RID not asked for: %d\n", rid));
4179 continue;
4182 attrs[rid_index] = SID_NAME_USER;
4183 names[rid_index] = name;
4184 num_mapped += 1;
4187 if (num_mapped == num_rids) {
4188 /* No need to look for groups anymore -- we're done */
4189 result = NT_STATUS_OK;
4190 goto done;
4193 /* Same game for groups */
4196 char *filter;
4197 const char *ldap_attrs[] = { "cn", "displayName", "sambaSid",
4198 "sambaGroupType", NULL };
4200 filter = talloc_asprintf(
4201 mem_ctx, "(&(objectClass=%s)(|%s))",
4202 LDAP_OBJ_GROUPMAP, allsids);
4203 if (filter == NULL) {
4204 goto done;
4207 rc = smbldap_search(ldap_state->smbldap_state,
4208 lp_ldap_suffix(),
4209 LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
4210 &msg);
4211 talloc_autofree_ldapmsg(mem_ctx, msg);
4214 if (rc != LDAP_SUCCESS)
4215 goto done;
4217 /* ldap_struct might have changed due to a reconnect */
4219 ld = ldap_state->smbldap_state->ldap_struct;
4221 /* For consistency checks, we already checked we're only domain or builtin */
4223 is_builtin = sid_check_is_builtin(domain_sid);
4225 for (entry = ldap_first_entry(ld, msg);
4226 entry != NULL;
4227 entry = ldap_next_entry(ld, entry))
4229 uint32_t rid;
4230 int rid_index;
4231 const char *attr;
4232 enum lsa_SidType type;
4233 const char *dn = smbldap_talloc_dn(mem_ctx, ld, entry);
4235 attr = smbldap_talloc_single_attribute(ld, entry, "sambaGroupType",
4236 mem_ctx);
4237 if (attr == NULL) {
4238 DEBUG(2, ("Could not extract type from ldap entry %s\n",
4239 dn));
4240 continue;
4243 type = (enum lsa_SidType)atol(attr);
4245 /* Consistency checks */
4246 if ((is_builtin && (type != SID_NAME_ALIAS)) ||
4247 (!is_builtin && ((type != SID_NAME_ALIAS) &&
4248 (type != SID_NAME_DOM_GRP)))) {
4249 DEBUG(2, ("Rejecting invalid group mapping entry %s\n", dn));
4252 if (!ldapsam_extract_rid_from_entry(ld, entry, domain_sid,
4253 &rid)) {
4254 DEBUG(2, ("Could not find sid from ldap entry %s\n", dn));
4255 continue;
4258 attr = smbldap_talloc_single_attribute(ld, entry, "displayName", names);
4260 if (attr == NULL) {
4261 DEBUG(10, ("Could not retrieve 'displayName' attribute from %s\n",
4262 dn));
4263 attr = smbldap_talloc_single_attribute(ld, entry, "cn", names);
4266 if (attr == NULL) {
4267 DEBUG(2, ("Could not retrieve naming attribute from %s\n",
4268 dn));
4269 continue;
4272 for (rid_index = 0; rid_index < num_rids; rid_index++) {
4273 if (rid == rids[rid_index])
4274 break;
4277 if (rid_index == num_rids) {
4278 DEBUG(2, ("Got a RID not asked for: %d\n", rid));
4279 continue;
4282 attrs[rid_index] = type;
4283 names[rid_index] = attr;
4284 num_mapped += 1;
4287 result = NT_STATUS_NONE_MAPPED;
4289 if (num_mapped > 0)
4290 result = (num_mapped == num_rids) ?
4291 NT_STATUS_OK : STATUS_SOME_UNMAPPED;
4292 done:
4293 TALLOC_FREE(mem_ctx);
4294 return result;
4297 static char *get_ldap_filter(TALLOC_CTX *mem_ctx, const char *username)
4299 char *filter = NULL;
4300 char *escaped = NULL;
4301 char *result = NULL;
4303 if (asprintf(&filter, "(&%s(objectclass=%s))",
4304 "(uid=%u)", LDAP_OBJ_SAMBASAMACCOUNT) < 0) {
4305 goto done;
4308 escaped = escape_ldap_string(talloc_tos(), username);
4309 if (escaped == NULL) goto done;
4311 result = talloc_string_sub(mem_ctx, filter, "%u", username);
4313 done:
4314 SAFE_FREE(filter);
4315 TALLOC_FREE(escaped);
4317 return result;
4320 static const char **talloc_attrs(TALLOC_CTX *mem_ctx, ...)
4322 int i, num = 0;
4323 va_list ap;
4324 const char **result;
4326 va_start(ap, mem_ctx);
4327 while (va_arg(ap, const char *) != NULL)
4328 num += 1;
4329 va_end(ap);
4331 if ((result = talloc_array(mem_ctx, const char *, num+1)) == NULL) {
4332 return NULL;
4335 va_start(ap, mem_ctx);
4336 for (i=0; i<num; i++) {
4337 result[i] = talloc_strdup(result, va_arg(ap, const char*));
4338 if (result[i] == NULL) {
4339 talloc_free(result);
4340 va_end(ap);
4341 return NULL;
4344 va_end(ap);
4346 result[num] = NULL;
4347 return result;
4350 struct ldap_search_state {
4351 struct smbldap_state *connection;
4353 uint32_t acct_flags;
4354 uint16_t group_type;
4356 const char *base;
4357 int scope;
4358 const char *filter;
4359 const char **attrs;
4360 int attrsonly;
4361 void *pagedresults_cookie;
4363 LDAPMessage *entries, *current_entry;
4364 bool (*ldap2displayentry)(struct ldap_search_state *state,
4365 TALLOC_CTX *mem_ctx,
4366 LDAP *ld, LDAPMessage *entry,
4367 struct samr_displayentry *result);
4370 static bool ldapsam_search_firstpage(struct pdb_search *search)
4372 struct ldap_search_state *state =
4373 (struct ldap_search_state *)search->private_data;
4374 LDAP *ld;
4375 int rc = LDAP_OPERATIONS_ERROR;
4377 state->entries = NULL;
4379 if (state->connection->paged_results) {
4380 rc = smbldap_search_paged(state->connection, state->base,
4381 state->scope, state->filter,
4382 state->attrs, state->attrsonly,
4383 lp_ldap_page_size(), &state->entries,
4384 &state->pagedresults_cookie);
4387 if ((rc != LDAP_SUCCESS) || (state->entries == NULL)) {
4389 if (state->entries != NULL) {
4390 /* Left over from unsuccessful paged attempt */
4391 ldap_msgfree(state->entries);
4392 state->entries = NULL;
4395 rc = smbldap_search(state->connection, state->base,
4396 state->scope, state->filter, state->attrs,
4397 state->attrsonly, &state->entries);
4399 if ((rc != LDAP_SUCCESS) || (state->entries == NULL))
4400 return False;
4402 /* Ok, the server was lying. It told us it could do paged
4403 * searches when it could not. */
4404 state->connection->paged_results = False;
4407 ld = state->connection->ldap_struct;
4408 if ( ld == NULL) {
4409 DEBUG(5, ("Don't have an LDAP connection right after a "
4410 "search\n"));
4411 return False;
4413 state->current_entry = ldap_first_entry(ld, state->entries);
4415 return True;
4418 static bool ldapsam_search_nextpage(struct pdb_search *search)
4420 struct ldap_search_state *state =
4421 (struct ldap_search_state *)search->private_data;
4422 int rc;
4424 if (!state->connection->paged_results) {
4425 /* There is no next page when there are no paged results */
4426 return False;
4429 rc = smbldap_search_paged(state->connection, state->base,
4430 state->scope, state->filter, state->attrs,
4431 state->attrsonly, lp_ldap_page_size(),
4432 &state->entries,
4433 &state->pagedresults_cookie);
4435 if ((rc != LDAP_SUCCESS) || (state->entries == NULL))
4436 return False;
4438 state->current_entry = ldap_first_entry(state->connection->ldap_struct, state->entries);
4440 if (state->current_entry == NULL) {
4441 ldap_msgfree(state->entries);
4442 state->entries = NULL;
4443 return false;
4446 return True;
4449 static bool ldapsam_search_next_entry(struct pdb_search *search,
4450 struct samr_displayentry *entry)
4452 struct ldap_search_state *state =
4453 (struct ldap_search_state *)search->private_data;
4454 bool result;
4456 retry:
4457 if ((state->entries == NULL) && (state->pagedresults_cookie == NULL))
4458 return False;
4460 if ((state->entries == NULL) &&
4461 !ldapsam_search_nextpage(search))
4462 return False;
4464 if (state->current_entry == NULL) {
4465 return false;
4468 result = state->ldap2displayentry(state, search,
4469 state->connection->ldap_struct,
4470 state->current_entry, entry);
4472 if (!result) {
4473 char *dn;
4474 dn = ldap_get_dn(state->connection->ldap_struct, state->current_entry);
4475 DEBUG(5, ("Skipping entry %s\n", dn != NULL ? dn : "<NULL>"));
4476 if (dn != NULL) ldap_memfree(dn);
4479 state->current_entry = ldap_next_entry(state->connection->ldap_struct, state->current_entry);
4481 if (state->current_entry == NULL) {
4482 ldap_msgfree(state->entries);
4483 state->entries = NULL;
4486 if (!result) goto retry;
4488 return True;
4491 static void ldapsam_search_end(struct pdb_search *search)
4493 struct ldap_search_state *state =
4494 (struct ldap_search_state *)search->private_data;
4495 int rc;
4497 if (state->pagedresults_cookie == NULL)
4498 return;
4500 if (state->entries != NULL)
4501 ldap_msgfree(state->entries);
4503 state->entries = NULL;
4504 state->current_entry = NULL;
4506 if (!state->connection->paged_results)
4507 return;
4509 /* Tell the LDAP server we're not interested in the rest anymore. */
4511 rc = smbldap_search_paged(state->connection, state->base, state->scope,
4512 state->filter, state->attrs,
4513 state->attrsonly, 0, &state->entries,
4514 &state->pagedresults_cookie);
4516 if (rc != LDAP_SUCCESS)
4517 DEBUG(5, ("Could not end search properly\n"));
4519 return;
4522 static bool ldapuser2displayentry(struct ldap_search_state *state,
4523 TALLOC_CTX *mem_ctx,
4524 LDAP *ld, LDAPMessage *entry,
4525 struct samr_displayentry *result)
4527 char **vals;
4528 size_t converted_size;
4529 struct dom_sid sid;
4530 uint32_t acct_flags;
4532 vals = ldap_get_values(ld, entry, "sambaAcctFlags");
4533 if ((vals == NULL) || (vals[0] == NULL)) {
4534 DEBUG(5, ("\"sambaAcctFlags\" not found\n"));
4535 return False;
4537 acct_flags = pdb_decode_acct_ctrl(vals[0]);
4538 ldap_value_free(vals);
4540 if ((state->acct_flags != 0) &&
4541 ((state->acct_flags & acct_flags) == 0))
4542 return False;
4544 result->acct_flags = acct_flags;
4545 result->account_name = "";
4546 result->fullname = "";
4547 result->description = "";
4549 vals = ldap_get_values(ld, entry, "uid");
4550 if ((vals == NULL) || (vals[0] == NULL)) {
4551 DEBUG(5, ("\"uid\" not found\n"));
4552 return False;
4554 if (!pull_utf8_talloc(mem_ctx,
4555 discard_const_p(char *, &result->account_name),
4556 vals[0], &converted_size))
4558 DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s",
4559 strerror(errno)));
4562 ldap_value_free(vals);
4564 vals = ldap_get_values(ld, entry, "displayName");
4565 if ((vals == NULL) || (vals[0] == NULL))
4566 DEBUG(8, ("\"displayName\" not found\n"));
4567 else if (!pull_utf8_talloc(mem_ctx,
4568 discard_const_p(char *, &result->fullname),
4569 vals[0], &converted_size))
4571 DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s",
4572 strerror(errno)));
4575 ldap_value_free(vals);
4577 vals = ldap_get_values(ld, entry, "description");
4578 if ((vals == NULL) || (vals[0] == NULL))
4579 DEBUG(8, ("\"description\" not found\n"));
4580 else if (!pull_utf8_talloc(mem_ctx,
4581 discard_const_p(char *, &result->description),
4582 vals[0], &converted_size))
4584 DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s",
4585 strerror(errno)));
4588 ldap_value_free(vals);
4590 if ((result->account_name == NULL) ||
4591 (result->fullname == NULL) ||
4592 (result->description == NULL)) {
4593 DEBUG(0, ("talloc failed\n"));
4594 return False;
4597 vals = ldap_get_values(ld, entry, "sambaSid");
4598 if ((vals == NULL) || (vals[0] == NULL)) {
4599 DEBUG(0, ("\"objectSid\" not found\n"));
4600 return False;
4603 if (!string_to_sid(&sid, vals[0])) {
4604 DEBUG(0, ("Could not convert %s to SID\n", vals[0]));
4605 ldap_value_free(vals);
4606 return False;
4608 ldap_value_free(vals);
4610 if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)) {
4611 DEBUG(0, ("sid %s does not belong to our domain\n",
4612 sid_string_dbg(&sid)));
4613 return False;
4616 return True;
4620 static bool ldapsam_search_users(struct pdb_methods *methods,
4621 struct pdb_search *search,
4622 uint32_t acct_flags)
4624 struct ldapsam_privates *ldap_state =
4625 (struct ldapsam_privates *)methods->private_data;
4626 struct ldap_search_state *state;
4628 state = talloc(search, struct ldap_search_state);
4629 if (state == NULL) {
4630 DEBUG(0, ("talloc failed\n"));
4631 return False;
4634 state->connection = ldap_state->smbldap_state;
4636 if ((acct_flags != 0) && ((acct_flags & ACB_NORMAL) != 0))
4637 state->base = lp_ldap_user_suffix();
4638 else if ((acct_flags != 0) &&
4639 ((acct_flags & (ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) != 0))
4640 state->base = lp_ldap_machine_suffix();
4641 else
4642 state->base = lp_ldap_suffix();
4644 state->acct_flags = acct_flags;
4645 state->base = talloc_strdup(search, state->base);
4646 state->scope = LDAP_SCOPE_SUBTREE;
4647 state->filter = get_ldap_filter(search, "*");
4648 state->attrs = talloc_attrs(search, "uid", "sambaSid",
4649 "displayName", "description",
4650 "sambaAcctFlags", NULL);
4651 state->attrsonly = 0;
4652 state->pagedresults_cookie = NULL;
4653 state->entries = NULL;
4654 state->ldap2displayentry = ldapuser2displayentry;
4656 if ((state->filter == NULL) || (state->attrs == NULL)) {
4657 DEBUG(0, ("talloc failed\n"));
4658 return False;
4661 search->private_data = state;
4662 search->next_entry = ldapsam_search_next_entry;
4663 search->search_end = ldapsam_search_end;
4665 return ldapsam_search_firstpage(search);
4668 static bool ldapgroup2displayentry(struct ldap_search_state *state,
4669 TALLOC_CTX *mem_ctx,
4670 LDAP *ld, LDAPMessage *entry,
4671 struct samr_displayentry *result)
4673 char **vals;
4674 size_t converted_size;
4675 struct dom_sid sid;
4676 uint16_t group_type;
4678 result->account_name = "";
4679 result->fullname = "";
4680 result->description = "";
4683 vals = ldap_get_values(ld, entry, "sambaGroupType");
4684 if ((vals == NULL) || (vals[0] == NULL)) {
4685 DEBUG(5, ("\"sambaGroupType\" not found\n"));
4686 if (vals != NULL) {
4687 ldap_value_free(vals);
4689 return False;
4692 group_type = atoi(vals[0]);
4694 if ((state->group_type != 0) &&
4695 ((state->group_type != group_type))) {
4696 ldap_value_free(vals);
4697 return False;
4700 ldap_value_free(vals);
4702 /* display name is the NT group name */
4704 vals = ldap_get_values(ld, entry, "displayName");
4705 if ((vals == NULL) || (vals[0] == NULL)) {
4706 DEBUG(8, ("\"displayName\" not found\n"));
4708 /* fallback to the 'cn' attribute */
4709 vals = ldap_get_values(ld, entry, "cn");
4710 if ((vals == NULL) || (vals[0] == NULL)) {
4711 DEBUG(5, ("\"cn\" not found\n"));
4712 return False;
4714 if (!pull_utf8_talloc(mem_ctx,
4715 discard_const_p(char *,
4716 &result->account_name),
4717 vals[0], &converted_size))
4719 DEBUG(0,("ldapgroup2displayentry: pull_utf8_talloc "
4720 "failed: %s", strerror(errno)));
4723 else if (!pull_utf8_talloc(mem_ctx,
4724 discard_const_p(char *,
4725 &result->account_name),
4726 vals[0], &converted_size))
4728 DEBUG(0,("ldapgroup2displayentry: pull_utf8_talloc failed: %s",
4729 strerror(errno)));
4732 ldap_value_free(vals);
4734 vals = ldap_get_values(ld, entry, "description");
4735 if ((vals == NULL) || (vals[0] == NULL))
4736 DEBUG(8, ("\"description\" not found\n"));
4737 else if (!pull_utf8_talloc(mem_ctx,
4738 discard_const_p(char *, &result->description),
4739 vals[0], &converted_size))
4741 DEBUG(0,("ldapgroup2displayentry: pull_utf8_talloc failed: %s",
4742 strerror(errno)));
4744 ldap_value_free(vals);
4746 if ((result->account_name == NULL) ||
4747 (result->fullname == NULL) ||
4748 (result->description == NULL)) {
4749 DEBUG(0, ("talloc failed\n"));
4750 return False;
4753 vals = ldap_get_values(ld, entry, "sambaSid");
4754 if ((vals == NULL) || (vals[0] == NULL)) {
4755 DEBUG(0, ("\"objectSid\" not found\n"));
4756 if (vals != NULL) {
4757 ldap_value_free(vals);
4759 return False;
4762 if (!string_to_sid(&sid, vals[0])) {
4763 DEBUG(0, ("Could not convert %s to SID\n", vals[0]));
4764 return False;
4767 ldap_value_free(vals);
4769 switch (group_type) {
4770 case SID_NAME_DOM_GRP:
4771 case SID_NAME_ALIAS:
4773 if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)
4774 && !sid_peek_check_rid(&global_sid_Builtin, &sid, &result->rid))
4776 DEBUG(0, ("%s is not in our domain\n",
4777 sid_string_dbg(&sid)));
4778 return False;
4780 break;
4782 default:
4783 DEBUG(0,("unknown group type: %d\n", group_type));
4784 return False;
4787 result->acct_flags = 0;
4789 return True;
4792 static bool ldapsam_search_grouptype(struct pdb_methods *methods,
4793 struct pdb_search *search,
4794 const struct dom_sid *sid,
4795 enum lsa_SidType type)
4797 struct ldapsam_privates *ldap_state =
4798 (struct ldapsam_privates *)methods->private_data;
4799 struct ldap_search_state *state;
4800 fstring tmp;
4802 state = talloc(search, struct ldap_search_state);
4803 if (state == NULL) {
4804 DEBUG(0, ("talloc failed\n"));
4805 return False;
4808 state->connection = ldap_state->smbldap_state;
4810 state->base = talloc_strdup(search, lp_ldap_suffix());
4811 state->connection = ldap_state->smbldap_state;
4812 state->scope = LDAP_SCOPE_SUBTREE;
4813 state->filter = talloc_asprintf(search, "(&(objectclass=%s)"
4814 "(sambaGroupType=%d)(sambaSID=%s*))",
4815 LDAP_OBJ_GROUPMAP,
4816 type, sid_to_fstring(tmp, sid));
4817 state->attrs = talloc_attrs(search, "cn", "sambaSid",
4818 "displayName", "description",
4819 "sambaGroupType", NULL);
4820 state->attrsonly = 0;
4821 state->pagedresults_cookie = NULL;
4822 state->entries = NULL;
4823 state->group_type = type;
4824 state->ldap2displayentry = ldapgroup2displayentry;
4826 if ((state->filter == NULL) || (state->attrs == NULL)) {
4827 DEBUG(0, ("talloc failed\n"));
4828 return False;
4831 search->private_data = state;
4832 search->next_entry = ldapsam_search_next_entry;
4833 search->search_end = ldapsam_search_end;
4835 return ldapsam_search_firstpage(search);
4838 static bool ldapsam_search_groups(struct pdb_methods *methods,
4839 struct pdb_search *search)
4841 return ldapsam_search_grouptype(methods, search, get_global_sam_sid(), SID_NAME_DOM_GRP);
4844 static bool ldapsam_search_aliases(struct pdb_methods *methods,
4845 struct pdb_search *search,
4846 const struct dom_sid *sid)
4848 return ldapsam_search_grouptype(methods, search, sid, SID_NAME_ALIAS);
4851 static uint32_t ldapsam_capabilities(struct pdb_methods *methods)
4853 return PDB_CAP_STORE_RIDS;
4856 static NTSTATUS ldapsam_get_new_rid(struct ldapsam_privates *priv,
4857 uint32_t *rid)
4859 struct smbldap_state *smbldap_state = priv->smbldap_state;
4861 LDAPMessage *result = NULL;
4862 LDAPMessage *entry = NULL;
4863 LDAPMod **mods = NULL;
4864 NTSTATUS status;
4865 char *value;
4866 int rc;
4867 uint32_t nextRid = 0;
4868 const char *dn;
4870 TALLOC_CTX *mem_ctx;
4872 mem_ctx = talloc_new(NULL);
4873 if (mem_ctx == NULL) {
4874 DEBUG(0, ("talloc_new failed\n"));
4875 return NT_STATUS_NO_MEMORY;
4878 status = smbldap_search_domain_info(smbldap_state, &result,
4879 get_global_sam_name(), False);
4880 if (!NT_STATUS_IS_OK(status)) {
4881 DEBUG(3, ("Could not get domain info: %s\n",
4882 nt_errstr(status)));
4883 goto done;
4886 talloc_autofree_ldapmsg(mem_ctx, result);
4888 entry = ldap_first_entry(priv2ld(priv), result);
4889 if (entry == NULL) {
4890 DEBUG(0, ("Could not get domain info entry\n"));
4891 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4892 goto done;
4895 /* Find the largest of the three attributes "sambaNextRid",
4896 "sambaNextGroupRid" and "sambaNextUserRid". I gave up on the
4897 concept of differentiating between user and group rids, and will
4898 use only "sambaNextRid" in the future. But for compatibility
4899 reasons I look if others have chosen different strategies -- VL */
4901 value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
4902 "sambaNextRid", mem_ctx);
4903 if (value != NULL) {
4904 uint32_t tmp = (uint32_t)strtoul(value, NULL, 10);
4905 nextRid = MAX(nextRid, tmp);
4908 value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
4909 "sambaNextUserRid", mem_ctx);
4910 if (value != NULL) {
4911 uint32_t tmp = (uint32_t)strtoul(value, NULL, 10);
4912 nextRid = MAX(nextRid, tmp);
4915 value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
4916 "sambaNextGroupRid", mem_ctx);
4917 if (value != NULL) {
4918 uint32_t tmp = (uint32_t)strtoul(value, NULL, 10);
4919 nextRid = MAX(nextRid, tmp);
4922 if (nextRid == 0) {
4923 nextRid = BASE_RID-1;
4926 nextRid += 1;
4928 smbldap_make_mod(priv2ld(priv), entry, &mods, "sambaNextRid",
4929 talloc_asprintf(mem_ctx, "%d", nextRid));
4930 talloc_autofree_ldapmod(mem_ctx, mods);
4932 if ((dn = smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry)) == NULL) {
4933 status = NT_STATUS_NO_MEMORY;
4934 goto done;
4937 rc = smbldap_modify(smbldap_state, dn, mods);
4939 /* ACCESS_DENIED is used as a placeholder for "the modify failed,
4940 * please retry" */
4942 status = (rc == LDAP_SUCCESS) ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
4944 done:
4945 if (NT_STATUS_IS_OK(status)) {
4946 *rid = nextRid;
4949 TALLOC_FREE(mem_ctx);
4950 return status;
4953 static NTSTATUS ldapsam_new_rid_internal(struct pdb_methods *methods, uint32_t *rid)
4955 int i;
4957 for (i=0; i<10; i++) {
4958 NTSTATUS result = ldapsam_get_new_rid(
4959 (struct ldapsam_privates *)methods->private_data, rid);
4960 if (NT_STATUS_IS_OK(result)) {
4961 return result;
4964 if (!NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
4965 return result;
4968 /* The ldap update failed (maybe a race condition), retry */
4971 /* Tried 10 times, fail. */
4972 return NT_STATUS_ACCESS_DENIED;
4975 static bool ldapsam_new_rid(struct pdb_methods *methods, uint32_t *rid)
4977 NTSTATUS result = ldapsam_new_rid_internal(methods, rid);
4978 return NT_STATUS_IS_OK(result) ? True : False;
4981 static bool ldapsam_sid_to_id(struct pdb_methods *methods,
4982 const struct dom_sid *sid,
4983 struct unixid *id)
4985 struct ldapsam_privates *priv =
4986 (struct ldapsam_privates *)methods->private_data;
4987 char *filter;
4988 const char *attrs[] = { "sambaGroupType", "gidNumber", "uidNumber",
4989 NULL };
4990 LDAPMessage *result = NULL;
4991 LDAPMessage *entry = NULL;
4992 bool ret = False;
4993 char *value;
4994 int rc;
4996 TALLOC_CTX *mem_ctx;
4998 mem_ctx = talloc_new(NULL);
4999 if (mem_ctx == NULL) {
5000 DEBUG(0, ("talloc_new failed\n"));
5001 return False;
5004 filter = talloc_asprintf(mem_ctx,
5005 "(&(sambaSid=%s)"
5006 "(|(objectClass=%s)(objectClass=%s)))",
5007 sid_string_talloc(mem_ctx, sid),
5008 LDAP_OBJ_GROUPMAP, LDAP_OBJ_SAMBASAMACCOUNT);
5009 if (filter == NULL) {
5010 DEBUG(5, ("talloc_asprintf failed\n"));
5011 goto done;
5014 rc = smbldap_search_suffix(priv->smbldap_state, filter,
5015 attrs, &result);
5016 if (rc != LDAP_SUCCESS) {
5017 goto done;
5019 talloc_autofree_ldapmsg(mem_ctx, result);
5021 if (ldap_count_entries(priv2ld(priv), result) != 1) {
5022 DEBUG(10, ("Got %d entries, expected one\n",
5023 ldap_count_entries(priv2ld(priv), result)));
5024 goto done;
5027 entry = ldap_first_entry(priv2ld(priv), result);
5029 value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
5030 "sambaGroupType", mem_ctx);
5032 if (value != NULL) {
5033 const char *gid_str;
5034 /* It's a group */
5036 gid_str = smbldap_talloc_single_attribute(
5037 priv2ld(priv), entry, "gidNumber", mem_ctx);
5038 if (gid_str == NULL) {
5039 DEBUG(1, ("%s has sambaGroupType but no gidNumber\n",
5040 smbldap_talloc_dn(mem_ctx, priv2ld(priv),
5041 entry)));
5042 goto done;
5045 id->id = strtoul(gid_str, NULL, 10);
5046 id->type = ID_TYPE_GID;
5047 idmap_cache_set_sid2unixid(sid, id);
5048 ret = True;
5049 goto done;
5052 /* It must be a user */
5054 value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
5055 "uidNumber", mem_ctx);
5056 if (value == NULL) {
5057 DEBUG(1, ("Could not find uidNumber in %s\n",
5058 smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry)));
5059 goto done;
5062 id->id = strtoul(value, NULL, 10);
5063 id->type = ID_TYPE_UID;
5064 idmap_cache_set_sid2unixid(sid, id);
5066 ret = True;
5067 done:
5068 TALLOC_FREE(mem_ctx);
5069 return ret;
5073 * Find the SID for a uid.
5074 * This is shortcut is only used if ldapsam:trusted is set to true.
5076 static bool ldapsam_uid_to_sid(struct pdb_methods *methods, uid_t uid,
5077 struct dom_sid *sid)
5079 struct ldapsam_privates *priv =
5080 (struct ldapsam_privates *)methods->private_data;
5081 char *filter;
5082 const char *attrs[] = { "sambaSID", NULL };
5083 LDAPMessage *result = NULL;
5084 LDAPMessage *entry = NULL;
5085 bool ret = false;
5086 char *user_sid_string;
5087 struct dom_sid user_sid;
5088 int rc;
5089 TALLOC_CTX *tmp_ctx = talloc_stackframe();
5090 struct unixid id;
5092 filter = talloc_asprintf(tmp_ctx,
5093 "(&(uidNumber=%u)"
5094 "(objectClass=%s)"
5095 "(objectClass=%s))",
5096 (unsigned int)uid,
5097 LDAP_OBJ_POSIXACCOUNT,
5098 LDAP_OBJ_SAMBASAMACCOUNT);
5099 if (filter == NULL) {
5100 DEBUG(3, ("talloc_asprintf failed\n"));
5101 goto done;
5104 rc = smbldap_search_suffix(priv->smbldap_state, filter, attrs, &result);
5105 if (rc != LDAP_SUCCESS) {
5106 goto done;
5108 talloc_autofree_ldapmsg(tmp_ctx, result);
5110 if (ldap_count_entries(priv2ld(priv), result) != 1) {
5111 DEBUG(3, ("ERROR: Got %d entries for uid %u, expected one\n",
5112 ldap_count_entries(priv2ld(priv), result),
5113 (unsigned int)uid));
5114 goto done;
5117 entry = ldap_first_entry(priv2ld(priv), result);
5119 user_sid_string = smbldap_talloc_single_attribute(priv2ld(priv), entry,
5120 "sambaSID", tmp_ctx);
5121 if (user_sid_string == NULL) {
5122 DEBUG(1, ("Could not find sambaSID in object '%s'\n",
5123 smbldap_talloc_dn(tmp_ctx, priv2ld(priv), entry)));
5124 goto done;
5127 if (!string_to_sid(&user_sid, user_sid_string)) {
5128 DEBUG(3, ("Error calling sid_string_talloc for sid '%s'\n",
5129 user_sid_string));
5130 goto done;
5133 sid_copy(sid, &user_sid);
5135 id.id = uid;
5136 id.type = ID_TYPE_UID;
5138 idmap_cache_set_sid2unixid(sid, &id);
5140 ret = true;
5142 done:
5143 TALLOC_FREE(tmp_ctx);
5144 return ret;
5148 * Find the SID for a gid.
5149 * This is shortcut is only used if ldapsam:trusted is set to true.
5151 static bool ldapsam_gid_to_sid(struct pdb_methods *methods, gid_t gid,
5152 struct dom_sid *sid)
5154 struct ldapsam_privates *priv =
5155 (struct ldapsam_privates *)methods->private_data;
5156 char *filter;
5157 const char *attrs[] = { "sambaSID", NULL };
5158 LDAPMessage *result = NULL;
5159 LDAPMessage *entry = NULL;
5160 bool ret = false;
5161 char *group_sid_string;
5162 struct dom_sid group_sid;
5163 int rc;
5164 TALLOC_CTX *tmp_ctx = talloc_stackframe();
5165 struct unixid id;
5167 filter = talloc_asprintf(tmp_ctx,
5168 "(&(gidNumber=%u)"
5169 "(objectClass=%s))",
5170 (unsigned int)gid,
5171 LDAP_OBJ_GROUPMAP);
5172 if (filter == NULL) {
5173 DEBUG(3, ("talloc_asprintf failed\n"));
5174 goto done;
5177 rc = smbldap_search_suffix(priv->smbldap_state, filter, attrs, &result);
5178 if (rc != LDAP_SUCCESS) {
5179 goto done;
5181 talloc_autofree_ldapmsg(tmp_ctx, result);
5183 if (ldap_count_entries(priv2ld(priv), result) != 1) {
5184 DEBUG(3, ("ERROR: Got %d entries for gid %u, expected one\n",
5185 ldap_count_entries(priv2ld(priv), result),
5186 (unsigned int)gid));
5187 goto done;
5190 entry = ldap_first_entry(priv2ld(priv), result);
5192 group_sid_string = smbldap_talloc_single_attribute(priv2ld(priv), entry,
5193 "sambaSID", tmp_ctx);
5194 if (group_sid_string == NULL) {
5195 DEBUG(1, ("Could not find sambaSID in object '%s'\n",
5196 smbldap_talloc_dn(tmp_ctx, priv2ld(priv), entry)));
5197 goto done;
5200 if (!string_to_sid(&group_sid, group_sid_string)) {
5201 DEBUG(3, ("Error calling sid_string_talloc for sid '%s'\n",
5202 group_sid_string));
5203 goto done;
5206 sid_copy(sid, &group_sid);
5208 id.id = gid;
5209 id.type = ID_TYPE_GID;
5211 idmap_cache_set_sid2unixid(sid, &id);
5213 ret = true;
5215 done:
5216 TALLOC_FREE(tmp_ctx);
5217 return ret;
5222 * The following functions are called only if
5223 * ldapsam:trusted and ldapsam:editposix are
5224 * set to true
5228 * ldapsam_create_user creates a new
5229 * posixAccount and sambaSamAccount object
5230 * in the ldap users subtree
5232 * The uid is allocated by winbindd.
5235 static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
5236 TALLOC_CTX *tmp_ctx, const char *name,
5237 uint32_t acb_info, uint32_t *rid)
5239 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
5240 LDAPMessage *entry = NULL;
5241 LDAPMessage *result = NULL;
5242 uint32_t num_result;
5243 bool is_machine = False;
5244 bool add_posix = False;
5245 LDAPMod **mods = NULL;
5246 struct samu *user;
5247 char *filter;
5248 char *username;
5249 char *homedir;
5250 char *gidstr;
5251 char *uidstr;
5252 char *shell;
5253 const char *dn = NULL;
5254 struct dom_sid group_sid;
5255 struct dom_sid user_sid;
5256 gid_t gid = -1;
5257 uid_t uid = -1;
5258 NTSTATUS ret;
5259 int rc;
5261 if (((acb_info & ACB_NORMAL) && name[strlen(name)-1] == '$') ||
5262 acb_info & ACB_WSTRUST ||
5263 acb_info & ACB_SVRTRUST ||
5264 acb_info & ACB_DOMTRUST) {
5265 is_machine = True;
5268 username = escape_ldap_string(talloc_tos(), name);
5269 filter = talloc_asprintf(tmp_ctx, "(&(uid=%s)(objectClass=%s))",
5270 username, LDAP_OBJ_POSIXACCOUNT);
5271 TALLOC_FREE(username);
5273 rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
5274 if (rc != LDAP_SUCCESS) {
5275 DEBUG(0,("ldapsam_create_user: ldap search failed!\n"));
5276 return NT_STATUS_ACCESS_DENIED;
5278 talloc_autofree_ldapmsg(tmp_ctx, result);
5280 num_result = ldap_count_entries(priv2ld(ldap_state), result);
5282 if (num_result > 1) {
5283 DEBUG (0, ("ldapsam_create_user: More than one user with name [%s] ?!\n", name));
5284 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5287 if (num_result == 1) {
5288 char *tmp;
5289 /* check if it is just a posix account.
5290 * or if there is a sid attached to this entry
5293 entry = ldap_first_entry(priv2ld(ldap_state), result);
5294 if (!entry) {
5295 return NT_STATUS_UNSUCCESSFUL;
5298 tmp = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "sambaSID", tmp_ctx);
5299 if (tmp) {
5300 DEBUG (1, ("ldapsam_create_user: The user [%s] already exist!\n", name));
5301 return NT_STATUS_USER_EXISTS;
5304 /* it is just a posix account, retrieve the dn for later use */
5305 dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
5306 if (!dn) {
5307 DEBUG(0,("ldapsam_create_user: Out of memory!\n"));
5308 return NT_STATUS_NO_MEMORY;
5312 if (num_result == 0) {
5313 add_posix = True;
5316 /* Create the basic samu structure and generate the mods for the ldap commit */
5317 if (!NT_STATUS_IS_OK((ret = ldapsam_new_rid_internal(my_methods, rid)))) {
5318 DEBUG(1, ("ldapsam_create_user: Could not allocate a new RID\n"));
5319 return ret;
5322 sid_compose(&user_sid, get_global_sam_sid(), *rid);
5324 user = samu_new(tmp_ctx);
5325 if (!user) {
5326 DEBUG(1,("ldapsam_create_user: Unable to allocate user struct\n"));
5327 return NT_STATUS_NO_MEMORY;
5330 if (!pdb_set_username(user, name, PDB_SET)) {
5331 DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
5332 return NT_STATUS_UNSUCCESSFUL;
5334 if (!pdb_set_domain(user, get_global_sam_name(), PDB_SET)) {
5335 DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
5336 return NT_STATUS_UNSUCCESSFUL;
5338 if (is_machine) {
5339 if (acb_info & ACB_NORMAL) {
5340 if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_SET)) {
5341 DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
5342 return NT_STATUS_UNSUCCESSFUL;
5344 } else {
5345 if (!pdb_set_acct_ctrl(user, acb_info, PDB_SET)) {
5346 DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
5347 return NT_STATUS_UNSUCCESSFUL;
5350 } else {
5351 if (!pdb_set_acct_ctrl(user, ACB_NORMAL | ACB_DISABLED, PDB_SET)) {
5352 DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
5353 return NT_STATUS_UNSUCCESSFUL;
5357 if (!pdb_set_user_sid(user, &user_sid, PDB_SET)) {
5358 DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
5359 return NT_STATUS_UNSUCCESSFUL;
5362 if (!init_ldap_from_sam(ldap_state, entry, &mods, user, pdb_element_is_set_or_changed)) {
5363 DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
5364 return NT_STATUS_UNSUCCESSFUL;
5367 if (ldap_state->schema_ver != SCHEMAVER_SAMBASAMACCOUNT) {
5368 DEBUG(1,("ldapsam_create_user: Unsupported schema version\n"));
5370 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
5372 if (add_posix) {
5373 char *escape_name;
5375 DEBUG(3,("ldapsam_create_user: Creating new posix user\n"));
5377 /* retrieve the Domain Users group gid */
5378 if (!sid_compose(&group_sid, get_global_sam_sid(), DOMAIN_RID_USERS) ||
5379 !sid_to_gid(&group_sid, &gid)) {
5380 DEBUG (0, ("ldapsam_create_user: Unable to get the Domain Users gid: bailing out!\n"));
5381 return NT_STATUS_INVALID_PRIMARY_GROUP;
5384 /* lets allocate a new userid for this user */
5385 if (!winbind_allocate_uid(&uid)) {
5386 DEBUG (0, ("ldapsam_create_user: Unable to allocate a new user id: bailing out!\n"));
5387 return NT_STATUS_UNSUCCESSFUL;
5391 if (is_machine) {
5392 /* TODO: choose a more appropriate default for machines */
5393 homedir = talloc_sub_specified(tmp_ctx, lp_template_homedir(), "SMB_workstations_home", ldap_state->domain_name, uid, gid);
5394 shell = talloc_strdup(tmp_ctx, "/bin/false");
5395 } else {
5396 homedir = talloc_sub_specified(tmp_ctx, lp_template_homedir(), name, ldap_state->domain_name, uid, gid);
5397 shell = talloc_sub_specified(tmp_ctx, lp_template_shell(), name, ldap_state->domain_name, uid, gid);
5399 uidstr = talloc_asprintf(tmp_ctx, "%u", (unsigned int)uid);
5400 gidstr = talloc_asprintf(tmp_ctx, "%u", (unsigned int)gid);
5402 escape_name = escape_rdn_val_string_alloc(name);
5403 if (!escape_name) {
5404 DEBUG (0, ("ldapsam_create_user: Out of memory!\n"));
5405 return NT_STATUS_NO_MEMORY;
5408 if (is_machine) {
5409 dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", escape_name, lp_ldap_machine_suffix ());
5410 } else {
5411 dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", escape_name, lp_ldap_user_suffix ());
5414 SAFE_FREE(escape_name);
5416 if (!homedir || !shell || !uidstr || !gidstr || !dn) {
5417 DEBUG (0, ("ldapsam_create_user: Out of memory!\n"));
5418 return NT_STATUS_NO_MEMORY;
5421 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_ACCOUNT);
5422 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXACCOUNT);
5423 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
5424 smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
5425 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
5426 smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", homedir);
5427 smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", shell);
5430 talloc_autofree_ldapmod(tmp_ctx, mods);
5432 if (add_posix) {
5433 rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
5434 } else {
5435 rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
5438 if (rc != LDAP_SUCCESS) {
5439 DEBUG(0,("ldapsam_create_user: failed to create a new user [%s] (dn = %s)\n", name ,dn));
5440 return NT_STATUS_UNSUCCESSFUL;
5443 DEBUG(2,("ldapsam_create_user: added account [%s] in the LDAP database\n", name));
5445 flush_pwnam_cache();
5447 return NT_STATUS_OK;
5450 static NTSTATUS ldapsam_delete_user(struct pdb_methods *my_methods, TALLOC_CTX *tmp_ctx, struct samu *sam_acct)
5452 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
5453 LDAPMessage *result = NULL;
5454 LDAPMessage *entry = NULL;
5455 int num_result;
5456 const char *dn;
5457 char *filter;
5458 int rc;
5460 DEBUG(0,("ldapsam_delete_user: Attempt to delete user [%s]\n", pdb_get_username(sam_acct)));
5462 filter = talloc_asprintf(tmp_ctx,
5463 "(&(uid=%s)"
5464 "(objectClass=%s)"
5465 "(objectClass=%s))",
5466 pdb_get_username(sam_acct),
5467 LDAP_OBJ_POSIXACCOUNT,
5468 LDAP_OBJ_SAMBASAMACCOUNT);
5469 if (filter == NULL) {
5470 return NT_STATUS_NO_MEMORY;
5473 rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
5474 if (rc != LDAP_SUCCESS) {
5475 DEBUG(0,("ldapsam_delete_user: user search failed!\n"));
5476 return NT_STATUS_UNSUCCESSFUL;
5478 talloc_autofree_ldapmsg(tmp_ctx, result);
5480 num_result = ldap_count_entries(priv2ld(ldap_state), result);
5482 if (num_result == 0) {
5483 DEBUG(0,("ldapsam_delete_user: user not found!\n"));
5484 return NT_STATUS_NO_SUCH_USER;
5487 if (num_result > 1) {
5488 DEBUG (0, ("ldapsam_delete_user: More than one user with name [%s] ?!\n", pdb_get_username(sam_acct)));
5489 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5492 entry = ldap_first_entry(priv2ld(ldap_state), result);
5493 if (!entry) {
5494 return NT_STATUS_UNSUCCESSFUL;
5497 /* it is just a posix account, retrieve the dn for later use */
5498 dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
5499 if (!dn) {
5500 DEBUG(0,("ldapsam_delete_user: Out of memory!\n"));
5501 return NT_STATUS_NO_MEMORY;
5504 /* try to remove memberships first */
5506 NTSTATUS status;
5507 struct dom_sid *sids = NULL;
5508 gid_t *gids = NULL;
5509 uint32_t num_groups = 0;
5510 int i;
5511 uint32_t user_rid = pdb_get_user_rid(sam_acct);
5513 status = ldapsam_enum_group_memberships(my_methods,
5514 tmp_ctx,
5515 sam_acct,
5516 &sids,
5517 &gids,
5518 &num_groups);
5519 if (!NT_STATUS_IS_OK(status)) {
5520 goto delete_dn;
5523 for (i=0; i < num_groups; i++) {
5525 uint32_t group_rid;
5527 sid_peek_rid(&sids[i], &group_rid);
5529 ldapsam_del_groupmem(my_methods,
5530 tmp_ctx,
5531 group_rid,
5532 user_rid);
5536 delete_dn:
5538 rc = smbldap_delete(ldap_state->smbldap_state, dn);
5539 if (rc != LDAP_SUCCESS) {
5540 return NT_STATUS_UNSUCCESSFUL;
5543 flush_pwnam_cache();
5545 return NT_STATUS_OK;
5549 * ldapsam_create_group creates a new
5550 * posixGroup and sambaGroupMapping object
5551 * in the ldap groups subtree
5553 * The gid is allocated by winbindd.
5556 static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
5557 TALLOC_CTX *tmp_ctx,
5558 const char *name,
5559 uint32_t *rid)
5561 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
5562 NTSTATUS ret;
5563 LDAPMessage *entry = NULL;
5564 LDAPMessage *result = NULL;
5565 uint32_t num_result;
5566 bool is_new_entry = False;
5567 LDAPMod **mods = NULL;
5568 char *filter;
5569 char *groupsidstr;
5570 char *groupname;
5571 char *grouptype;
5572 char *gidstr;
5573 const char *dn = NULL;
5574 struct dom_sid group_sid;
5575 gid_t gid = -1;
5576 int rc;
5578 groupname = escape_ldap_string(talloc_tos(), name);
5579 filter = talloc_asprintf(tmp_ctx, "(&(cn=%s)(objectClass=%s))",
5580 groupname, LDAP_OBJ_POSIXGROUP);
5581 TALLOC_FREE(groupname);
5583 rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
5584 if (rc != LDAP_SUCCESS) {
5585 DEBUG(0,("ldapsam_create_group: ldap search failed!\n"));
5586 return NT_STATUS_UNSUCCESSFUL;
5588 talloc_autofree_ldapmsg(tmp_ctx, result);
5590 num_result = ldap_count_entries(priv2ld(ldap_state), result);
5592 if (num_result > 1) {
5593 DEBUG (0, ("ldapsam_create_group: There exists more than one group with name [%s]: bailing out!\n", name));
5594 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5597 if (num_result == 1) {
5598 char *tmp;
5599 /* check if it is just a posix group.
5600 * or if there is a sid attached to this entry
5603 entry = ldap_first_entry(priv2ld(ldap_state), result);
5604 if (!entry) {
5605 return NT_STATUS_UNSUCCESSFUL;
5608 tmp = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "sambaSID", tmp_ctx);
5609 if (tmp) {
5610 DEBUG (1, ("ldapsam_create_group: The group [%s] already exist!\n", name));
5611 return NT_STATUS_GROUP_EXISTS;
5614 /* it is just a posix group, retrieve the gid and the dn for later use */
5615 tmp = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", tmp_ctx);
5616 if (!tmp) {
5617 DEBUG (1, ("ldapsam_create_group: Couldn't retrieve the gidNumber for [%s]?!?!\n", name));
5618 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5621 gid = strtoul(tmp, NULL, 10);
5623 dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
5624 if (!dn) {
5625 DEBUG(0,("ldapsam_create_group: Out of memory!\n"));
5626 return NT_STATUS_NO_MEMORY;
5630 if (num_result == 0) {
5631 is_new_entry = true;
5634 if (!NT_STATUS_IS_OK((ret = ldapsam_new_rid_internal(my_methods, rid)))) {
5635 DEBUG(1, ("ldapsam_create_group: Could not allocate a new RID\n"));
5636 return ret;
5639 sid_compose(&group_sid, get_global_sam_sid(), *rid);
5641 groupsidstr = talloc_strdup(tmp_ctx, sid_string_talloc(tmp_ctx,
5642 &group_sid));
5643 grouptype = talloc_asprintf(tmp_ctx, "%d", SID_NAME_DOM_GRP);
5645 if (!groupsidstr || !grouptype) {
5646 DEBUG(0,("ldapsam_create_group: Out of memory!\n"));
5647 return NT_STATUS_NO_MEMORY;
5650 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
5651 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid", groupsidstr);
5652 smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", grouptype);
5653 smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", name);
5655 if (is_new_entry) {
5656 char *escape_name;
5658 DEBUG(3,("ldapsam_create_user: Creating new posix group\n"));
5660 /* lets allocate a new groupid for this group */
5661 if (!winbind_allocate_gid(&gid)) {
5662 DEBUG (0, ("ldapsam_create_group: Unable to allocate a new group id: bailing out!\n"));
5663 return NT_STATUS_UNSUCCESSFUL;
5666 gidstr = talloc_asprintf(tmp_ctx, "%u", (unsigned int)gid);
5668 escape_name = escape_rdn_val_string_alloc(name);
5669 if (!escape_name) {
5670 DEBUG (0, ("ldapsam_create_group: Out of memory!\n"));
5671 return NT_STATUS_NO_MEMORY;
5674 dn = talloc_asprintf(tmp_ctx, "cn=%s,%s", escape_name, lp_ldap_group_suffix());
5676 SAFE_FREE(escape_name);
5678 if (!gidstr || !dn) {
5679 DEBUG (0, ("ldapsam_create_group: Out of memory!\n"));
5680 return NT_STATUS_NO_MEMORY;
5683 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_POSIXGROUP);
5684 smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
5685 smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
5688 talloc_autofree_ldapmod(tmp_ctx, mods);
5690 if (is_new_entry) {
5691 rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
5692 #if 0
5693 if (rc == LDAP_OBJECT_CLASS_VIOLATION) {
5694 /* This call may fail with rfc2307bis schema */
5695 /* Retry adding a structural class */
5696 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", "????");
5697 rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
5699 #endif
5700 } else {
5701 rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
5704 if (rc != LDAP_SUCCESS) {
5705 DEBUG(0,("ldapsam_create_group: failed to create a new group [%s] (dn = %s)\n", name ,dn));
5706 return NT_STATUS_UNSUCCESSFUL;
5709 DEBUG(2,("ldapsam_create_group: added group [%s] in the LDAP database\n", name));
5711 return NT_STATUS_OK;
5714 static NTSTATUS ldapsam_delete_dom_group(struct pdb_methods *my_methods, TALLOC_CTX *tmp_ctx, uint32_t rid)
5716 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
5717 LDAPMessage *result = NULL;
5718 LDAPMessage *entry = NULL;
5719 int num_result;
5720 const char *dn;
5721 char *gidstr;
5722 char *filter;
5723 struct dom_sid group_sid;
5724 int rc;
5726 /* get the group sid */
5727 sid_compose(&group_sid, get_global_sam_sid(), rid);
5729 filter = talloc_asprintf(tmp_ctx,
5730 "(&(sambaSID=%s)"
5731 "(objectClass=%s)"
5732 "(objectClass=%s))",
5733 sid_string_talloc(tmp_ctx, &group_sid),
5734 LDAP_OBJ_POSIXGROUP,
5735 LDAP_OBJ_GROUPMAP);
5736 if (filter == NULL) {
5737 return NT_STATUS_NO_MEMORY;
5740 rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
5741 if (rc != LDAP_SUCCESS) {
5742 DEBUG(1,("ldapsam_delete_dom_group: group search failed!\n"));
5743 return NT_STATUS_UNSUCCESSFUL;
5745 talloc_autofree_ldapmsg(tmp_ctx, result);
5747 num_result = ldap_count_entries(priv2ld(ldap_state), result);
5749 if (num_result == 0) {
5750 DEBUG(1,("ldapsam_delete_dom_group: group not found!\n"));
5751 return NT_STATUS_NO_SUCH_GROUP;
5754 if (num_result > 1) {
5755 DEBUG (0, ("ldapsam_delete_dom_group: More than one group with the same SID ?!\n"));
5756 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5759 entry = ldap_first_entry(priv2ld(ldap_state), result);
5760 if (!entry) {
5761 return NT_STATUS_UNSUCCESSFUL;
5764 /* here it is, retrieve the dn for later use */
5765 dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
5766 if (!dn) {
5767 DEBUG(0,("ldapsam_delete_dom_group: Out of memory!\n"));
5768 return NT_STATUS_NO_MEMORY;
5771 gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", tmp_ctx);
5772 if (!gidstr) {
5773 DEBUG (0, ("ldapsam_delete_dom_group: Unable to find the group's gid!\n"));
5774 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5777 /* check no user have this group marked as primary group */
5778 filter = talloc_asprintf(tmp_ctx,
5779 "(&(gidNumber=%s)"
5780 "(objectClass=%s)"
5781 "(objectClass=%s))",
5782 gidstr,
5783 LDAP_OBJ_POSIXACCOUNT,
5784 LDAP_OBJ_SAMBASAMACCOUNT);
5786 rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
5787 if (rc != LDAP_SUCCESS) {
5788 DEBUG(1,("ldapsam_delete_dom_group: accounts search failed!\n"));
5789 return NT_STATUS_UNSUCCESSFUL;
5791 talloc_autofree_ldapmsg(tmp_ctx, result);
5793 num_result = ldap_count_entries(priv2ld(ldap_state), result);
5795 if (num_result != 0) {
5796 DEBUG(3,("ldapsam_delete_dom_group: Can't delete group, it is a primary group for %d users\n", num_result));
5797 return NT_STATUS_MEMBERS_PRIMARY_GROUP;
5800 rc = smbldap_delete(ldap_state->smbldap_state, dn);
5801 if (rc != LDAP_SUCCESS) {
5802 return NT_STATUS_UNSUCCESSFUL;
5805 return NT_STATUS_OK;
5808 static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods,
5809 TALLOC_CTX *tmp_ctx,
5810 uint32_t group_rid,
5811 uint32_t member_rid,
5812 int modop)
5814 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
5815 LDAPMessage *entry = NULL;
5816 LDAPMessage *result = NULL;
5817 uint32_t num_result;
5818 LDAPMod **mods = NULL;
5819 char *filter;
5820 char *uidstr;
5821 const char *dn = NULL;
5822 struct dom_sid group_sid;
5823 struct dom_sid member_sid;
5824 int rc;
5826 switch (modop) {
5827 case LDAP_MOD_ADD:
5828 DEBUG(1,("ldapsam_change_groupmem: add new member(rid=%d) to a domain group(rid=%d)", member_rid, group_rid));
5829 break;
5830 case LDAP_MOD_DELETE:
5831 DEBUG(1,("ldapsam_change_groupmem: delete member(rid=%d) from a domain group(rid=%d)", member_rid, group_rid));
5832 break;
5833 default:
5834 return NT_STATUS_UNSUCCESSFUL;
5837 /* get member sid */
5838 sid_compose(&member_sid, get_global_sam_sid(), member_rid);
5840 /* get the group sid */
5841 sid_compose(&group_sid, get_global_sam_sid(), group_rid);
5843 filter = talloc_asprintf(tmp_ctx,
5844 "(&(sambaSID=%s)"
5845 "(objectClass=%s)"
5846 "(objectClass=%s))",
5847 sid_string_talloc(tmp_ctx, &member_sid),
5848 LDAP_OBJ_POSIXACCOUNT,
5849 LDAP_OBJ_SAMBASAMACCOUNT);
5850 if (filter == NULL) {
5851 return NT_STATUS_NO_MEMORY;
5854 /* get the member uid */
5855 rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
5856 if (rc != LDAP_SUCCESS) {
5857 DEBUG(1,("ldapsam_change_groupmem: member search failed!\n"));
5858 return NT_STATUS_UNSUCCESSFUL;
5860 talloc_autofree_ldapmsg(tmp_ctx, result);
5862 num_result = ldap_count_entries(priv2ld(ldap_state), result);
5864 if (num_result == 0) {
5865 DEBUG(1,("ldapsam_change_groupmem: member not found!\n"));
5866 return NT_STATUS_NO_SUCH_MEMBER;
5869 if (num_result > 1) {
5870 DEBUG (0, ("ldapsam_change_groupmem: More than one account with the same SID ?!\n"));
5871 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5874 entry = ldap_first_entry(priv2ld(ldap_state), result);
5875 if (!entry) {
5876 return NT_STATUS_UNSUCCESSFUL;
5879 if (modop == LDAP_MOD_DELETE) {
5880 /* check if we are trying to remove the member from his primary group */
5881 char *gidstr;
5882 gid_t user_gid, group_gid;
5884 gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", tmp_ctx);
5885 if (!gidstr) {
5886 DEBUG (0, ("ldapsam_change_groupmem: Unable to find the member's gid!\n"));
5887 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5890 user_gid = strtoul(gidstr, NULL, 10);
5892 if (!sid_to_gid(&group_sid, &group_gid)) {
5893 DEBUG (0, ("ldapsam_change_groupmem: Unable to get group gid from SID!\n"));
5894 return NT_STATUS_UNSUCCESSFUL;
5897 if (user_gid == group_gid) {
5898 DEBUG (3, ("ldapsam_change_groupmem: can't remove user from its own primary group!\n"));
5899 return NT_STATUS_MEMBERS_PRIMARY_GROUP;
5903 /* here it is, retrieve the uid for later use */
5904 uidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "uid", tmp_ctx);
5905 if (!uidstr) {
5906 DEBUG (0, ("ldapsam_change_groupmem: Unable to find the member's name!\n"));
5907 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5910 filter = talloc_asprintf(tmp_ctx,
5911 "(&(sambaSID=%s)"
5912 "(objectClass=%s)"
5913 "(objectClass=%s))",
5914 sid_string_talloc(tmp_ctx, &group_sid),
5915 LDAP_OBJ_POSIXGROUP,
5916 LDAP_OBJ_GROUPMAP);
5918 /* get the group */
5919 rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
5920 if (rc != LDAP_SUCCESS) {
5921 DEBUG(1,("ldapsam_change_groupmem: group search failed!\n"));
5922 return NT_STATUS_UNSUCCESSFUL;
5924 talloc_autofree_ldapmsg(tmp_ctx, result);
5926 num_result = ldap_count_entries(priv2ld(ldap_state), result);
5928 if (num_result == 0) {
5929 DEBUG(1,("ldapsam_change_groupmem: group not found!\n"));
5930 return NT_STATUS_NO_SUCH_GROUP;
5933 if (num_result > 1) {
5934 DEBUG (0, ("ldapsam_change_groupmem: More than one group with the same SID ?!\n"));
5935 return NT_STATUS_INTERNAL_DB_CORRUPTION;
5938 entry = ldap_first_entry(priv2ld(ldap_state), result);
5939 if (!entry) {
5940 return NT_STATUS_UNSUCCESSFUL;
5943 /* here it is, retrieve the dn for later use */
5944 dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
5945 if (!dn) {
5946 DEBUG(0,("ldapsam_change_groupmem: Out of memory!\n"));
5947 return NT_STATUS_NO_MEMORY;
5950 smbldap_set_mod(&mods, modop, "memberUid", uidstr);
5952 talloc_autofree_ldapmod(tmp_ctx, mods);
5954 rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
5955 if (rc != LDAP_SUCCESS) {
5956 if (rc == LDAP_TYPE_OR_VALUE_EXISTS && modop == LDAP_MOD_ADD) {
5957 DEBUG(1,("ldapsam_change_groupmem: member is already in group, add failed!\n"));
5958 return NT_STATUS_MEMBER_IN_GROUP;
5960 if (rc == LDAP_NO_SUCH_ATTRIBUTE && modop == LDAP_MOD_DELETE) {
5961 DEBUG(1,("ldapsam_change_groupmem: member is not in group, delete failed!\n"));
5962 return NT_STATUS_MEMBER_NOT_IN_GROUP;
5964 return NT_STATUS_UNSUCCESSFUL;
5967 return NT_STATUS_OK;
5970 static NTSTATUS ldapsam_add_groupmem(struct pdb_methods *my_methods,
5971 TALLOC_CTX *tmp_ctx,
5972 uint32_t group_rid,
5973 uint32_t member_rid)
5975 return ldapsam_change_groupmem(my_methods, tmp_ctx, group_rid, member_rid, LDAP_MOD_ADD);
5977 static NTSTATUS ldapsam_del_groupmem(struct pdb_methods *my_methods,
5978 TALLOC_CTX *tmp_ctx,
5979 uint32_t group_rid,
5980 uint32_t member_rid)
5982 return ldapsam_change_groupmem(my_methods, tmp_ctx, group_rid, member_rid, LDAP_MOD_DELETE);
5985 static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
5986 TALLOC_CTX *mem_ctx,
5987 struct samu *sampass)
5989 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
5990 LDAPMessage *entry = NULL;
5991 LDAPMessage *result = NULL;
5992 uint32_t num_result;
5993 LDAPMod **mods = NULL;
5994 char *filter;
5995 char *escape_username;
5996 char *gidstr;
5997 const char *dn = NULL;
5998 gid_t gid;
5999 int rc;
6001 DEBUG(0,("ldapsam_set_primary_group: Attempt to set primary group for user [%s]\n", pdb_get_username(sampass)));
6003 if (!sid_to_gid(pdb_get_group_sid(sampass), &gid)) {
6004 DEBUG(0,("ldapsam_set_primary_group: failed to retrieve gid from user's group SID!\n"));
6005 return NT_STATUS_UNSUCCESSFUL;
6007 gidstr = talloc_asprintf(mem_ctx, "%u", (unsigned int)gid);
6008 if (!gidstr) {
6009 DEBUG(0,("ldapsam_set_primary_group: Out of Memory!\n"));
6010 return NT_STATUS_NO_MEMORY;
6013 escape_username = escape_ldap_string(talloc_tos(),
6014 pdb_get_username(sampass));
6015 if (escape_username== NULL) {
6016 return NT_STATUS_NO_MEMORY;
6019 filter = talloc_asprintf(mem_ctx,
6020 "(&(uid=%s)"
6021 "(objectClass=%s)"
6022 "(objectClass=%s))",
6023 escape_username,
6024 LDAP_OBJ_POSIXACCOUNT,
6025 LDAP_OBJ_SAMBASAMACCOUNT);
6027 TALLOC_FREE(escape_username);
6029 if (filter == NULL) {
6030 return NT_STATUS_NO_MEMORY;
6033 rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
6034 if (rc != LDAP_SUCCESS) {
6035 DEBUG(0,("ldapsam_set_primary_group: user search failed!\n"));
6036 return NT_STATUS_UNSUCCESSFUL;
6038 talloc_autofree_ldapmsg(mem_ctx, result);
6040 num_result = ldap_count_entries(priv2ld(ldap_state), result);
6042 if (num_result == 0) {
6043 DEBUG(0,("ldapsam_set_primary_group: user not found!\n"));
6044 return NT_STATUS_NO_SUCH_USER;
6047 if (num_result > 1) {
6048 DEBUG (0, ("ldapsam_set_primary_group: More than one user with name [%s] ?!\n", pdb_get_username(sampass)));
6049 return NT_STATUS_INTERNAL_DB_CORRUPTION;
6052 entry = ldap_first_entry(priv2ld(ldap_state), result);
6053 if (!entry) {
6054 return NT_STATUS_UNSUCCESSFUL;
6057 /* retrieve the dn for later use */
6058 dn = smbldap_talloc_dn(mem_ctx, priv2ld(ldap_state), entry);
6059 if (!dn) {
6060 DEBUG(0,("ldapsam_set_primary_group: Out of memory!\n"));
6061 return NT_STATUS_NO_MEMORY;
6064 /* remove the old one, and add the new one, this way we do not risk races */
6065 smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "gidNumber", gidstr);
6067 if (mods == NULL) {
6068 return NT_STATUS_OK;
6071 rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
6073 if (rc != LDAP_SUCCESS) {
6074 DEBUG(0,("ldapsam_set_primary_group: failed to modify [%s] primary group to [%s]\n",
6075 pdb_get_username(sampass), gidstr));
6076 return NT_STATUS_UNSUCCESSFUL;
6079 flush_pwnam_cache();
6081 return NT_STATUS_OK;
6085 /**********************************************************************
6086 trusted domains functions
6087 *********************************************************************/
6089 static char *trusteddom_dn(struct ldapsam_privates *ldap_state,
6090 const char *domain)
6092 return talloc_asprintf(talloc_tos(), "sambaDomainName=%s,%s", domain,
6093 ldap_state->domain_dn);
6096 static bool get_trusteddom_pw_int(struct ldapsam_privates *ldap_state,
6097 TALLOC_CTX *mem_ctx,
6098 const char *domain, LDAPMessage **entry)
6100 int rc;
6101 char *filter;
6102 int scope = LDAP_SCOPE_SUBTREE;
6103 const char **attrs = NULL; /* NULL: get all attrs */
6104 int attrsonly = 0; /* 0: return values too */
6105 LDAPMessage *result = NULL;
6106 char *trusted_dn;
6107 uint32_t num_result;
6109 filter = talloc_asprintf(talloc_tos(),
6110 "(&(objectClass=%s)(sambaDomainName=%s))",
6111 LDAP_OBJ_TRUSTDOM_PASSWORD, domain);
6113 trusted_dn = trusteddom_dn(ldap_state, domain);
6114 if (trusted_dn == NULL) {
6115 return False;
6117 rc = smbldap_search(ldap_state->smbldap_state, trusted_dn, scope,
6118 filter, attrs, attrsonly, &result);
6120 if (result != NULL) {
6121 talloc_autofree_ldapmsg(mem_ctx, result);
6124 if (rc == LDAP_NO_SUCH_OBJECT) {
6125 *entry = NULL;
6126 return True;
6129 if (rc != LDAP_SUCCESS) {
6130 return False;
6133 num_result = ldap_count_entries(priv2ld(ldap_state), result);
6135 if (num_result > 1) {
6136 DEBUG(1, ("ldapsam_get_trusteddom_pw: more than one "
6137 "%s object for domain '%s'?!\n",
6138 LDAP_OBJ_TRUSTDOM_PASSWORD, domain));
6139 return False;
6142 if (num_result == 0) {
6143 DEBUG(1, ("ldapsam_get_trusteddom_pw: no "
6144 "%s object for domain %s.\n",
6145 LDAP_OBJ_TRUSTDOM_PASSWORD, domain));
6146 *entry = NULL;
6147 } else {
6148 *entry = ldap_first_entry(priv2ld(ldap_state), result);
6151 return True;
6154 static bool ldapsam_get_trusteddom_pw(struct pdb_methods *methods,
6155 const char *domain,
6156 char** pwd,
6157 struct dom_sid *sid,
6158 time_t *pass_last_set_time)
6160 struct ldapsam_privates *ldap_state =
6161 (struct ldapsam_privates *)methods->private_data;
6162 LDAPMessage *entry = NULL;
6164 DEBUG(10, ("ldapsam_get_trusteddom_pw called for domain %s\n", domain));
6166 if (!get_trusteddom_pw_int(ldap_state, talloc_tos(), domain, &entry) ||
6167 (entry == NULL))
6169 return False;
6172 /* password */
6173 if (pwd != NULL) {
6174 char *pwd_str;
6175 pwd_str = smbldap_talloc_single_attribute(priv2ld(ldap_state),
6176 entry, "sambaClearTextPassword", talloc_tos());
6177 if (pwd_str == NULL) {
6178 return False;
6180 /* trusteddom_pw routines do not use talloc yet... */
6181 *pwd = SMB_STRDUP(pwd_str);
6182 if (*pwd == NULL) {
6183 return False;
6187 /* last change time */
6188 if (pass_last_set_time != NULL) {
6189 char *time_str;
6190 time_str = smbldap_talloc_single_attribute(priv2ld(ldap_state),
6191 entry, "sambaPwdLastSet", talloc_tos());
6192 if (time_str == NULL) {
6193 return False;
6195 *pass_last_set_time = (time_t)atol(time_str);
6198 /* domain sid */
6199 if (sid != NULL) {
6200 char *sid_str;
6201 struct dom_sid dom_sid;
6202 sid_str = smbldap_talloc_single_attribute(priv2ld(ldap_state),
6203 entry, "sambaSID",
6204 talloc_tos());
6205 if (sid_str == NULL) {
6206 return False;
6208 if (!string_to_sid(&dom_sid, sid_str)) {
6209 return False;
6211 sid_copy(sid, &dom_sid);
6214 return True;
6217 static bool ldapsam_set_trusteddom_pw(struct pdb_methods *methods,
6218 const char* domain,
6219 const char* pwd,
6220 const struct dom_sid *sid)
6222 struct ldapsam_privates *ldap_state =
6223 (struct ldapsam_privates *)methods->private_data;
6224 LDAPMessage *entry = NULL;
6225 LDAPMod **mods = NULL;
6226 char *prev_pwd = NULL;
6227 char *trusted_dn = NULL;
6228 int rc;
6230 DEBUG(10, ("ldapsam_set_trusteddom_pw called for domain %s\n", domain));
6233 * get the current entry (if there is one) in order to put the
6234 * current password into the previous password attribute
6236 if (!get_trusteddom_pw_int(ldap_state, talloc_tos(), domain, &entry)) {
6237 return False;
6240 mods = NULL;
6241 smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "objectClass",
6242 LDAP_OBJ_TRUSTDOM_PASSWORD);
6243 smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "sambaDomainName",
6244 domain);
6245 smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "sambaSID",
6246 sid_string_tos(sid));
6247 smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "sambaPwdLastSet",
6248 talloc_asprintf(talloc_tos(), "%li", (long int)time(NULL)));
6249 smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
6250 "sambaClearTextPassword", pwd);
6252 if (entry != NULL) {
6253 prev_pwd = smbldap_talloc_single_attribute(priv2ld(ldap_state),
6254 entry, "sambaClearTextPassword", talloc_tos());
6255 if (prev_pwd != NULL) {
6256 smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
6257 "sambaPreviousClearTextPassword",
6258 prev_pwd);
6262 talloc_autofree_ldapmod(talloc_tos(), mods);
6264 trusted_dn = trusteddom_dn(ldap_state, domain);
6265 if (trusted_dn == NULL) {
6266 return False;
6268 if (entry == NULL) {
6269 rc = smbldap_add(ldap_state->smbldap_state, trusted_dn, mods);
6270 } else {
6271 rc = smbldap_modify(ldap_state->smbldap_state, trusted_dn, mods);
6274 if (rc != LDAP_SUCCESS) {
6275 DEBUG(1, ("error writing trusted domain password!\n"));
6276 return False;
6279 return True;
6282 static bool ldapsam_del_trusteddom_pw(struct pdb_methods *methods,
6283 const char *domain)
6285 int rc;
6286 struct ldapsam_privates *ldap_state =
6287 (struct ldapsam_privates *)methods->private_data;
6288 LDAPMessage *entry = NULL;
6289 const char *trusted_dn;
6291 if (!get_trusteddom_pw_int(ldap_state, talloc_tos(), domain, &entry)) {
6292 return False;
6295 if (entry == NULL) {
6296 DEBUG(5, ("ldapsam_del_trusteddom_pw: no such trusted domain: "
6297 "%s\n", domain));
6298 return True;
6301 trusted_dn = smbldap_talloc_dn(talloc_tos(), priv2ld(ldap_state),
6302 entry);
6303 if (trusted_dn == NULL) {
6304 DEBUG(0,("ldapsam_del_trusteddom_pw: Out of memory!\n"));
6305 return False;
6308 rc = smbldap_delete(ldap_state->smbldap_state, trusted_dn);
6309 if (rc != LDAP_SUCCESS) {
6310 return False;
6313 return True;
6316 static NTSTATUS ldapsam_enum_trusteddoms(struct pdb_methods *methods,
6317 TALLOC_CTX *mem_ctx,
6318 uint32_t *num_domains,
6319 struct trustdom_info ***domains)
6321 int rc;
6322 struct ldapsam_privates *ldap_state =
6323 (struct ldapsam_privates *)methods->private_data;
6324 char *filter;
6325 int scope = LDAP_SCOPE_SUBTREE;
6326 const char *attrs[] = { "sambaDomainName", "sambaSID", NULL };
6327 int attrsonly = 0; /* 0: return values too */
6328 LDAPMessage *result = NULL;
6329 LDAPMessage *entry = NULL;
6331 filter = talloc_asprintf(talloc_tos(), "(objectClass=%s)",
6332 LDAP_OBJ_TRUSTDOM_PASSWORD);
6334 rc = smbldap_search(ldap_state->smbldap_state,
6335 ldap_state->domain_dn,
6336 scope,
6337 filter,
6338 attrs,
6339 attrsonly,
6340 &result);
6342 if (result != NULL) {
6343 talloc_autofree_ldapmsg(mem_ctx, result);
6346 if (rc != LDAP_SUCCESS) {
6347 return NT_STATUS_UNSUCCESSFUL;
6350 *num_domains = 0;
6351 if (!(*domains = talloc_array(mem_ctx, struct trustdom_info *, 1))) {
6352 DEBUG(1, ("talloc failed\n"));
6353 return NT_STATUS_NO_MEMORY;
6356 for (entry = ldap_first_entry(priv2ld(ldap_state), result);
6357 entry != NULL;
6358 entry = ldap_next_entry(priv2ld(ldap_state), entry))
6360 char *dom_name, *dom_sid_str;
6361 struct trustdom_info *dom_info;
6363 dom_info = talloc(*domains, struct trustdom_info);
6364 if (dom_info == NULL) {
6365 DEBUG(1, ("talloc failed\n"));
6366 return NT_STATUS_NO_MEMORY;
6369 dom_name = smbldap_talloc_single_attribute(priv2ld(ldap_state),
6370 entry,
6371 "sambaDomainName",
6372 talloc_tos());
6373 if (dom_name == NULL) {
6374 DEBUG(1, ("talloc failed\n"));
6375 return NT_STATUS_NO_MEMORY;
6377 dom_info->name = dom_name;
6379 dom_sid_str = smbldap_talloc_single_attribute(
6380 priv2ld(ldap_state), entry, "sambaSID",
6381 talloc_tos());
6382 if (dom_sid_str == NULL) {
6383 DEBUG(1, ("talloc failed\n"));
6384 return NT_STATUS_NO_MEMORY;
6386 if (!string_to_sid(&dom_info->sid, dom_sid_str)) {
6387 DEBUG(1, ("Error calling string_to_sid on SID %s\n",
6388 dom_sid_str));
6389 return NT_STATUS_UNSUCCESSFUL;
6392 ADD_TO_ARRAY(*domains, struct trustdom_info *, dom_info,
6393 domains, num_domains);
6395 if (*domains == NULL) {
6396 DEBUG(1, ("talloc failed\n"));
6397 return NT_STATUS_NO_MEMORY;
6401 DEBUG(5, ("ldapsam_enum_trusteddoms: got %d domains\n", *num_domains));
6402 return NT_STATUS_OK;
6406 /**********************************************************************
6407 Housekeeping
6408 *********************************************************************/
6410 static void free_private_data(void **vp)
6412 struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
6414 smbldap_free_struct(&(*ldap_state)->smbldap_state);
6416 if ((*ldap_state)->result != NULL) {
6417 ldap_msgfree((*ldap_state)->result);
6418 (*ldap_state)->result = NULL;
6420 if ((*ldap_state)->domain_dn != NULL) {
6421 SAFE_FREE((*ldap_state)->domain_dn);
6424 *ldap_state = NULL;
6426 /* No need to free any further, as it is talloc()ed */
6429 /*********************************************************************
6430 Intitalise the parts of the pdb_methods structure that are common to
6431 all pdb_ldap modes
6432 *********************************************************************/
6434 static NTSTATUS pdb_init_ldapsam_common(struct pdb_methods **pdb_method, const char *location)
6436 NTSTATUS nt_status;
6437 struct ldapsam_privates *ldap_state;
6438 char *bind_dn = NULL;
6439 char *bind_secret = NULL;
6441 if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
6442 return nt_status;
6445 (*pdb_method)->name = "ldapsam";
6447 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
6448 (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
6449 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
6450 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
6451 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
6452 (*pdb_method)->rename_sam_account = ldapsam_rename_sam_account;
6454 (*pdb_method)->getgrsid = ldapsam_getgrsid;
6455 (*pdb_method)->getgrgid = ldapsam_getgrgid;
6456 (*pdb_method)->getgrnam = ldapsam_getgrnam;
6457 (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
6458 (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
6459 (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
6460 (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
6462 (*pdb_method)->get_account_policy = ldapsam_get_account_policy;
6463 (*pdb_method)->set_account_policy = ldapsam_set_account_policy;
6465 (*pdb_method)->get_seq_num = ldapsam_get_seq_num;
6467 (*pdb_method)->capabilities = ldapsam_capabilities;
6468 (*pdb_method)->new_rid = ldapsam_new_rid;
6470 (*pdb_method)->get_trusteddom_pw = ldapsam_get_trusteddom_pw;
6471 (*pdb_method)->set_trusteddom_pw = ldapsam_set_trusteddom_pw;
6472 (*pdb_method)->del_trusteddom_pw = ldapsam_del_trusteddom_pw;
6473 (*pdb_method)->enum_trusteddoms = ldapsam_enum_trusteddoms;
6475 /* TODO: Setup private data and free */
6477 if ( !(ldap_state = talloc_zero(*pdb_method, struct ldapsam_privates)) ) {
6478 DEBUG(0, ("pdb_init_ldapsam_common: talloc() failed for ldapsam private_data!\n"));
6479 return NT_STATUS_NO_MEMORY;
6482 if (!fetch_ldap_pw(&bind_dn, &bind_secret)) {
6483 DEBUG(0, ("pdb_init_ldapsam_common: Failed to retrieve LDAP password from secrets.tdb\n"));
6484 return NT_STATUS_NO_MEMORY;
6487 nt_status = smbldap_init(*pdb_method, pdb_get_tevent_context(),
6488 location, false, bind_dn, bind_secret,
6489 &ldap_state->smbldap_state);
6490 memset(bind_secret, '\0', strlen(bind_secret));
6491 SAFE_FREE(bind_secret);
6492 SAFE_FREE(bind_dn);
6493 if ( !NT_STATUS_IS_OK(nt_status) ) {
6494 return nt_status;
6497 if ( !(ldap_state->domain_name = talloc_strdup(*pdb_method, get_global_sam_name()) ) ) {
6498 return NT_STATUS_NO_MEMORY;
6501 (*pdb_method)->private_data = ldap_state;
6503 (*pdb_method)->free_private_data = free_private_data;
6505 return NT_STATUS_OK;
6508 /**********************************************************************
6509 Initialise the 'compat' mode for pdb_ldap
6510 *********************************************************************/
6512 NTSTATUS pdb_init_ldapsam_compat(struct pdb_methods **pdb_method, const char *location)
6514 NTSTATUS nt_status;
6515 struct ldapsam_privates *ldap_state;
6516 char *uri = talloc_strdup( NULL, location );
6518 trim_char( uri, '\"', '\"' );
6519 nt_status = pdb_init_ldapsam_common( pdb_method, uri );
6520 if ( uri )
6521 TALLOC_FREE( uri );
6523 if ( !NT_STATUS_IS_OK(nt_status) ) {
6524 return nt_status;
6527 (*pdb_method)->name = "ldapsam_compat";
6529 ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
6530 ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
6532 sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
6534 return NT_STATUS_OK;
6537 /**********************************************************************
6538 Initialise the normal mode for pdb_ldap
6539 *********************************************************************/
6541 NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
6543 NTSTATUS nt_status;
6544 struct ldapsam_privates *ldap_state = NULL;
6545 uint32_t alg_rid_base;
6546 char *alg_rid_base_string = NULL;
6547 LDAPMessage *result = NULL;
6548 LDAPMessage *entry = NULL;
6549 struct dom_sid ldap_domain_sid;
6550 struct dom_sid secrets_domain_sid;
6551 char *domain_sid_string = NULL;
6552 char *dn = NULL;
6553 char *uri = talloc_strdup( NULL, location );
6555 trim_char( uri, '\"', '\"' );
6556 nt_status = pdb_init_ldapsam_common(pdb_method, uri);
6558 TALLOC_FREE(uri);
6560 if (!NT_STATUS_IS_OK(nt_status)) {
6561 return nt_status;
6564 (*pdb_method)->name = "ldapsam";
6566 (*pdb_method)->add_aliasmem = ldapsam_add_aliasmem;
6567 (*pdb_method)->del_aliasmem = ldapsam_del_aliasmem;
6568 (*pdb_method)->enum_aliasmem = ldapsam_enum_aliasmem;
6569 (*pdb_method)->enum_alias_memberships = ldapsam_alias_memberships;
6570 (*pdb_method)->search_users = ldapsam_search_users;
6571 (*pdb_method)->search_groups = ldapsam_search_groups;
6572 (*pdb_method)->search_aliases = ldapsam_search_aliases;
6574 if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
6575 (*pdb_method)->enum_group_members = ldapsam_enum_group_members;
6576 (*pdb_method)->enum_group_memberships =
6577 ldapsam_enum_group_memberships;
6578 (*pdb_method)->lookup_rids = ldapsam_lookup_rids;
6579 (*pdb_method)->sid_to_id = ldapsam_sid_to_id;
6580 (*pdb_method)->uid_to_sid = ldapsam_uid_to_sid;
6581 (*pdb_method)->gid_to_sid = ldapsam_gid_to_sid;
6583 if (lp_parm_bool(-1, "ldapsam", "editposix", False)) {
6584 (*pdb_method)->create_user = ldapsam_create_user;
6585 (*pdb_method)->delete_user = ldapsam_delete_user;
6586 (*pdb_method)->create_dom_group = ldapsam_create_dom_group;
6587 (*pdb_method)->delete_dom_group = ldapsam_delete_dom_group;
6588 (*pdb_method)->add_groupmem = ldapsam_add_groupmem;
6589 (*pdb_method)->del_groupmem = ldapsam_del_groupmem;
6590 (*pdb_method)->set_unix_primary_group = ldapsam_set_primary_group;
6594 ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
6595 ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
6597 /* Try to setup the Domain Name, Domain SID, algorithmic rid base */
6599 nt_status = smbldap_search_domain_info(ldap_state->smbldap_state,
6600 &result,
6601 ldap_state->domain_name, True);
6603 if ( !NT_STATUS_IS_OK(nt_status) ) {
6604 DEBUG(0, ("pdb_init_ldapsam: WARNING: Could not get domain "
6605 "info, nor add one to the domain. "
6606 "We cannot work reliably without it.\n"));
6607 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
6610 /* Given that the above might fail, everything below this must be
6611 * optional */
6613 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
6614 result);
6615 if (!entry) {
6616 DEBUG(0, ("pdb_init_ldapsam: Could not get domain info "
6617 "entry\n"));
6618 ldap_msgfree(result);
6619 return NT_STATUS_UNSUCCESSFUL;
6622 dn = smbldap_talloc_dn(talloc_tos(), ldap_state->smbldap_state->ldap_struct, entry);
6623 if (!dn) {
6624 ldap_msgfree(result);
6625 return NT_STATUS_UNSUCCESSFUL;
6628 ldap_state->domain_dn = smb_xstrdup(dn);
6629 TALLOC_FREE(dn);
6631 domain_sid_string = smbldap_talloc_single_attribute(
6632 ldap_state->smbldap_state->ldap_struct,
6633 entry,
6634 get_userattr_key2string(ldap_state->schema_ver,
6635 LDAP_ATTR_USER_SID),
6636 talloc_tos());
6638 if (domain_sid_string) {
6639 bool found_sid;
6640 if (!string_to_sid(&ldap_domain_sid, domain_sid_string)) {
6641 DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be "
6642 "read as a valid SID\n", domain_sid_string));
6643 ldap_msgfree(result);
6644 TALLOC_FREE(domain_sid_string);
6645 return NT_STATUS_INVALID_PARAMETER;
6647 found_sid = secrets_fetch_domain_sid(ldap_state->domain_name,
6648 &secrets_domain_sid);
6649 if (!found_sid || !dom_sid_equal(&secrets_domain_sid,
6650 &ldap_domain_sid)) {
6651 DEBUG(1, ("pdb_init_ldapsam: Resetting SID for domain "
6652 "%s based on pdb_ldap results %s -> %s\n",
6653 ldap_state->domain_name,
6654 sid_string_dbg(&secrets_domain_sid),
6655 sid_string_dbg(&ldap_domain_sid)));
6657 /* reset secrets.tdb sid */
6658 secrets_store_domain_sid(ldap_state->domain_name,
6659 &ldap_domain_sid);
6660 DEBUG(1, ("New global sam SID: %s\n",
6661 sid_string_dbg(get_global_sam_sid())));
6663 sid_copy(&ldap_state->domain_sid, &ldap_domain_sid);
6664 TALLOC_FREE(domain_sid_string);
6667 alg_rid_base_string = smbldap_talloc_single_attribute(
6668 ldap_state->smbldap_state->ldap_struct,
6669 entry,
6670 get_attr_key2string( dominfo_attr_list,
6671 LDAP_ATTR_ALGORITHMIC_RID_BASE ),
6672 talloc_tos());
6673 if (alg_rid_base_string) {
6674 alg_rid_base = (uint32_t)atol(alg_rid_base_string);
6675 if (alg_rid_base != algorithmic_rid_base()) {
6676 DEBUG(0, ("The value of 'algorithmic RID base' has "
6677 "changed since the LDAP\n"
6678 "database was initialised. Aborting. \n"));
6679 ldap_msgfree(result);
6680 TALLOC_FREE(alg_rid_base_string);
6681 return NT_STATUS_UNSUCCESSFUL;
6683 TALLOC_FREE(alg_rid_base_string);
6685 ldap_msgfree(result);
6687 return NT_STATUS_OK;
6690 NTSTATUS pdb_ldap_init(void)
6692 NTSTATUS nt_status;
6693 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam", pdb_init_ldapsam)))
6694 return nt_status;
6696 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat)))
6697 return nt_status;
6699 /* Let pdb_nds register backends */
6700 pdb_nds_init();
6702 pdb_ipa_init();
6704 return NT_STATUS_OK;