port latest changes from SAMBA_3_0 tree
[Samba/bb.git] / source / passdb / pdb_ldap.c
blobaee6495759308a362026277c5ef6794c9bd6b3e4
1 /*
2 Unix SMB/CIFS mplementation.
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
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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/SAM_ACCOUNT
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"
48 #undef DBGC_CLASS
49 #define DBGC_CLASS DBGC_PASSDB
51 #include <lber.h>
52 #include <ldap.h>
55 * Work around versions of the LDAP client libs that don't have the OIDs
56 * defined, or have them defined under the old name.
57 * This functionality is really a factor of the server, not the client
61 #if defined(LDAP_EXOP_X_MODIFY_PASSWD) && !defined(LDAP_EXOP_MODIFY_PASSWD)
62 #define LDAP_EXOP_MODIFY_PASSWD LDAP_EXOP_X_MODIFY_PASSWD
63 #elif !defined(LDAP_EXOP_MODIFY_PASSWD)
64 #define "1.3.6.1.4.1.4203.1.11.1"
65 #endif
67 #if defined(LDAP_EXOP_X_MODIFY_PASSWD_ID) && !defined(LDAP_EXOP_MODIFY_PASSWD_ID)
68 #define LDAP_TAG_EXOP_MODIFY_PASSWD_ID LDAP_EXOP_X_MODIFY_PASSWD_ID
69 #elif !defined(LDAP_EXOP_MODIFY_PASSWD_ID)
70 #define LDAP_TAG_EXOP_MODIFY_PASSWD_ID ((ber_tag_t) 0x80U)
71 #endif
73 #if defined(LDAP_EXOP_X_MODIFY_PASSWD_NEW) && !defined(LDAP_EXOP_MODIFY_PASSWD_NEW)
74 #define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW LDAP_EXOP_X_MODIFY_PASSWD_NEW
75 #elif !defined(LDAP_EXOP_MODIFY_PASSWD_NEW)
76 #define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW ((ber_tag_t) 0x82U)
77 #endif
80 #ifndef SAM_ACCOUNT
81 #define SAM_ACCOUNT struct sam_passwd
82 #endif
84 #include "smbldap.h"
86 struct ldapsam_privates {
87 struct smbldap_state *smbldap_state;
89 /* Former statics */
90 LDAPMessage *result;
91 LDAPMessage *entry;
92 int index;
94 const char *domain_name;
95 DOM_SID domain_sid;
97 /* configuration items */
98 int schema_ver;
101 /**********************************************************************
102 Free a LDAPMessage (one is stored on the SAM_ACCOUNT)
103 **********************************************************************/
105 static void private_data_free_fn(void **result)
107 ldap_msgfree(*result);
108 *result = NULL;
111 /**********************************************************************
112 get the attribute name given a user schame version
113 **********************************************************************/
115 static const char* get_userattr_key2string( int schema_ver, int key )
117 switch ( schema_ver )
119 case SCHEMAVER_SAMBAACCOUNT:
120 return get_attr_key2string( attrib_map_v22, key );
122 case SCHEMAVER_SAMBASAMACCOUNT:
123 return get_attr_key2string( attrib_map_v30, key );
125 default:
126 DEBUG(0,("get_userattr_key2string: unknown schema version specified\n"));
127 break;
129 return NULL;
132 /**********************************************************************
133 return the list of attribute names given a user schema version
134 **********************************************************************/
136 static char** get_userattr_list( int schema_ver )
138 switch ( schema_ver )
140 case SCHEMAVER_SAMBAACCOUNT:
141 return get_attr_list( attrib_map_v22 );
143 case SCHEMAVER_SAMBASAMACCOUNT:
144 return get_attr_list( attrib_map_v30 );
145 default:
146 DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
147 break;
150 return NULL;
152 /*******************************************************************
153 generate the LDAP search filter for the objectclass based on the
154 version of the schema we are using
155 ******************************************************************/
157 static const char* get_objclass_filter( int schema_ver )
159 static fstring objclass_filter;
161 switch( schema_ver )
163 case SCHEMAVER_SAMBAACCOUNT:
164 fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT );
165 break;
166 case SCHEMAVER_SAMBASAMACCOUNT:
167 fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT );
168 break;
169 default:
170 DEBUG(0,("pdb_ldapsam: get_objclass_filter(): Invalid schema version specified!\n"));
171 break;
174 return objclass_filter;
177 /*******************************************************************
178 run the search by name.
179 ******************************************************************/
180 static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state,
181 const char *user,
182 LDAPMessage ** result, char **attr)
184 pstring filter;
185 char *escape_user = escape_ldap_string_alloc(user);
187 if (!escape_user) {
188 return LDAP_NO_MEMORY;
192 * in the filter expression, replace %u with the real name
193 * so in ldap filter, %u MUST exist :-)
195 pstr_sprintf(filter, "(&%s%s)", lp_ldap_filter(),
196 get_objclass_filter(ldap_state->schema_ver));
199 * have to use this here because $ is filtered out
200 * in pstring_sub
204 all_string_sub(filter, "%u", escape_user, sizeof(pstring));
205 SAFE_FREE(escape_user);
207 return smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result);
210 /*******************************************************************
211 run the search by rid.
212 ******************************************************************/
213 static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state,
214 uint32 rid, LDAPMessage ** result,
215 char **attr)
217 pstring filter;
218 int rc;
220 pstr_sprintf(filter, "(&(rid=%i)%s)", rid,
221 get_objclass_filter(ldap_state->schema_ver));
223 rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result);
225 return rc;
228 /*******************************************************************
229 run the search by SID.
230 ******************************************************************/
231 static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state,
232 const DOM_SID *sid, LDAPMessage ** result,
233 char **attr)
235 pstring filter;
236 int rc;
237 fstring sid_string;
239 pstr_sprintf(filter, "(&(%s=%s)%s)",
240 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
241 sid_to_string(sid_string, sid),
242 get_objclass_filter(ldap_state->schema_ver));
244 rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result);
246 return rc;
249 /*******************************************************************
250 Delete complete object or objectclass and attrs from
251 object found in search_result depending on lp_ldap_delete_dn
252 ******************************************************************/
253 static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
254 LDAPMessage *result,
255 const char *objectclass,
256 char **attrs)
258 int rc;
259 LDAPMessage *entry;
260 LDAPMod **mods = NULL;
261 char *name, *dn;
262 BerElement *ptr = NULL;
264 rc = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
266 if (rc != 1) {
267 DEBUG(0, ("Entry must exist exactly once!\n"));
268 return NT_STATUS_UNSUCCESSFUL;
271 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
272 dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
274 if (lp_ldap_delete_dn()) {
275 NTSTATUS ret = NT_STATUS_OK;
276 rc = smbldap_delete(ldap_state->smbldap_state, dn);
278 if (rc != LDAP_SUCCESS) {
279 DEBUG(0, ("Could not delete object %s\n", dn));
280 ret = NT_STATUS_UNSUCCESSFUL;
282 ldap_memfree(dn);
283 return ret;
286 /* Ok, delete only the SAM attributes */
288 for (name = ldap_first_attribute(ldap_state->smbldap_state->ldap_struct, entry, &ptr);
289 name != NULL;
290 name = ldap_next_attribute(ldap_state->smbldap_state->ldap_struct, entry, ptr))
292 char **attrib;
294 /* We are only allowed to delete the attributes that
295 really exist. */
297 for (attrib = attrs; *attrib != NULL; attrib++)
299 if (StrCaseCmp(*attrib, name) == 0) {
300 DEBUG(10, ("deleting attribute %s\n", name));
301 smbldap_set_mod(&mods, LDAP_MOD_DELETE, name, NULL);
305 ldap_memfree(name);
308 if (ptr != NULL) {
309 ber_free(ptr, 0);
312 smbldap_set_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
314 rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
315 ldap_mods_free(mods, True);
317 if (rc != LDAP_SUCCESS) {
318 char *ld_error = NULL;
319 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
320 &ld_error);
322 DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n",
323 dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
324 SAFE_FREE(ld_error);
325 ldap_memfree(dn);
326 return NT_STATUS_UNSUCCESSFUL;
329 ldap_memfree(dn);
330 return NT_STATUS_OK;
334 /* New Interface is being implemented here */
336 /**********************************************************************
337 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
338 *********************************************************************/
339 static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state,
340 SAM_ACCOUNT * sampass,
341 LDAPMessage * entry,
342 gid_t *gid)
344 pstring homedir;
345 pstring temp;
346 char **ldap_values;
347 char **values;
349 if ((ldap_values = ldap_get_values (ldap_state->smbldap_state->ldap_struct, entry, "objectClass")) == NULL) {
350 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
351 return False;
354 for (values=ldap_values;*values;values++) {
355 if (strcasecmp(*values, LDAP_OBJ_POSIXACCOUNT ) == 0) {
356 break;
360 if (!*values) { /*end of array, no posixAccount */
361 DEBUG(10, ("user does not have %s attributes\n", LDAP_OBJ_POSIXACCOUNT));
362 ldap_value_free(ldap_values);
363 return False;
365 ldap_value_free(ldap_values);
367 if ( !smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
368 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_UNIX_HOME), homedir) )
370 return False;
373 if ( !smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
374 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_GIDNUMBER), temp) )
376 return False;
379 *gid = (gid_t)atol(temp);
381 pdb_set_unix_homedir(sampass, homedir, PDB_SET);
383 DEBUG(10, ("user has %s attributes\n", LDAP_OBJ_POSIXACCOUNT));
385 return True;
389 /**********************************************************************
390 Initialize SAM_ACCOUNT from an LDAP query
391 (Based on init_sam_from_buffer in pdb_tdb.c)
392 *********************************************************************/
393 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
394 SAM_ACCOUNT * sampass,
395 LDAPMessage * entry)
397 time_t logon_time,
398 logoff_time,
399 kickoff_time,
400 pass_last_set_time,
401 pass_can_change_time,
402 pass_must_change_time;
403 pstring username,
404 domain,
405 nt_username,
406 fullname,
407 homedir,
408 dir_drive,
409 logon_script,
410 profile_path,
411 acct_desc,
412 munged_dial,
413 workstations;
414 uint32 user_rid;
415 uint8 smblmpwd[LM_HASH_LEN],
416 smbntpwd[NT_HASH_LEN];
417 uint16 acct_ctrl = 0,
418 logon_divs;
419 uint32 hours_len;
420 uint8 hours[MAX_HOURS_LEN];
421 pstring temp;
422 uid_t uid = -1;
423 gid_t gid = getegid();
426 * do a little initialization
428 username[0] = '\0';
429 domain[0] = '\0';
430 nt_username[0] = '\0';
431 fullname[0] = '\0';
432 homedir[0] = '\0';
433 dir_drive[0] = '\0';
434 logon_script[0] = '\0';
435 profile_path[0] = '\0';
436 acct_desc[0] = '\0';
437 munged_dial[0] = '\0';
438 workstations[0] = '\0';
441 if (sampass == NULL || ldap_state == NULL || entry == NULL) {
442 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
443 return False;
446 if (ldap_state->smbldap_state->ldap_struct == NULL) {
447 DEBUG(0, ("init_sam_from_ldap: ldap_state->smbldap_state->ldap_struct is NULL!\n"));
448 return False;
451 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, "uid", username)) {
452 DEBUG(1, ("No uid attribute found for this user!\n"));
453 return False;
456 DEBUG(2, ("Entry found for user: %s\n", username));
458 pstrcpy(nt_username, username);
460 pstrcpy(domain, ldap_state->domain_name);
462 pdb_set_username(sampass, username, PDB_SET);
464 pdb_set_domain(sampass, domain, PDB_DEFAULT);
465 pdb_set_nt_username(sampass, nt_username, PDB_SET);
467 /* deal with different attributes between the schema first */
469 if ( ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT )
471 if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
472 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), temp))
474 pdb_set_user_sid_from_string(sampass, temp, PDB_SET);
477 if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
478 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), temp))
480 pdb_set_group_sid_from_string(sampass, temp, PDB_SET);
482 else
484 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
489 else
491 if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
492 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp))
494 user_rid = (uint32)atol(temp);
495 pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
498 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
499 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp))
501 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
502 } else {
503 uint32 group_rid;
505 group_rid = (uint32)atol(temp);
507 /* for some reason, we often have 0 as a primary group RID.
508 Make sure that we treat this just as a 'default' value */
510 if ( group_rid > 0 )
511 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
512 else
513 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
517 if (pdb_get_init_flags(sampass,PDB_USERSID) == PDB_DEFAULT) {
518 DEBUG(1, ("no %s or %s attribute found for this user %s\n",
519 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
520 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID),
521 username));
522 return False;
527 * If so configured, try and get the values from LDAP
530 if (lp_ldap_trust_ids() && (get_unix_attributes(ldap_state, sampass, entry, &gid)))
532 if (pdb_get_init_flags(sampass,PDB_GROUPSID) == PDB_DEFAULT)
534 GROUP_MAP map;
535 /* call the mapping code here */
536 if(pdb_getgrgid(&map, gid)) {
537 pdb_set_group_sid(sampass, &map.sid, PDB_SET);
539 else {
540 pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
545 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
546 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), temp))
548 /* leave as default */
549 } else {
550 pass_last_set_time = (time_t) atol(temp);
551 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
554 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
555 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp))
557 /* leave as default */
558 } else {
559 logon_time = (time_t) atol(temp);
560 pdb_set_logon_time(sampass, logon_time, PDB_SET);
563 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
564 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp))
566 /* leave as default */
567 } else {
568 logoff_time = (time_t) atol(temp);
569 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
572 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
573 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp))
575 /* leave as default */
576 } else {
577 kickoff_time = (time_t) atol(temp);
578 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
581 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
582 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp))
584 /* leave as default */
585 } else {
586 pass_can_change_time = (time_t) atol(temp);
587 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
590 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
591 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp))
593 /* leave as default */
594 } else {
595 pass_must_change_time = (time_t) atol(temp);
596 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
599 /* recommend that 'gecos' and 'displayName' should refer to the same
600 * attribute OID. userFullName depreciated, only used by Samba
601 * primary rules of LDAP: don't make a new attribute when one is already defined
602 * that fits your needs; using cn then displayName rather than 'userFullName'
605 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
606 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), fullname))
608 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
609 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_CN), fullname))
611 /* leave as default */
612 } else {
613 pdb_set_fullname(sampass, fullname, PDB_SET);
615 } else {
616 pdb_set_fullname(sampass, fullname, PDB_SET);
619 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
620 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), dir_drive))
622 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx,
623 lp_logon_drive(),
624 username, domain,
625 uid, gid),
626 PDB_DEFAULT);
627 } else {
628 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
631 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
632 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir))
634 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx,
635 lp_logon_home(),
636 username, domain,
637 uid, gid),
638 PDB_DEFAULT);
639 } else {
640 pdb_set_homedir(sampass, homedir, PDB_SET);
643 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
644 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script))
646 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx,
647 lp_logon_script(),
648 username, domain,
649 uid, gid),
650 PDB_DEFAULT);
651 } else {
652 pdb_set_logon_script(sampass, logon_script, PDB_SET);
655 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
656 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path))
658 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx,
659 lp_logon_path(),
660 username, domain,
661 uid, gid),
662 PDB_DEFAULT);
663 } else {
664 pdb_set_profile_path(sampass, profile_path, PDB_SET);
667 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
668 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC), acct_desc))
670 /* leave as default */
671 } else {
672 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
675 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
676 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), workstations))
678 /* leave as default */;
679 } else {
680 pdb_set_workstations(sampass, workstations, PDB_SET);
683 /* FIXME: hours stuff should be cleaner */
685 logon_divs = 168;
686 hours_len = 21;
687 memset(hours, 0xff, hours_len);
689 if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry,
690 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp))
692 /* leave as default */
693 } else {
694 pdb_gethexpwd(temp, smblmpwd);
695 memset((char *)temp, '\0', strlen(temp)+1);
696 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
697 return False;
698 ZERO_STRUCT(smblmpwd);
701 if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry,
702 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp))
704 /* leave as default */
705 } else {
706 pdb_gethexpwd(temp, smbntpwd);
707 memset((char *)temp, '\0', strlen(temp)+1);
708 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
709 return False;
710 ZERO_STRUCT(smbntpwd);
713 if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry,
714 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), temp))
716 acct_ctrl |= ACB_NORMAL;
717 } else {
718 acct_ctrl = pdb_decode_acct_ctrl(temp);
720 if (acct_ctrl == 0)
721 acct_ctrl |= ACB_NORMAL;
723 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
726 pdb_set_hours_len(sampass, hours_len, PDB_SET);
727 pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
729 pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
731 /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
732 /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
733 /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
735 pdb_set_hours(sampass, hours, PDB_SET);
737 return True;
740 /**********************************************************************
741 Initialize SAM_ACCOUNT from an LDAP query
742 (Based on init_buffer_from_sam in pdb_tdb.c)
743 *********************************************************************/
744 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
745 LDAPMessage *existing,
746 LDAPMod *** mods, SAM_ACCOUNT * sampass,
747 BOOL (*need_update)(const SAM_ACCOUNT *,
748 enum pdb_elements))
750 pstring temp;
751 uint32 rid;
753 if (mods == NULL || sampass == NULL) {
754 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
755 return False;
758 *mods = NULL;
761 * took out adding "objectclass: sambaAccount"
762 * do this on a per-mod basis
764 if (need_update(sampass, PDB_USERNAME))
765 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
766 "uid", pdb_get_username(sampass));
768 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
770 /* only update the RID if we actually need to */
771 if (need_update(sampass, PDB_USERSID))
773 fstring sid_string;
774 fstring dom_sid_string;
775 const DOM_SID *user_sid = pdb_get_user_sid(sampass);
777 switch ( ldap_state->schema_ver )
779 case SCHEMAVER_SAMBAACCOUNT:
780 if (!sid_peek_check_rid(&ldap_state->domain_sid, user_sid, &rid)) {
781 DEBUG(1, ("User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
782 sid_to_string(sid_string, user_sid),
783 sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
784 return False;
786 slprintf(temp, sizeof(temp) - 1, "%i", rid);
787 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
788 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID),
789 temp);
790 break;
792 case SCHEMAVER_SAMBASAMACCOUNT:
793 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
794 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
795 sid_to_string(sid_string, user_sid));
796 break;
798 default:
799 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
800 break;
804 /* we don't need to store the primary group RID - so leaving it
805 'free' to hang off the unix primary group makes life easier */
807 if (need_update(sampass, PDB_GROUPSID))
809 fstring sid_string;
810 fstring dom_sid_string;
811 const DOM_SID *group_sid = pdb_get_group_sid(sampass);
813 switch ( ldap_state->schema_ver )
815 case SCHEMAVER_SAMBAACCOUNT:
816 if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) {
817 DEBUG(1, ("User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
818 sid_to_string(sid_string, group_sid),
819 sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
820 return False;
823 slprintf(temp, sizeof(temp) - 1, "%i", rid);
824 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
825 get_userattr_key2string(ldap_state->schema_ver,
826 LDAP_ATTR_PRIMARY_GROUP_RID), temp);
827 break;
829 case SCHEMAVER_SAMBASAMACCOUNT:
830 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
831 get_userattr_key2string(ldap_state->schema_ver,
832 LDAP_ATTR_PRIMARY_GROUP_SID), sid_to_string(sid_string, group_sid));
833 break;
835 default:
836 DEBUG(0,("init_ldap_from_sam: unknown schema version specified\n"));
837 break;
842 /* displayName, cn, and gecos should all be the same
843 * most easily accomplished by giving them the same OID
844 * gecos isn't set here b/c it should be handled by the
845 * add-user script
846 * We change displayName only and fall back to cn if
847 * it does not exist.
850 if (need_update(sampass, PDB_FULLNAME))
851 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
852 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME),
853 pdb_get_fullname(sampass));
855 if (need_update(sampass, PDB_ACCTDESC))
856 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
857 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC),
858 pdb_get_acct_desc(sampass));
860 if (need_update(sampass, PDB_WORKSTATIONS))
861 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
862 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS),
863 pdb_get_workstations(sampass));
865 if (need_update(sampass, PDB_SMBHOME))
866 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
867 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH),
868 pdb_get_homedir(sampass));
870 if (need_update(sampass, PDB_DRIVE))
871 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
872 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE),
873 pdb_get_dir_drive(sampass));
875 if (need_update(sampass, PDB_LOGONSCRIPT))
876 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
877 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT),
878 pdb_get_logon_script(sampass));
880 if (need_update(sampass, PDB_PROFILE))
881 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
882 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH),
883 pdb_get_profile_path(sampass));
885 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
886 if (need_update(sampass, PDB_LOGONTIME))
887 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
888 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp);
890 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
891 if (need_update(sampass, PDB_LOGOFFTIME))
892 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
893 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp);
895 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass));
896 if (need_update(sampass, PDB_KICKOFFTIME))
897 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
898 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp);
900 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
901 if (need_update(sampass, PDB_CANCHANGETIME))
902 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
903 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp);
905 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass));
906 if (need_update(sampass, PDB_MUSTCHANGETIME))
907 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
908 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp);
910 if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))
911 || (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY))
914 pdb_sethexpwd(temp, pdb_get_lanman_passwd(sampass),
915 pdb_get_acct_ctrl(sampass));
917 if (need_update(sampass, PDB_LMPASSWD))
918 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
919 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW),
920 temp);
922 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass),
923 pdb_get_acct_ctrl(sampass));
925 if (need_update(sampass, PDB_NTPASSWD))
926 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
927 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW),
928 temp);
930 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
931 if (need_update(sampass, PDB_PASSLASTSET))
932 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
933 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET),
934 temp);
937 /* FIXME: Hours stuff goes in LDAP */
939 if (need_update(sampass, PDB_ACCTCTRL))
940 smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
941 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO),
942 pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass), NEW_PW_FORMAT_SPACE_PADDED_LEN));
944 return True;
949 /**********************************************************************
950 Connect to LDAP server for password enumeration
951 *********************************************************************/
952 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
954 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
955 int rc;
956 pstring filter;
957 char **attr_list;
959 pstr_sprintf( filter, "(&%s%s)", lp_ldap_filter(),
960 get_objclass_filter(ldap_state->schema_ver));
961 all_string_sub(filter, "%u", "*", sizeof(pstring));
963 attr_list = get_userattr_list(ldap_state->schema_ver);
964 rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
965 attr_list, &ldap_state->result);
966 free_attr_list( attr_list );
968 if (rc != LDAP_SUCCESS) {
969 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
970 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
971 ldap_msgfree(ldap_state->result);
972 ldap_state->result = NULL;
973 return NT_STATUS_UNSUCCESSFUL;
976 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
977 ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
978 ldap_state->result)));
980 ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
981 ldap_state->result);
982 ldap_state->index = 0;
984 return NT_STATUS_OK;
987 /**********************************************************************
988 End enumeration of the LDAP password list
989 *********************************************************************/
990 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
992 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
993 if (ldap_state->result) {
994 ldap_msgfree(ldap_state->result);
995 ldap_state->result = NULL;
999 /**********************************************************************
1000 Get the next entry in the LDAP password database
1001 *********************************************************************/
1002 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
1004 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1005 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1006 BOOL bret = False;
1008 while (!bret) {
1009 if (!ldap_state->entry)
1010 return ret;
1012 ldap_state->index++;
1013 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
1015 ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
1016 ldap_state->entry);
1019 return NT_STATUS_OK;
1022 /**********************************************************************
1023 Get SAM_ACCOUNT entry from LDAP by username
1024 *********************************************************************/
1025 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
1027 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1028 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1029 LDAPMessage *result;
1030 LDAPMessage *entry;
1031 int count;
1032 char ** attr_list;
1033 int rc;
1035 attr_list = get_userattr_list( ldap_state->schema_ver );
1036 rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
1037 free_attr_list( attr_list );
1039 if ( rc != LDAP_SUCCESS )
1040 return NT_STATUS_NO_SUCH_USER;
1042 count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1044 if (count < 1) {
1045 DEBUG(4,
1046 ("Unable to locate user [%s] count=%d\n", sname,
1047 count));
1048 ldap_msgfree(result);
1049 return NT_STATUS_NO_SUCH_USER;
1050 } else if (count > 1) {
1051 DEBUG(1,
1052 ("Duplicate entries for this user [%s] Failing. count=%d\n", sname,
1053 count));
1054 ldap_msgfree(result);
1055 return NT_STATUS_NO_SUCH_USER;
1058 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1059 if (entry) {
1060 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1061 DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
1062 ldap_msgfree(result);
1063 return NT_STATUS_NO_SUCH_USER;
1065 pdb_set_backend_private_data(user, result,
1066 private_data_free_fn,
1067 my_methods, PDB_CHANGED);
1068 ret = NT_STATUS_OK;
1069 } else {
1070 ldap_msgfree(result);
1072 return ret;
1075 static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state,
1076 const DOM_SID *sid, LDAPMessage **result)
1078 int rc = -1;
1079 char ** attr_list;
1080 uint32 rid;
1082 switch ( ldap_state->schema_ver )
1084 case SCHEMAVER_SAMBASAMACCOUNT:
1085 attr_list = get_userattr_list(ldap_state->schema_ver);
1086 rc = ldapsam_search_suffix_by_sid(ldap_state, sid, result, attr_list);
1087 free_attr_list( attr_list );
1089 if ( rc != LDAP_SUCCESS )
1090 return rc;
1091 break;
1093 case SCHEMAVER_SAMBAACCOUNT:
1094 if (!sid_peek_check_rid(&ldap_state->domain_sid, sid, &rid)) {
1095 return rc;
1098 attr_list = get_userattr_list(ldap_state->schema_ver);
1099 rc = ldapsam_search_suffix_by_rid(ldap_state, rid, result, attr_list );
1100 free_attr_list( attr_list );
1102 if ( rc != LDAP_SUCCESS )
1103 return rc;
1104 break;
1106 return rc;
1109 /**********************************************************************
1110 Get SAM_ACCOUNT entry from LDAP by SID
1111 *********************************************************************/
1112 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
1114 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1115 LDAPMessage *result;
1116 LDAPMessage *entry;
1117 int count;
1118 int rc;
1119 fstring sid_string;
1121 rc = ldapsam_get_ldap_user_by_sid(ldap_state,
1122 sid, &result);
1123 if (rc != LDAP_SUCCESS)
1124 return NT_STATUS_NO_SUCH_USER;
1126 count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1128 if (count < 1)
1130 DEBUG(4,
1131 ("Unable to locate SID [%s] count=%d\n", sid_to_string(sid_string, sid),
1132 count));
1133 ldap_msgfree(result);
1134 return NT_STATUS_NO_SUCH_USER;
1136 else if (count > 1)
1138 DEBUG(1,
1139 ("More than one user with SID [%s]. Failing. count=%d\n", sid_to_string(sid_string, sid),
1140 count));
1141 ldap_msgfree(result);
1142 return NT_STATUS_NO_SUCH_USER;
1145 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1146 if (!entry)
1148 ldap_msgfree(result);
1149 return NT_STATUS_NO_SUCH_USER;
1152 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1153 DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
1154 ldap_msgfree(result);
1155 return NT_STATUS_NO_SUCH_USER;
1158 pdb_set_backend_private_data(user, result,
1159 private_data_free_fn,
1160 my_methods, PDB_CHANGED);
1161 return NT_STATUS_OK;
1164 /********************************************************************
1165 Do the actual modification - also change a plaintext passord if
1166 it it set.
1167 **********************************************************************/
1169 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
1170 SAM_ACCOUNT *newpwd, char *dn,
1171 LDAPMod **mods, int ldap_op,
1172 BOOL (*need_update)(const SAM_ACCOUNT *,
1173 enum pdb_elements))
1175 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1176 int rc;
1178 if (!my_methods || !newpwd || !dn) {
1179 return NT_STATUS_INVALID_PARAMETER;
1182 if (!mods) {
1183 DEBUG(5,("mods is empty: nothing to modify\n"));
1184 /* may be password change below however */
1185 } else {
1186 switch(ldap_op)
1188 case LDAP_MOD_ADD:
1189 smbldap_set_mod(&mods, LDAP_MOD_ADD,
1190 "objectclass",
1191 LDAP_OBJ_ACCOUNT);
1192 rc = smbldap_add(ldap_state->smbldap_state,
1193 dn, mods);
1194 break;
1195 case LDAP_MOD_REPLACE:
1196 rc = smbldap_modify(ldap_state->smbldap_state,
1197 dn ,mods);
1198 break;
1199 default:
1200 DEBUG(0,("Wrong LDAP operation type: %d!\n",
1201 ldap_op));
1202 return NT_STATUS_INVALID_PARAMETER;
1205 if (rc!=LDAP_SUCCESS) {
1206 char *ld_error = NULL;
1207 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1208 &ld_error);
1209 DEBUG(1,
1210 ("failed to %s user dn= %s with: %s\n\t%s\n",
1211 ldap_op == LDAP_MOD_ADD ? "add" : "modify",
1212 dn, ldap_err2string(rc),
1213 ld_error?ld_error:"unknown"));
1214 SAFE_FREE(ld_error);
1215 return NT_STATUS_UNSUCCESSFUL;
1219 if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) &&
1220 (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) &&
1221 need_update(newpwd, PDB_PLAINTEXT_PW) &&
1222 (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
1223 BerElement *ber;
1224 struct berval *bv;
1225 char *retoid;
1226 struct berval *retdata;
1227 char *utf8_password;
1228 char *utf8_dn;
1230 if (push_utf8_allocate(&utf8_password, pdb_get_plaintext_passwd(newpwd)) == (size_t)-1) {
1231 return NT_STATUS_NO_MEMORY;
1234 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
1235 return NT_STATUS_NO_MEMORY;
1238 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
1239 DEBUG(0,("ber_alloc_t returns NULL\n"));
1240 SAFE_FREE(utf8_password);
1241 return NT_STATUS_UNSUCCESSFUL;
1244 ber_printf (ber, "{");
1245 ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, utf8_dn);
1246 ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, utf8_password);
1247 ber_printf (ber, "N}");
1249 if ((rc = ber_flatten (ber, &bv))<0) {
1250 DEBUG(0,("ber_flatten returns a value <0\n"));
1251 ber_free(ber,1);
1252 SAFE_FREE(utf8_dn);
1253 SAFE_FREE(utf8_password);
1254 return NT_STATUS_UNSUCCESSFUL;
1257 SAFE_FREE(utf8_dn);
1258 SAFE_FREE(utf8_password);
1259 ber_free(ber, 1);
1261 if ((rc = smbldap_extended_operation(ldap_state->smbldap_state,
1262 LDAP_EXOP_MODIFY_PASSWD,
1263 bv, NULL, NULL, &retoid,
1264 &retdata)) != LDAP_SUCCESS) {
1265 DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
1266 pdb_get_username(newpwd),ldap_err2string(rc)));
1267 } else {
1268 DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
1269 #ifdef DEBUG_PASSWORD
1270 DEBUG(100,("LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd)));
1271 #endif
1272 ber_bvfree(retdata);
1273 ber_memfree(retoid);
1275 ber_bvfree(bv);
1277 return NT_STATUS_OK;
1280 /**********************************************************************
1281 Delete entry from LDAP for username
1282 *********************************************************************/
1283 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
1285 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1286 const char *sname;
1287 int rc;
1288 LDAPMessage *result;
1289 NTSTATUS ret;
1290 char **attr_list;
1291 fstring objclass;
1293 if (!sam_acct) {
1294 DEBUG(0, ("sam_acct was NULL!\n"));
1295 return NT_STATUS_INVALID_PARAMETER;
1298 sname = pdb_get_username(sam_acct);
1300 DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
1302 attr_list= get_userattr_list( ldap_state->schema_ver );
1303 rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
1305 if (rc != LDAP_SUCCESS) {
1306 free_attr_list( attr_list );
1307 return NT_STATUS_NO_SUCH_USER;
1310 switch ( ldap_state->schema_ver )
1312 case SCHEMAVER_SAMBASAMACCOUNT:
1313 fstrcpy( objclass, LDAP_OBJ_SAMBASAMACCOUNT );
1314 break;
1316 case SCHEMAVER_SAMBAACCOUNT:
1317 fstrcpy( objclass, LDAP_OBJ_SAMBAACCOUNT );
1318 break;
1319 default:
1320 fstrcpy( objclass, "UNKNOWN" );
1321 DEBUG(0,("ldapsam_delete_sam_account: Unknown schema version specified!\n"));
1322 break;
1325 ret = ldapsam_delete_entry(ldap_state, result, objclass, attr_list );
1326 ldap_msgfree(result);
1327 free_attr_list( attr_list );
1329 return ret;
1332 /**********************************************************************
1333 Helper function to determine for update_sam_account whether
1334 we need LDAP modification.
1335 *********************************************************************/
1336 static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
1337 enum pdb_elements element)
1339 return IS_SAM_CHANGED(sampass, element);
1342 /**********************************************************************
1343 Update SAM_ACCOUNT
1344 *********************************************************************/
1345 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1347 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1348 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1349 int rc;
1350 char *dn;
1351 LDAPMessage *result;
1352 LDAPMessage *entry;
1353 LDAPMod **mods;
1354 char **attr_list;
1356 result = pdb_get_backend_private_data(newpwd, my_methods);
1357 if (!result) {
1358 attr_list = get_userattr_list(ldap_state->schema_ver);
1359 rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list );
1360 free_attr_list( attr_list );
1361 if (rc != LDAP_SUCCESS) {
1362 return NT_STATUS_UNSUCCESSFUL;
1364 pdb_set_backend_private_data(newpwd, result, private_data_free_fn, my_methods, PDB_CHANGED);
1367 if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
1368 DEBUG(0, ("No user to modify!\n"));
1369 return NT_STATUS_UNSUCCESSFUL;
1372 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1373 dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
1375 DEBUG(4, ("user %s to be modified has dn: %s\n", pdb_get_username(newpwd), dn));
1377 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
1378 element_is_changed)) {
1379 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1380 ldap_memfree(dn);
1381 return NT_STATUS_UNSUCCESSFUL;
1384 if (mods == NULL) {
1385 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
1386 pdb_get_username(newpwd)));
1387 ldap_mods_free(mods, True);
1388 ldap_memfree(dn);
1389 return NT_STATUS_OK;
1392 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed);
1393 ldap_mods_free(mods,True);
1394 ldap_memfree(dn);
1396 if (!NT_STATUS_IS_OK(ret)) {
1397 char *ld_error = NULL;
1398 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1399 &ld_error);
1400 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
1401 pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
1402 SAFE_FREE(ld_error);
1403 return ret;
1406 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
1407 pdb_get_username(newpwd)));
1408 return NT_STATUS_OK;
1411 /**********************************************************************
1412 Helper function to determine for update_sam_account whether
1413 we need LDAP modification.
1414 *********************************************************************/
1415 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
1416 enum pdb_elements element)
1418 return (IS_SAM_SET(sampass, element) ||
1419 IS_SAM_CHANGED(sampass, element));
1422 /**********************************************************************
1423 Add SAM_ACCOUNT to LDAP
1424 *********************************************************************/
1426 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1428 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1429 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1430 int rc;
1431 LDAPMessage *result = NULL;
1432 LDAPMessage *entry = NULL;
1433 pstring dn;
1434 LDAPMod **mods = NULL;
1435 int ldap_op;
1436 uint32 num_result;
1437 char **attr_list;
1438 char *escape_user;
1439 const char *username = pdb_get_username(newpwd);
1440 const DOM_SID *sid = pdb_get_user_sid(newpwd);
1441 pstring filter;
1442 fstring sid_string;
1444 if (!username || !*username) {
1445 DEBUG(0, ("Cannot add user without a username!\n"));
1446 return NT_STATUS_INVALID_PARAMETER;
1449 /* free this list after the second search or in case we exit on failure */
1450 attr_list = get_userattr_list(ldap_state->schema_ver);
1452 rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list);
1454 if (rc != LDAP_SUCCESS) {
1455 free_attr_list( attr_list );
1456 return NT_STATUS_UNSUCCESSFUL;
1459 if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
1460 DEBUG(0,("User '%s' already in the base, with samba attributes\n",
1461 username));
1462 ldap_msgfree(result);
1463 free_attr_list( attr_list );
1464 return NT_STATUS_UNSUCCESSFUL;
1466 ldap_msgfree(result);
1467 result = NULL;
1469 if (element_is_set_or_changed(newpwd, PDB_USERSID)) {
1470 rc = ldapsam_get_ldap_user_by_sid(ldap_state,
1471 sid, &result);
1472 if (rc == LDAP_SUCCESS) {
1473 if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
1474 DEBUG(0,("SID '%s' already in the base, with samba attributes\n",
1475 sid_to_string(sid_string, sid)));
1476 free_attr_list( attr_list );
1477 return NT_STATUS_UNSUCCESSFUL;
1479 ldap_msgfree(result);
1483 /* does the entry already exist but without a samba attributes?
1484 we need to return the samba attributes here */
1486 escape_user = escape_ldap_string_alloc( username );
1487 pstrcpy( filter, lp_ldap_filter() );
1488 all_string_sub( filter, "%u", escape_user, sizeof(filter) );
1489 SAFE_FREE( escape_user );
1491 rc = smbldap_search_suffix(ldap_state->smbldap_state,
1492 filter, attr_list, &result);
1493 if ( rc != LDAP_SUCCESS ) {
1494 free_attr_list( attr_list );
1495 return NT_STATUS_UNSUCCESSFUL;
1498 num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1500 if (num_result > 1) {
1501 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1502 free_attr_list( attr_list );
1503 ldap_msgfree(result);
1504 return NT_STATUS_UNSUCCESSFUL;
1507 /* Check if we need to update an existing entry */
1508 if (num_result == 1) {
1509 char *tmp;
1511 DEBUG(3,("User exists without samba attributes: adding them\n"));
1512 ldap_op = LDAP_MOD_REPLACE;
1513 entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
1514 tmp = ldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
1515 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1516 ldap_memfree (tmp);
1518 } else if (ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT) {
1520 /* There might be a SID for this account already - say an idmap entry */
1522 pstr_sprintf(filter, "(&(%s=%s)(|(objectClass=%s)(objectClass=%s)))",
1523 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
1524 sid_to_string(sid_string, sid),
1525 LDAP_OBJ_IDMAP_ENTRY,
1526 LDAP_OBJ_SID_ENTRY);
1528 rc = smbldap_search_suffix(ldap_state->smbldap_state,
1529 filter, attr_list, &result);
1531 if ( rc != LDAP_SUCCESS ) {
1532 free_attr_list( attr_list );
1533 return NT_STATUS_UNSUCCESSFUL;
1536 num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1538 if (num_result > 1) {
1539 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1540 free_attr_list( attr_list );
1541 ldap_msgfree(result);
1542 return NT_STATUS_UNSUCCESSFUL;
1545 /* Check if we need to update an existing entry */
1546 if (num_result == 1) {
1547 char *tmp;
1549 DEBUG(3,("User exists without samba attributes: adding them\n"));
1550 ldap_op = LDAP_MOD_REPLACE;
1551 entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
1552 tmp = ldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
1553 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1554 ldap_memfree (tmp);
1558 free_attr_list( attr_list );
1560 if (num_result == 0) {
1561 /* Check if we need to add an entry */
1562 DEBUG(3,("Adding new user\n"));
1563 ldap_op = LDAP_MOD_ADD;
1564 if (username[strlen(username)-1] == '$') {
1565 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
1566 } else {
1567 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
1571 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
1572 element_is_set_or_changed)) {
1573 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
1574 ldap_msgfree(result);
1575 return NT_STATUS_UNSUCCESSFUL;
1578 ldap_msgfree(result);
1580 if (mods == NULL) {
1581 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
1582 return NT_STATUS_UNSUCCESSFUL;
1584 switch ( ldap_state->schema_ver )
1586 case SCHEMAVER_SAMBAACCOUNT:
1587 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBAACCOUNT);
1588 break;
1589 case SCHEMAVER_SAMBASAMACCOUNT:
1590 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBASAMACCOUNT);
1591 break;
1592 default:
1593 DEBUG(0,("ldapsam_add_sam_account: invalid schema version specified\n"));
1594 break;
1597 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed);
1598 if (!NT_STATUS_IS_OK(ret)) {
1599 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
1600 pdb_get_username(newpwd),dn));
1601 ldap_mods_free(mods, True);
1602 return ret;
1605 DEBUG(2,("added: uid == %s in the LDAP database\n", pdb_get_username(newpwd)));
1606 ldap_mods_free(mods, True);
1608 return NT_STATUS_OK;
1611 /**********************************************************************
1612 *********************************************************************/
1614 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
1615 const char *filter,
1616 LDAPMessage ** result)
1618 int scope = LDAP_SCOPE_SUBTREE;
1619 int rc;
1620 char **attr_list;
1622 DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
1625 attr_list = get_attr_list(groupmap_attr_list);
1626 rc = smbldap_search(ldap_state->smbldap_state,
1627 lp_ldap_group_suffix (), scope,
1628 filter, attr_list, 0, result);
1629 free_attr_list( attr_list );
1631 if (rc != LDAP_SUCCESS) {
1632 char *ld_error = NULL;
1633 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1634 &ld_error);
1635 DEBUG(0, ("ldapsam_search_one_group: "
1636 "Problem during the LDAP search: LDAP error: %s (%s)",
1637 ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
1638 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
1639 lp_ldap_group_suffix(), filter));
1640 SAFE_FREE(ld_error);
1643 return rc;
1646 /**********************************************************************
1647 *********************************************************************/
1649 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
1650 GROUP_MAP *map, LDAPMessage *entry)
1652 pstring temp;
1654 if (ldap_state == NULL || map == NULL || entry == NULL ||
1655 ldap_state->smbldap_state->ldap_struct == NULL)
1657 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
1658 return False;
1661 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
1662 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), temp))
1664 DEBUG(0, ("Mandatory attribute %s not found\n",
1665 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GIDNUMBER)));
1666 return False;
1668 DEBUG(2, ("Entry found for group: %s\n", temp));
1670 map->gid = (gid_t)atol(temp);
1672 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
1673 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID), temp))
1675 DEBUG(0, ("Mandatory attribute %s not found\n",
1676 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID)));
1677 return False;
1679 string_to_sid(&map->sid, temp);
1681 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
1682 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), temp))
1684 DEBUG(0, ("Mandatory attribute %s not found\n",
1685 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE)));
1686 return False;
1688 map->sid_name_use = (uint32)atol(temp);
1690 if ((map->sid_name_use < SID_NAME_USER) ||
1691 (map->sid_name_use > SID_NAME_UNKNOWN)) {
1692 DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use));
1693 return False;
1696 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
1697 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), temp))
1699 temp[0] = '\0';
1700 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
1701 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_CN), temp))
1703 DEBUG(0, ("Attributes cn not found either "
1704 "for gidNumber(%lu)\n",(unsigned long)map->gid));
1705 return False;
1708 fstrcpy(map->nt_name, temp);
1710 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
1711 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), temp))
1713 temp[0] = '\0';
1715 fstrcpy(map->comment, temp);
1717 return True;
1720 /**********************************************************************
1721 *********************************************************************/
1723 static BOOL init_ldap_from_group(LDAP *ldap_struct,
1724 LDAPMessage *existing,
1725 LDAPMod ***mods,
1726 const GROUP_MAP *map)
1728 pstring tmp;
1730 if (mods == NULL || map == NULL) {
1731 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
1732 return False;
1735 *mods = NULL;
1737 sid_to_string(tmp, &map->sid);
1738 smbldap_make_mod(ldap_struct, existing, mods,
1739 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID), tmp);
1740 pstr_sprintf(tmp, "%i", map->sid_name_use);
1741 smbldap_make_mod(ldap_struct, existing, mods,
1742 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), tmp);
1744 smbldap_make_mod(ldap_struct, existing, mods,
1745 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), map->nt_name);
1746 smbldap_make_mod(ldap_struct, existing, mods,
1747 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), map->comment);
1749 return True;
1752 /**********************************************************************
1753 *********************************************************************/
1755 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
1756 const char *filter,
1757 GROUP_MAP *map)
1759 struct ldapsam_privates *ldap_state =
1760 (struct ldapsam_privates *)methods->private_data;
1761 LDAPMessage *result;
1762 LDAPMessage *entry;
1763 int count;
1765 if (ldapsam_search_one_group(ldap_state, filter, &result)
1766 != LDAP_SUCCESS) {
1767 return NT_STATUS_NO_SUCH_GROUP;
1770 count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1772 if (count < 1) {
1773 DEBUG(4, ("Did not find group\n"));
1774 ldap_msgfree(result);
1775 return NT_STATUS_NO_SUCH_GROUP;
1778 if (count > 1) {
1779 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
1780 filter, count));
1781 ldap_msgfree(result);
1782 return NT_STATUS_NO_SUCH_GROUP;
1785 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1787 if (!entry) {
1788 ldap_msgfree(result);
1789 return NT_STATUS_UNSUCCESSFUL;
1792 if (!init_group_from_ldap(ldap_state, map, entry)) {
1793 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
1794 filter));
1795 ldap_msgfree(result);
1796 return NT_STATUS_NO_SUCH_GROUP;
1799 ldap_msgfree(result);
1800 return NT_STATUS_OK;
1803 /**********************************************************************
1804 *********************************************************************/
1806 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1807 DOM_SID sid)
1809 pstring filter;
1811 pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
1812 LDAP_OBJ_GROUPMAP,
1813 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID),
1814 sid_string_static(&sid));
1816 return ldapsam_getgroup(methods, filter, map);
1819 /**********************************************************************
1820 *********************************************************************/
1822 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1823 gid_t gid)
1825 pstring filter;
1827 pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))",
1828 LDAP_OBJ_GROUPMAP,
1829 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
1830 (unsigned long)gid);
1832 return ldapsam_getgroup(methods, filter, map);
1835 /**********************************************************************
1836 *********************************************************************/
1838 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1839 const char *name)
1841 pstring filter;
1842 char *escape_name = escape_ldap_string_alloc(name);
1844 if (!escape_name) {
1845 return NT_STATUS_NO_MEMORY;
1848 pstr_sprintf(filter, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))",
1849 LDAP_OBJ_GROUPMAP,
1850 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), escape_name,
1851 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), escape_name);
1853 SAFE_FREE(escape_name);
1855 return ldapsam_getgroup(methods, filter, map);
1858 /**********************************************************************
1859 *********************************************************************/
1861 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
1862 gid_t gid,
1863 LDAPMessage **result)
1865 pstring filter;
1867 pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))",
1868 LDAP_OBJ_POSIXGROUP,
1869 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
1870 (unsigned long)gid);
1872 return ldapsam_search_one_group(ldap_state, filter, result);
1875 /**********************************************************************
1876 *********************************************************************/
1878 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
1879 GROUP_MAP *map)
1881 struct ldapsam_privates *ldap_state =
1882 (struct ldapsam_privates *)methods->private_data;
1883 LDAPMessage *result = NULL;
1884 LDAPMod **mods = NULL;
1885 int count;
1887 char *tmp;
1888 pstring dn;
1889 LDAPMessage *entry;
1891 GROUP_MAP dummy;
1893 int rc;
1895 if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
1896 map->gid))) {
1897 DEBUG(0, ("Group %ld already exists in LDAP\n", (unsigned long)map->gid));
1898 return NT_STATUS_UNSUCCESSFUL;
1901 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
1902 if (rc != LDAP_SUCCESS) {
1903 ldap_msgfree(result);
1904 return NT_STATUS_UNSUCCESSFUL;
1907 count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1909 if ( count == 0 ) {
1910 ldap_msgfree(result);
1911 return NT_STATUS_UNSUCCESSFUL;
1914 if (count > 1) {
1915 DEBUG(2, ("Group %lu must exist exactly once in LDAP\n",
1916 (unsigned long)map->gid));
1917 ldap_msgfree(result);
1918 return NT_STATUS_UNSUCCESSFUL;
1921 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1922 tmp = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
1923 pstrcpy(dn, tmp);
1924 ldap_memfree(tmp);
1926 if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
1927 result, &mods, map)) {
1928 DEBUG(0, ("init_ldap_from_group failed!\n"));
1929 ldap_mods_free(mods, True);
1930 ldap_msgfree(result);
1931 return NT_STATUS_UNSUCCESSFUL;
1934 ldap_msgfree(result);
1936 if (mods == NULL) {
1937 DEBUG(0, ("mods is empty\n"));
1938 return NT_STATUS_UNSUCCESSFUL;
1941 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP );
1943 rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
1944 ldap_mods_free(mods, True);
1946 if (rc != LDAP_SUCCESS) {
1947 char *ld_error = NULL;
1948 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1949 &ld_error);
1950 DEBUG(0, ("failed to add group %lu error: %s (%s)\n", (unsigned long)map->gid,
1951 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
1952 SAFE_FREE(ld_error);
1953 return NT_STATUS_UNSUCCESSFUL;
1956 DEBUG(2, ("successfully modified group %lu in LDAP\n", (unsigned long)map->gid));
1957 return NT_STATUS_OK;
1960 /**********************************************************************
1961 *********************************************************************/
1963 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
1964 GROUP_MAP *map)
1966 struct ldapsam_privates *ldap_state =
1967 (struct ldapsam_privates *)methods->private_data;
1968 int rc;
1969 char *dn;
1970 LDAPMessage *result;
1971 LDAPMessage *entry;
1972 LDAPMod **mods;
1974 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
1976 if (rc != LDAP_SUCCESS) {
1977 return NT_STATUS_UNSUCCESSFUL;
1980 if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
1981 DEBUG(0, ("No group to modify!\n"));
1982 ldap_msgfree(result);
1983 return NT_STATUS_UNSUCCESSFUL;
1986 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1987 dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
1989 if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
1990 result, &mods, map)) {
1991 DEBUG(0, ("init_ldap_from_group failed\n"));
1992 ldap_msgfree(result);
1993 return NT_STATUS_UNSUCCESSFUL;
1996 ldap_msgfree(result);
1998 if (mods == NULL) {
1999 DEBUG(4, ("mods is empty: nothing to do\n"));
2000 return NT_STATUS_UNSUCCESSFUL;
2003 rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
2005 ldap_mods_free(mods, True);
2007 if (rc != LDAP_SUCCESS) {
2008 char *ld_error = NULL;
2009 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2010 &ld_error);
2011 DEBUG(0, ("failed to modify group %lu error: %s (%s)\n", (unsigned long)map->gid,
2012 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2013 SAFE_FREE(ld_error);
2016 DEBUG(2, ("successfully modified group %lu in LDAP\n", (unsigned long)map->gid));
2017 return NT_STATUS_OK;
2020 /**********************************************************************
2021 *********************************************************************/
2023 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
2024 DOM_SID sid)
2026 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)methods->private_data;
2027 pstring sidstring, filter;
2028 LDAPMessage *result;
2029 int rc;
2030 NTSTATUS ret;
2031 char **attr_list;
2033 sid_to_string(sidstring, &sid);
2035 pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
2036 LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID, sidstring);
2038 rc = ldapsam_search_one_group(ldap_state, filter, &result);
2040 if (rc != LDAP_SUCCESS) {
2041 return NT_STATUS_NO_SUCH_GROUP;
2044 attr_list = get_attr_list( groupmap_attr_list_to_delete );
2045 ret = ldapsam_delete_entry(ldap_state, result, LDAP_OBJ_GROUPMAP, attr_list);
2046 free_attr_list ( attr_list );
2048 ldap_msgfree(result);
2050 return ret;
2053 /**********************************************************************
2054 *********************************************************************/
2056 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update)
2058 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2059 fstring filter;
2060 int rc;
2061 char **attr_list;
2063 pstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_GROUPMAP);
2064 attr_list = get_attr_list( groupmap_attr_list );
2065 rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
2066 LDAP_SCOPE_SUBTREE, filter,
2067 attr_list, 0, &ldap_state->result);
2068 free_attr_list( attr_list );
2070 if (rc != LDAP_SUCCESS) {
2071 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2072 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_group_suffix(), filter));
2073 ldap_msgfree(ldap_state->result);
2074 ldap_state->result = NULL;
2075 return NT_STATUS_UNSUCCESSFUL;
2078 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2079 ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
2080 ldap_state->result)));
2082 ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->result);
2083 ldap_state->index = 0;
2085 return NT_STATUS_OK;
2088 /**********************************************************************
2089 *********************************************************************/
2091 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
2093 ldapsam_endsampwent(my_methods);
2096 /**********************************************************************
2097 *********************************************************************/
2099 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
2100 GROUP_MAP *map)
2102 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2103 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2104 BOOL bret = False;
2106 while (!bret) {
2107 if (!ldap_state->entry)
2108 return ret;
2110 ldap_state->index++;
2111 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
2113 ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
2114 ldap_state->entry);
2117 return NT_STATUS_OK;
2120 /**********************************************************************
2121 *********************************************************************/
2123 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
2124 enum SID_NAME_USE sid_name_use,
2125 GROUP_MAP **rmap, int *num_entries,
2126 BOOL unix_only)
2128 GROUP_MAP map;
2129 GROUP_MAP *mapt;
2130 int entries = 0;
2131 NTSTATUS nt_status;
2133 *num_entries = 0;
2134 *rmap = NULL;
2136 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
2137 DEBUG(0, ("Unable to open passdb\n"));
2138 return NT_STATUS_ACCESS_DENIED;
2141 while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) {
2142 if (sid_name_use != SID_NAME_UNKNOWN &&
2143 sid_name_use != map.sid_name_use) {
2144 DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
2145 continue;
2147 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
2148 DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
2149 continue;
2152 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
2153 if (!mapt) {
2154 DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
2155 SAFE_FREE(*rmap);
2156 return NT_STATUS_UNSUCCESSFUL;
2158 else
2159 (*rmap) = mapt;
2161 mapt[entries] = map;
2163 entries += 1;
2166 ldapsam_endsamgrent(methods);
2168 *num_entries = entries;
2170 return NT_STATUS_OK;
2173 /**********************************************************************
2174 Housekeeping
2175 *********************************************************************/
2177 static void free_private_data(void **vp)
2179 struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
2181 smbldap_free_struct(&(*ldap_state)->smbldap_state);
2183 *ldap_state = NULL;
2185 /* No need to free any further, as it is talloc()ed */
2188 /**********************************************************************
2189 Intitalise the parts of the pdb_context that are common to all pdb_ldap modes
2190 *********************************************************************/
2192 static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method,
2193 const char *location)
2195 NTSTATUS nt_status;
2196 struct ldapsam_privates *ldap_state;
2198 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
2199 return nt_status;
2202 (*pdb_method)->name = "ldapsam";
2204 (*pdb_method)->setsampwent = ldapsam_setsampwent;
2205 (*pdb_method)->endsampwent = ldapsam_endsampwent;
2206 (*pdb_method)->getsampwent = ldapsam_getsampwent;
2207 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
2208 (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
2209 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
2210 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
2211 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
2213 (*pdb_method)->getgrsid = ldapsam_getgrsid;
2214 (*pdb_method)->getgrgid = ldapsam_getgrgid;
2215 (*pdb_method)->getgrnam = ldapsam_getgrnam;
2216 (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
2217 (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
2218 (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
2219 (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
2221 /* TODO: Setup private data and free */
2223 ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(*ldap_state));
2224 if (!ldap_state) {
2225 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
2226 return NT_STATUS_NO_MEMORY;
2229 if (!NT_STATUS_IS_OK(nt_status =
2230 smbldap_init(pdb_context->mem_ctx, location,
2231 &ldap_state->smbldap_state)));
2233 ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, get_global_sam_name());
2234 if (!ldap_state->domain_name) {
2235 return NT_STATUS_NO_MEMORY;
2238 (*pdb_method)->private_data = ldap_state;
2240 (*pdb_method)->free_private_data = free_private_data;
2242 return NT_STATUS_OK;
2245 /**********************************************************************
2246 Initialise the 'compat' mode for pdb_ldap
2247 *********************************************************************/
2249 static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2251 NTSTATUS nt_status;
2252 struct ldapsam_privates *ldap_state;
2254 #ifdef WITH_LDAP_SAMCONFIG
2255 if (!location) {
2256 int ldap_port = lp_ldap_port();
2258 /* remap default port if not using SSL (ie clear or TLS) */
2259 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
2260 ldap_port = 389;
2263 location = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port);
2264 if (!location) {
2265 return NT_STATUS_NO_MEMORY;
2268 #endif
2270 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
2271 return nt_status;
2274 (*pdb_method)->name = "ldapsam_compat";
2276 ldap_state = (*pdb_method)->private_data;
2277 ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
2279 sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
2281 return NT_STATUS_OK;
2284 /**********************************************************************
2285 Initialise the normal mode for pdb_ldap
2286 *********************************************************************/
2288 static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2290 NTSTATUS nt_status;
2291 struct ldapsam_privates *ldap_state;
2292 uint32 alg_rid_base;
2293 pstring alg_rid_base_string;
2294 LDAPMessage *result = NULL;
2295 LDAPMessage *entry = NULL;
2296 DOM_SID ldap_domain_sid;
2297 DOM_SID secrets_domain_sid;
2298 pstring domain_sid_string;
2300 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
2301 return nt_status;
2304 (*pdb_method)->name = "ldapsam";
2306 ldap_state = (*pdb_method)->private_data;
2307 ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
2309 /* Try to setup the Domain Name, Domain SID, algorithmic rid base */
2311 nt_status = smbldap_search_domain_info(ldap_state->smbldap_state, &result,
2312 ldap_state->domain_name, True);
2314 if ( !NT_STATUS_IS_OK(nt_status) ) {
2315 DEBUG(2, ("WARNING: Could not get domain info, nor add one to the domain\n"));
2316 DEBUGADD(2, ("Continuing on regardless, will be unable to allocate new users/groups, "
2317 "and will risk BDCs having inconsistant SIDs\n"));
2318 sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
2319 return NT_STATUS_OK;
2322 /* Given that the above might fail, everything below this must be optional */
2324 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
2325 if (!entry) {
2326 DEBUG(0, ("Could not get domain info entry\n"));
2327 ldap_msgfree(result);
2328 return NT_STATUS_UNSUCCESSFUL;
2331 if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
2332 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
2333 domain_sid_string))
2335 BOOL found_sid;
2336 string_to_sid(&ldap_domain_sid, domain_sid_string);
2337 found_sid = secrets_fetch_domain_sid(ldap_state->domain_name, &secrets_domain_sid);
2338 if (!found_sid || !sid_equal(&secrets_domain_sid, &ldap_domain_sid)) {
2339 /* reset secrets.tdb sid */
2340 secrets_store_domain_sid(ldap_state->domain_name, &ldap_domain_sid);
2342 sid_copy(&ldap_state->domain_sid, &ldap_domain_sid);
2345 if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
2346 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ALGORITHMIC_RID_BASE),
2347 alg_rid_base_string))
2349 alg_rid_base = (uint32)atol(alg_rid_base_string);
2350 if (alg_rid_base != algorithmic_rid_base()) {
2351 DEBUG(0, ("The value of 'algorithmic RID base' has changed since the LDAP\n"
2352 "database was initialised. Aborting. \n"));
2353 ldap_msgfree(result);
2354 return NT_STATUS_UNSUCCESSFUL;
2357 ldap_msgfree(result);
2359 return NT_STATUS_OK;
2362 NTSTATUS pdb_ldap_init(void)
2364 NTSTATUS nt_status;
2365 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam", pdb_init_ldapsam)))
2366 return nt_status;
2368 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat)))
2369 return nt_status;
2371 return NT_STATUS_OK;