trying to get HEAD building again. If you want the code
[Samba/gbeck.git] / source / passdb / pdb_ldap.c
bloba4ee4dbd4bfe7ee45ff7882c46acc9533e60de99
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_memfree(*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 snprintf( objclass_filter, sizeof(objclass_filter)-1, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT );
165 break;
166 case SCHEMAVER_SAMBASAMACCOUNT:
167 snprintf( objclass_filter, sizeof(objclass_filter)-1, "(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 snprintf(filter, sizeof(filter)-1, "(&%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 snprintf(filter, sizeof(filter)-1, "(&(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 snprintf(filter, sizeof(filter)-1, "(&(%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 snprintf( filter, sizeof(filter)-1, "(&%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 plaittext 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 return NT_STATUS_UNSUCCESSFUL;
1383 if (mods == NULL) {
1384 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
1385 pdb_get_username(newpwd)));
1386 ldap_mods_free(mods, True);
1387 return NT_STATUS_OK;
1390 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed);
1391 ldap_mods_free(mods,True);
1393 if (!NT_STATUS_IS_OK(ret)) {
1394 char *ld_error = NULL;
1395 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1396 &ld_error);
1397 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
1398 pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
1399 SAFE_FREE(ld_error);
1400 return ret;
1403 DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
1404 pdb_get_username(newpwd)));
1405 return NT_STATUS_OK;
1408 /**********************************************************************
1409 Helper function to determine for update_sam_account whether
1410 we need LDAP modification.
1411 *********************************************************************/
1412 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
1413 enum pdb_elements element)
1415 return (IS_SAM_SET(sampass, element) ||
1416 IS_SAM_CHANGED(sampass, element));
1419 /**********************************************************************
1420 Add SAM_ACCOUNT to LDAP
1421 *********************************************************************/
1423 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1425 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1426 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1427 int rc;
1428 LDAPMessage *result = NULL;
1429 LDAPMessage *entry = NULL;
1430 pstring dn;
1431 LDAPMod **mods = NULL;
1432 int ldap_op;
1433 uint32 num_result;
1434 char **attr_list;
1435 char *escape_user;
1436 const char *username = pdb_get_username(newpwd);
1437 const DOM_SID *sid = pdb_get_user_sid(newpwd);
1438 pstring filter;
1439 fstring sid_string;
1441 if (!username || !*username) {
1442 DEBUG(0, ("Cannot add user without a username!\n"));
1443 return NT_STATUS_INVALID_PARAMETER;
1446 /* free this list after the second search or in case we exit on failure */
1447 attr_list = get_userattr_list(ldap_state->schema_ver);
1449 rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list);
1451 if (rc != LDAP_SUCCESS) {
1452 free_attr_list( attr_list );
1453 return NT_STATUS_UNSUCCESSFUL;
1456 if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
1457 DEBUG(0,("User '%s' already in the base, with samba attributes\n",
1458 username));
1459 ldap_msgfree(result);
1460 free_attr_list( attr_list );
1461 return NT_STATUS_UNSUCCESSFUL;
1463 ldap_msgfree(result);
1464 result = NULL;
1466 if (element_is_set_or_changed(newpwd, PDB_USERSID)) {
1467 rc = ldapsam_get_ldap_user_by_sid(ldap_state,
1468 sid, &result);
1469 if (rc == LDAP_SUCCESS) {
1470 if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
1471 DEBUG(0,("SID '%s' already in the base, with samba attributes\n",
1472 sid_to_string(sid_string, sid)));
1473 free_attr_list( attr_list );
1474 return NT_STATUS_UNSUCCESSFUL;
1476 ldap_msgfree(result);
1480 /* does the entry already exist but without a samba attributes?
1481 we need to return the samba attributes here */
1483 escape_user = escape_ldap_string_alloc( username );
1484 pstrcpy( filter, lp_ldap_filter() );
1485 all_string_sub( filter, "%u", escape_user, sizeof(filter) );
1486 SAFE_FREE( escape_user );
1488 rc = smbldap_search_suffix(ldap_state->smbldap_state,
1489 filter, attr_list, &result);
1490 if ( rc != LDAP_SUCCESS ) {
1491 free_attr_list( attr_list );
1492 return NT_STATUS_UNSUCCESSFUL;
1495 num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1497 if (num_result > 1) {
1498 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1499 free_attr_list( attr_list );
1500 ldap_msgfree(result);
1501 return NT_STATUS_UNSUCCESSFUL;
1504 /* Check if we need to update an existing entry */
1505 if (num_result == 1) {
1506 char *tmp;
1508 DEBUG(3,("User exists without samba attributes: adding them\n"));
1509 ldap_op = LDAP_MOD_REPLACE;
1510 entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
1511 tmp = ldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
1512 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1513 ldap_memfree (tmp);
1515 } else if (ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT) {
1517 /* There might be a SID for this account already - say an idmap entry */
1519 snprintf(filter, sizeof(filter)-1, "(&(%s=%s)(|(objectClass=%s)(objectClass=%s)))",
1520 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
1521 sid_to_string(sid_string, sid),
1522 LDAP_OBJ_IDMAP_ENTRY,
1523 LDAP_OBJ_SID_ENTRY);
1525 rc = smbldap_search_suffix(ldap_state->smbldap_state,
1526 filter, attr_list, &result);
1528 if ( rc != LDAP_SUCCESS ) {
1529 free_attr_list( attr_list );
1530 return NT_STATUS_UNSUCCESSFUL;
1533 num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1535 if (num_result > 1) {
1536 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1537 free_attr_list( attr_list );
1538 ldap_msgfree(result);
1539 return NT_STATUS_UNSUCCESSFUL;
1542 /* Check if we need to update an existing entry */
1543 if (num_result == 1) {
1544 char *tmp;
1546 DEBUG(3,("User exists without samba attributes: adding them\n"));
1547 ldap_op = LDAP_MOD_REPLACE;
1548 entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
1549 tmp = ldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
1550 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1551 ldap_memfree (tmp);
1555 free_attr_list( attr_list );
1557 if (num_result == 0) {
1558 /* Check if we need to add an entry */
1559 DEBUG(3,("Adding new user\n"));
1560 ldap_op = LDAP_MOD_ADD;
1561 if (username[strlen(username)-1] == '$') {
1562 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
1563 } else {
1564 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
1568 if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
1569 element_is_set_or_changed)) {
1570 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
1571 ldap_msgfree(result);
1572 return NT_STATUS_UNSUCCESSFUL;
1575 ldap_msgfree(result);
1577 if (mods == NULL) {
1578 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
1579 return NT_STATUS_UNSUCCESSFUL;
1581 switch ( ldap_state->schema_ver )
1583 case SCHEMAVER_SAMBAACCOUNT:
1584 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBAACCOUNT);
1585 break;
1586 case SCHEMAVER_SAMBASAMACCOUNT:
1587 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBASAMACCOUNT);
1588 break;
1589 default:
1590 DEBUG(0,("ldapsam_add_sam_account: invalid schema version specified\n"));
1591 break;
1594 ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed);
1595 if (!NT_STATUS_IS_OK(ret)) {
1596 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
1597 pdb_get_username(newpwd),dn));
1598 ldap_mods_free(mods, True);
1599 return ret;
1602 DEBUG(2,("added: uid == %s in the LDAP database\n", pdb_get_username(newpwd)));
1603 ldap_mods_free(mods, True);
1605 return NT_STATUS_OK;
1608 /**********************************************************************
1609 *********************************************************************/
1611 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
1612 const char *filter,
1613 LDAPMessage ** result)
1615 int scope = LDAP_SCOPE_SUBTREE;
1616 int rc;
1617 char **attr_list;
1619 DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
1622 attr_list = get_attr_list(groupmap_attr_list);
1623 rc = smbldap_search(ldap_state->smbldap_state,
1624 lp_ldap_group_suffix (), scope,
1625 filter, attr_list, 0, result);
1626 free_attr_list( attr_list );
1628 if (rc != LDAP_SUCCESS) {
1629 char *ld_error = NULL;
1630 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1631 &ld_error);
1632 DEBUG(0, ("ldapsam_search_one_group: "
1633 "Problem during the LDAP search: LDAP error: %s (%s)",
1634 ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
1635 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
1636 lp_ldap_group_suffix(), filter));
1637 SAFE_FREE(ld_error);
1640 return rc;
1643 /**********************************************************************
1644 *********************************************************************/
1646 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
1647 GROUP_MAP *map, LDAPMessage *entry)
1649 pstring temp;
1651 if (ldap_state == NULL || map == NULL || entry == NULL ||
1652 ldap_state->smbldap_state->ldap_struct == NULL)
1654 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
1655 return False;
1658 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
1659 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), temp))
1661 DEBUG(0, ("Mandatory attribute %s not found\n",
1662 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GIDNUMBER)));
1663 return False;
1665 DEBUG(2, ("Entry found for group: %s\n", temp));
1667 map->gid = (gid_t)atol(temp);
1669 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
1670 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID), temp))
1672 DEBUG(0, ("Mandatory attribute %s not found\n",
1673 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID)));
1674 return False;
1676 string_to_sid(&map->sid, temp);
1678 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
1679 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), temp))
1681 DEBUG(0, ("Mandatory attribute %s not found\n",
1682 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE)));
1683 return False;
1685 map->sid_name_use = (uint32)atol(temp);
1687 if ((map->sid_name_use < SID_NAME_USER) ||
1688 (map->sid_name_use > SID_NAME_UNKNOWN)) {
1689 DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use));
1690 return False;
1693 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
1694 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), temp))
1696 temp[0] = '\0';
1697 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
1698 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_CN), temp))
1700 DEBUG(0, ("Attributes cn not found either "
1701 "for gidNumber(%i)\n",map->gid));
1702 return False;
1705 fstrcpy(map->nt_name, temp);
1707 if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
1708 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), temp))
1710 temp[0] = '\0';
1712 fstrcpy(map->comment, temp);
1714 return True;
1717 /**********************************************************************
1718 *********************************************************************/
1720 static BOOL init_ldap_from_group(LDAP *ldap_struct,
1721 LDAPMessage *existing,
1722 LDAPMod ***mods,
1723 const GROUP_MAP *map)
1725 pstring tmp;
1727 if (mods == NULL || map == NULL) {
1728 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
1729 return False;
1732 *mods = NULL;
1734 sid_to_string(tmp, &map->sid);
1735 smbldap_make_mod(ldap_struct, existing, mods,
1736 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID), tmp);
1737 snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use);
1738 smbldap_make_mod(ldap_struct, existing, mods,
1739 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), tmp);
1741 smbldap_make_mod(ldap_struct, existing, mods,
1742 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), map->nt_name);
1743 smbldap_make_mod(ldap_struct, existing, mods,
1744 get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), map->comment);
1746 return True;
1749 /**********************************************************************
1750 *********************************************************************/
1752 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
1753 const char *filter,
1754 GROUP_MAP *map)
1756 struct ldapsam_privates *ldap_state =
1757 (struct ldapsam_privates *)methods->private_data;
1758 LDAPMessage *result;
1759 LDAPMessage *entry;
1760 int count;
1762 if (ldapsam_search_one_group(ldap_state, filter, &result)
1763 != LDAP_SUCCESS) {
1764 return NT_STATUS_NO_SUCH_GROUP;
1767 count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1769 if (count < 1) {
1770 DEBUG(4, ("Did not find group\n"));
1771 ldap_msgfree(result);
1772 return NT_STATUS_NO_SUCH_GROUP;
1775 if (count > 1) {
1776 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
1777 filter, count));
1778 ldap_msgfree(result);
1779 return NT_STATUS_NO_SUCH_GROUP;
1782 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1784 if (!entry) {
1785 ldap_msgfree(result);
1786 return NT_STATUS_UNSUCCESSFUL;
1789 if (!init_group_from_ldap(ldap_state, map, entry)) {
1790 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
1791 filter));
1792 ldap_msgfree(result);
1793 return NT_STATUS_NO_SUCH_GROUP;
1796 ldap_msgfree(result);
1797 return NT_STATUS_OK;
1800 /**********************************************************************
1801 *********************************************************************/
1803 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
1804 DOM_SID sid)
1806 pstring filter;
1808 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))",
1809 LDAP_OBJ_GROUPMAP,
1810 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID),
1811 sid_string_static(&sid));
1813 return ldapsam_getgroup(methods, filter, map);
1816 /**********************************************************************
1817 *********************************************************************/
1819 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
1820 gid_t gid)
1822 pstring filter;
1824 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%d))",
1825 LDAP_OBJ_GROUPMAP,
1826 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
1827 gid);
1829 return ldapsam_getgroup(methods, filter, map);
1832 /**********************************************************************
1833 *********************************************************************/
1835 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
1836 const char *name)
1838 pstring filter;
1839 char *escape_name = escape_ldap_string_alloc(name);
1841 if (!escape_name) {
1842 return NT_STATUS_NO_MEMORY;
1845 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))",
1846 LDAP_OBJ_GROUPMAP,
1847 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), escape_name,
1848 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), escape_name);
1850 SAFE_FREE(escape_name);
1852 return ldapsam_getgroup(methods, filter, map);
1855 /**********************************************************************
1856 *********************************************************************/
1858 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
1859 gid_t gid,
1860 LDAPMessage **result)
1862 pstring filter;
1864 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%i))",
1865 LDAP_OBJ_POSIXGROUP,
1866 get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
1867 gid);
1869 return ldapsam_search_one_group(ldap_state, filter, result);
1872 /**********************************************************************
1873 *********************************************************************/
1875 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
1876 GROUP_MAP *map)
1878 struct ldapsam_privates *ldap_state =
1879 (struct ldapsam_privates *)methods->private_data;
1880 LDAPMessage *result = NULL;
1881 LDAPMod **mods = NULL;
1882 int count;
1884 char *tmp;
1885 pstring dn;
1886 LDAPMessage *entry;
1888 GROUP_MAP dummy;
1890 int rc;
1892 if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
1893 map->gid))) {
1894 DEBUG(0, ("Group %i already exists in LDAP\n", map->gid));
1895 return NT_STATUS_UNSUCCESSFUL;
1898 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
1899 if (rc != LDAP_SUCCESS) {
1900 return NT_STATUS_UNSUCCESSFUL;
1903 count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
1905 if ( count == 0 )
1906 return NT_STATUS_UNSUCCESSFUL;
1908 if (count > 1) {
1909 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
1910 map->gid));
1911 ldap_msgfree(result);
1912 return NT_STATUS_UNSUCCESSFUL;
1915 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1916 tmp = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
1917 pstrcpy(dn, tmp);
1918 ldap_memfree(tmp);
1920 if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
1921 result, &mods, map)) {
1922 DEBUG(0, ("init_ldap_from_group failed!\n"));
1923 ldap_mods_free(mods, True);
1924 ldap_msgfree(result);
1925 return NT_STATUS_UNSUCCESSFUL;
1928 ldap_msgfree(result);
1930 if (mods == NULL) {
1931 DEBUG(0, ("mods is empty\n"));
1932 return NT_STATUS_UNSUCCESSFUL;
1935 smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP );
1937 rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
1938 ldap_mods_free(mods, True);
1940 if (rc != LDAP_SUCCESS) {
1941 char *ld_error = NULL;
1942 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1943 &ld_error);
1944 DEBUG(0, ("failed to add group %i error: %s (%s)\n", map->gid,
1945 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
1946 SAFE_FREE(ld_error);
1947 return NT_STATUS_UNSUCCESSFUL;
1950 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
1951 return NT_STATUS_OK;
1954 /**********************************************************************
1955 *********************************************************************/
1957 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
1958 GROUP_MAP *map)
1960 struct ldapsam_privates *ldap_state =
1961 (struct ldapsam_privates *)methods->private_data;
1962 int rc;
1963 char *dn;
1964 LDAPMessage *result;
1965 LDAPMessage *entry;
1966 LDAPMod **mods;
1968 rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
1970 if (rc != LDAP_SUCCESS) {
1971 return NT_STATUS_UNSUCCESSFUL;
1974 if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
1975 DEBUG(0, ("No group to modify!\n"));
1976 ldap_msgfree(result);
1977 return NT_STATUS_UNSUCCESSFUL;
1980 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
1981 dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
1983 if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
1984 result, &mods, map)) {
1985 DEBUG(0, ("init_ldap_from_group failed\n"));
1986 ldap_msgfree(result);
1987 return NT_STATUS_UNSUCCESSFUL;
1990 ldap_msgfree(result);
1992 if (mods == NULL) {
1993 DEBUG(4, ("mods is empty: nothing to do\n"));
1994 return NT_STATUS_UNSUCCESSFUL;
1997 rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
1999 ldap_mods_free(mods, True);
2001 if (rc != LDAP_SUCCESS) {
2002 char *ld_error = NULL;
2003 ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2004 &ld_error);
2005 DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map->gid,
2006 ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2007 SAFE_FREE(ld_error);
2010 DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2011 return NT_STATUS_OK;
2014 /**********************************************************************
2015 *********************************************************************/
2017 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
2018 DOM_SID sid)
2020 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)methods->private_data;
2021 pstring sidstring, filter;
2022 LDAPMessage *result;
2023 int rc;
2024 NTSTATUS ret;
2025 char **attr_list;
2027 sid_to_string(sidstring, &sid);
2029 snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))",
2030 LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID, sidstring);
2032 rc = ldapsam_search_one_group(ldap_state, filter, &result);
2034 if (rc != LDAP_SUCCESS) {
2035 return NT_STATUS_NO_SUCH_GROUP;
2038 attr_list = get_attr_list( groupmap_attr_list_to_delete );
2039 ret = ldapsam_delete_entry(ldap_state, result, LDAP_OBJ_GROUPMAP, attr_list);
2040 free_attr_list ( attr_list );
2042 ldap_msgfree(result);
2044 return ret;
2047 /**********************************************************************
2048 *********************************************************************/
2050 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update)
2052 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2053 fstring filter;
2054 int rc;
2055 char **attr_list;
2057 snprintf( filter, sizeof(filter)-1, "(objectclass=%s)", LDAP_OBJ_GROUPMAP);
2058 attr_list = get_attr_list( groupmap_attr_list );
2059 rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
2060 LDAP_SCOPE_SUBTREE, filter,
2061 attr_list, 0, &ldap_state->result);
2062 free_attr_list( attr_list );
2064 if (rc != LDAP_SUCCESS) {
2065 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2066 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_group_suffix(), filter));
2067 ldap_msgfree(ldap_state->result);
2068 ldap_state->result = NULL;
2069 return NT_STATUS_UNSUCCESSFUL;
2072 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2073 ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
2074 ldap_state->result)));
2076 ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->result);
2077 ldap_state->index = 0;
2079 return NT_STATUS_OK;
2082 /**********************************************************************
2083 *********************************************************************/
2085 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
2087 ldapsam_endsampwent(my_methods);
2090 /**********************************************************************
2091 *********************************************************************/
2093 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
2094 GROUP_MAP *map)
2096 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2097 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2098 BOOL bret = False;
2100 while (!bret) {
2101 if (!ldap_state->entry)
2102 return ret;
2104 ldap_state->index++;
2105 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
2107 ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
2108 ldap_state->entry);
2111 return NT_STATUS_OK;
2114 /**********************************************************************
2115 *********************************************************************/
2117 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
2118 enum SID_NAME_USE sid_name_use,
2119 GROUP_MAP **rmap, int *num_entries,
2120 BOOL unix_only)
2122 GROUP_MAP map;
2123 GROUP_MAP *mapt;
2124 int entries = 0;
2125 NTSTATUS nt_status;
2127 *num_entries = 0;
2128 *rmap = NULL;
2130 if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
2131 DEBUG(0, ("Unable to open passdb\n"));
2132 return NT_STATUS_ACCESS_DENIED;
2135 while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) {
2136 if (sid_name_use != SID_NAME_UNKNOWN &&
2137 sid_name_use != map.sid_name_use) {
2138 DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
2139 continue;
2141 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
2142 DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
2143 continue;
2146 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
2147 if (!mapt) {
2148 DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
2149 SAFE_FREE(*rmap);
2150 return NT_STATUS_UNSUCCESSFUL;
2152 else
2153 (*rmap) = mapt;
2155 mapt[entries] = map;
2157 entries += 1;
2160 ldapsam_endsamgrent(methods);
2162 *num_entries = entries;
2164 return NT_STATUS_OK;
2167 /**********************************************************************
2168 Housekeeping
2169 *********************************************************************/
2171 static void free_private_data(void **vp)
2173 struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
2175 smbldap_free_struct(&(*ldap_state)->smbldap_state);
2177 *ldap_state = NULL;
2179 /* No need to free any further, as it is talloc()ed */
2182 /**********************************************************************
2183 Intitalise the parts of the pdb_context that are common to all pdb_ldap modes
2184 *********************************************************************/
2186 static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method,
2187 const char *location)
2189 NTSTATUS nt_status;
2190 struct ldapsam_privates *ldap_state;
2192 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
2193 return nt_status;
2196 (*pdb_method)->name = "ldapsam";
2198 (*pdb_method)->setsampwent = ldapsam_setsampwent;
2199 (*pdb_method)->endsampwent = ldapsam_endsampwent;
2200 (*pdb_method)->getsampwent = ldapsam_getsampwent;
2201 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
2202 (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
2203 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
2204 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
2205 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
2207 (*pdb_method)->getgrsid = ldapsam_getgrsid;
2208 (*pdb_method)->getgrgid = ldapsam_getgrgid;
2209 (*pdb_method)->getgrnam = ldapsam_getgrnam;
2210 (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
2211 (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
2212 (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
2213 (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
2215 /* TODO: Setup private data and free */
2217 ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(*ldap_state));
2218 if (!ldap_state) {
2219 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
2220 return NT_STATUS_NO_MEMORY;
2223 if (!NT_STATUS_IS_OK(nt_status =
2224 smbldap_init(pdb_context->mem_ctx, location,
2225 &ldap_state->smbldap_state)));
2227 ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, get_global_sam_name());
2228 if (!ldap_state->domain_name) {
2229 return NT_STATUS_NO_MEMORY;
2232 (*pdb_method)->private_data = ldap_state;
2234 (*pdb_method)->free_private_data = free_private_data;
2236 return NT_STATUS_OK;
2239 /**********************************************************************
2240 Initialise the 'compat' mode for pdb_ldap
2241 *********************************************************************/
2243 static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2245 NTSTATUS nt_status;
2246 struct ldapsam_privates *ldap_state;
2248 #ifdef WITH_LDAP_SAMCONFIG
2249 if (!location) {
2250 int ldap_port = lp_ldap_port();
2252 /* remap default port if not using SSL (ie clear or TLS) */
2253 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
2254 ldap_port = 389;
2257 location = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port);
2258 if (!location) {
2259 return NT_STATUS_NO_MEMORY;
2262 #endif
2264 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
2265 return nt_status;
2268 (*pdb_method)->name = "ldapsam_compat";
2270 ldap_state = (*pdb_method)->private_data;
2271 ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
2273 sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
2275 return NT_STATUS_OK;
2278 /**********************************************************************
2279 Initialise the normal mode for pdb_ldap
2280 *********************************************************************/
2282 static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2284 NTSTATUS nt_status;
2285 struct ldapsam_privates *ldap_state;
2286 uint32 alg_rid_base;
2287 pstring alg_rid_base_string;
2288 LDAPMessage *result = NULL;
2289 LDAPMessage *entry = NULL;
2290 DOM_SID ldap_domain_sid;
2291 DOM_SID secrets_domain_sid;
2292 pstring domain_sid_string;
2294 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
2295 return nt_status;
2298 (*pdb_method)->name = "ldapsam";
2300 ldap_state = (*pdb_method)->private_data;
2301 ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
2303 /* Try to setup the Domain Name, Domain SID, algorithmic rid base */
2305 nt_status = smbldap_search_domain_info(ldap_state->smbldap_state, &result,
2306 ldap_state->domain_name, True);
2308 if ( !NT_STATUS_IS_OK(nt_status) ) {
2309 DEBUG(2, ("WARNING: Could not get domain info, nor add one to the domain\n"));
2310 DEBUGADD(2, ("Continuing on regardless, will be unable to allocate new users/groups, "
2311 "and will risk BDCs having inconsistant SIDs\n"));
2312 sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
2313 return NT_STATUS_OK;
2316 /* Given that the above might fail, everything below this must be optional */
2318 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
2319 if (!entry) {
2320 DEBUG(0, ("Could not get domain info entry\n"));
2321 ldap_msgfree(result);
2322 return NT_STATUS_UNSUCCESSFUL;
2325 if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
2326 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
2327 domain_sid_string))
2329 BOOL found_sid;
2330 string_to_sid(&ldap_domain_sid, domain_sid_string);
2331 found_sid = secrets_fetch_domain_sid(ldap_state->domain_name, &secrets_domain_sid);
2332 if (!found_sid || !sid_equal(&secrets_domain_sid, &ldap_domain_sid)) {
2333 /* reset secrets.tdb sid */
2334 secrets_store_domain_sid(ldap_state->domain_name, &ldap_domain_sid);
2336 sid_copy(&ldap_state->domain_sid, &ldap_domain_sid);
2339 if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
2340 get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ALGORITHMIC_RID_BASE),
2341 alg_rid_base_string))
2343 alg_rid_base = (uint32)atol(alg_rid_base_string);
2344 if (alg_rid_base != algorithmic_rid_base()) {
2345 DEBUG(0, ("The value of 'algorithmic RID base' has changed since the LDAP\n"
2346 "database was initialised. Aborting. \n"));
2347 ldap_msgfree(result);
2348 return NT_STATUS_UNSUCCESSFUL;
2351 ldap_msgfree(result);
2353 return NT_STATUS_OK;
2356 NTSTATUS pdb_ldap_init(void)
2358 NTSTATUS nt_status;
2359 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam", pdb_init_ldapsam)))
2360 return nt_status;
2362 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat)))
2363 return nt_status;
2365 return NT_STATUS_OK;