fix parameters for ldap_set_rebind_proc() from OpenLDAP 2.1
[Samba.git] / source / passdb / pdb_ldap.c
blob45e71b7a149dba97ce49895ebc78eaa673f49988
1 /*
2 Unix SMB/CIFS implementation.
3 LDAP protocol helper functions for SAMBA
4 Copyright (C) Gerald Carter 2001
5 Copyright (C) Shahms King 2001
6 Copyright (C) Jean François Micouleau 1998
7 Copyright (C) Andrew Bartlett 2002
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "includes.h"
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_PASSDB
30 #ifdef HAVE_LDAP
31 /* TODO:
32 * persistent connections: if using NSS LDAP, many connections are made
33 * however, using only one within Samba would be nice
35 * Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
37 * Other LDAP based login attributes: accountExpires, etc.
38 * (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
39 * structures don't have fields for some of these attributes)
41 * SSL is done, but can't get the certificate based authentication to work
42 * against on my test platform (Linux 2.4, OpenLDAP 2.x)
45 /* NOTE: this will NOT work against an Active Directory server
46 * due to the fact that the two password fields cannot be retrieved
47 * from a server; recommend using security = domain in this situation
48 * and/or winbind
51 #include <lber.h>
52 #include <ldap.h>
54 #ifndef SAM_ACCOUNT
55 #define SAM_ACCOUNT struct sam_passwd
56 #endif
58 struct ldapsam_privates {
60 /* Former statics */
61 LDAP *ldap_struct;
62 LDAPMessage *result;
63 LDAPMessage *entry;
64 int index;
66 /* retrive-once info */
67 const char *uri;
69 BOOL permit_non_unix_accounts;
71 uint32 low_nua_rid;
72 uint32 high_nua_rid;
75 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state);
77 /*******************************************************************
78 find the ldap password
79 ******************************************************************/
80 static BOOL fetch_ldapsam_pw(char **dn, char** pw)
82 char *key = NULL;
83 size_t size;
85 *dn = smb_xstrdup(lp_ldap_admin_dn());
87 if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
88 SAFE_FREE(*dn);
89 DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
92 *pw=secrets_fetch(key, &size);
93 if (!size) {
94 /* Upgrade 2.2 style entry */
95 char *p;
96 char* old_style_key = strdup(*dn);
97 char *data;
98 fstring old_style_pw;
100 if (!old_style_key) {
101 DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
102 return False;
105 for (p=old_style_key; *p; p++)
106 if (*p == ',') *p = '/';
108 data=secrets_fetch(old_style_key, &size);
109 if (!size && size < sizeof(old_style_pw)) {
110 DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
111 SAFE_FREE(old_style_key);
112 SAFE_FREE(*dn);
113 return False;
116 strncpy(old_style_pw, data, size);
117 old_style_pw[size] = 0;
119 SAFE_FREE(data);
121 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
122 DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
123 SAFE_FREE(old_style_key);
124 SAFE_FREE(*dn);
125 return False;
127 if (!secrets_delete(old_style_key)) {
128 DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
131 SAFE_FREE(old_style_key);
133 *pw = smb_xstrdup(old_style_pw);
136 return True;
139 static const char *attr[] = {"uid", "pwdLastSet", "logonTime",
140 "logoffTime", "kickoffTime", "cn",
141 "pwdCanChange", "pwdMustChange",
142 "displayName", "homeDrive",
143 "smbHome", "scriptPath",
144 "profilePath", "description",
145 "userWorkstations", "rid",
146 "primaryGroupID", "lmPassword",
147 "ntPassword", "acctFlags",
148 "domain", "description", NULL };
150 /*******************************************************************
151 open a connection to the ldap server.
152 ******************************************************************/
153 static BOOL ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct)
156 if (geteuid() != 0) {
157 DEBUG(0, ("ldap_open_connection: cannot access LDAP when not root..\n"));
158 return False;
161 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
162 DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
164 if (ldap_initialize(ldap_struct, ldap_state->uri) != LDAP_SUCCESS) {
165 DEBUG(0, ("ldap_initialize: %s\n", strerror(errno)));
166 return (False);
168 #else
170 /* Parse the string manually */
173 int rc;
174 int tls = LDAP_OPT_X_TLS_HARD;
175 int port = 0;
176 int version;
177 fstring protocol;
178 fstring host;
179 const char *p = ldap_state->uri;
180 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
182 /* skip leading "URL:" (if any) */
183 if ( strncasecmp( p, "URL:", 4 ) == 0 ) {
184 p += 4;
187 sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port);
189 if (port == 0) {
190 if (strequal(protocol, "ldap")) {
191 port = LDAP_PORT;
192 } else if (strequal(protocol, "ldaps")) {
193 port = LDAPS_PORT;
194 } else {
195 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
199 if ((*ldap_struct = ldap_init(host, port)) == NULL) {
200 DEBUG(0, ("ldap_init failed !\n"));
201 return False;
204 /* Connect to older servers using SSL and V2 rather than Start TLS */
205 if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
207 if (version != LDAP_VERSION2)
209 version = LDAP_VERSION2;
210 ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
214 if (strequal(protocol, "ldaps")) {
215 if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
216 if (ldap_get_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION,
217 &version) == LDAP_OPT_SUCCESS)
219 if (version < LDAP_VERSION3)
221 version = LDAP_VERSION3;
222 ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION,
223 &version);
226 if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
228 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
229 ldap_err2string(rc)));
230 return False;
232 DEBUG (2, ("StartTLS issued: using a TLS connection\n"));
233 } else {
235 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
237 DEBUG(0, ("Failed to setup a TLS session\n"));
240 } else {
242 * No special needs to setup options prior to the LDAP
243 * bind (which should be called next via ldap_connect_system()
247 #endif
249 DEBUG(2, ("ldap_open_connection: connection opened\n"));
250 return True;
254 /*******************************************************************
255 Add a rebind function for authenticated referrals
256 ******************************************************************/
258 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
259 int *method, int freeit )
261 int rc;
262 char *ldap_dn;
263 char *ldap_secret;
265 /** @TODO Should we be doing something to check what servers we rebind to?
266 Could we get a referral to a machine that we don't want to give our
267 username and password to? */
269 if (freeit != 0)
272 if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
274 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
275 return LDAP_OPERATIONS_ERROR; /* No idea what to return */
278 DEBUG(5,("ldap_connect_system: Rebinding as \"%s\"\n",
279 ldap_dn));
281 rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
283 SAFE_FREE(ldap_dn);
284 SAFE_FREE(ldap_secret);
286 return rc;
288 return 0;
291 /*******************************************************************
292 connect to the ldap server under system privilege.
293 ******************************************************************/
294 static BOOL ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
296 int rc;
297 char *ldap_dn;
298 char *ldap_secret;
300 /* get the password */
301 if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
303 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
304 return False;
307 /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
308 (OpenLDAP) doesnt' seem to support it */
310 DEBUG(10,("ldap_connect_system: Binding to ldap server as \"%s\"\n",
311 ldap_dn));
313 #if LDAP_SET_REBIND_PROC_ARGS == 3
314 ldap_set_rebind_proc(ldap_struct, (LDAP_REBIND_PROC *)(&rebindproc), NULL);
315 #elif LDAP_SET_REBIND_PROC_ARGS == 2
316 ldap_set_rebind_proc(ldap_struct, (LDAP_REBIND_PROC *)(&rebindproc));
317 #endif
320 rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
322 SAFE_FREE(ldap_dn);
323 SAFE_FREE(ldap_secret);
325 if (rc != LDAP_SUCCESS)
327 DEBUG(0, ("Bind failed: %s\n", ldap_err2string(rc)));
328 return False;
331 DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
332 return True;
335 /*******************************************************************
336 run the search by name.
337 ******************************************************************/
338 static int ldapsam_search_one_user (struct ldapsam_privates *ldap_state, LDAP * ldap_struct, const char *filter, LDAPMessage ** result)
340 int scope = LDAP_SCOPE_SUBTREE;
341 int rc;
343 DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter));
345 rc = ldap_search_s(ldap_struct, lp_ldap_suffix (), scope, filter, attr, 0, result);
347 if (rc != LDAP_SUCCESS) {
348 DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s\n",
349 ldap_err2string (rc)));
350 DEBUG(3,("ldapsam_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(),
351 filter));
354 return rc;
357 /*******************************************************************
358 run the search by name.
359 ******************************************************************/
360 static int ldapsam_search_one_user_by_name (struct ldapsam_privates *ldap_state, LDAP * ldap_struct, const char *user,
361 LDAPMessage ** result)
363 pstring filter;
366 * in the filter expression, replace %u with the real name
367 * so in ldap filter, %u MUST exist :-)
369 pstrcpy(filter, lp_ldap_filter());
372 * have to use this here because $ is filtered out
373 * in pstring_sub
375 all_string_sub(filter, "%u", user, sizeof(pstring));
377 return ldapsam_search_one_user(ldap_state, ldap_struct, filter, result);
380 /*******************************************************************
381 run the search by uid.
382 ******************************************************************/
383 static int ldapsam_search_one_user_by_uid(struct ldapsam_privates *ldap_state,
384 LDAP * ldap_struct, int uid,
385 LDAPMessage ** result)
387 struct passwd *user;
388 pstring filter;
390 /* Get the username from the system and look that up in the LDAP */
392 if ((user = getpwuid_alloc(uid)) == NULL) {
393 DEBUG(3,("ldapsam_search_one_user_by_uid: Failed to locate uid [%d]\n", uid));
394 return LDAP_NO_SUCH_OBJECT;
397 pstrcpy(filter, lp_ldap_filter());
399 all_string_sub(filter, "%u", user->pw_name, sizeof(pstring));
401 passwd_free(&user);
403 return ldapsam_search_one_user(ldap_state, ldap_struct, filter, result);
406 /*******************************************************************
407 run the search by rid.
408 ******************************************************************/
409 static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state,
410 LDAP * ldap_struct, uint32 rid,
411 LDAPMessage ** result)
413 pstring filter;
414 int rc;
416 /* check if the user rid exsists, if not, try searching on the uid */
418 snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
419 rc = ldapsam_search_one_user(ldap_state, ldap_struct, filter, result);
421 if (rc != LDAP_SUCCESS)
422 rc = ldapsam_search_one_user_by_uid(ldap_state, ldap_struct,
423 fallback_pdb_user_rid_to_uid(rid),
424 result);
426 return rc;
429 /*******************************************************************
430 search an attribute and return the first value found.
431 ******************************************************************/
432 static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
433 char *attribute, pstring value)
435 char **values;
437 if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
438 value = NULL;
439 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
441 return False;
444 pstrcpy(value, values[0]);
445 ldap_value_free(values);
446 #ifdef DEBUG_PASSWORDS
447 DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
448 #endif
449 return True;
452 /************************************************************************
453 Routine to manage the LDAPMod structure array
454 manage memory used by the array, by each struct, and values
456 ************************************************************************/
457 static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
459 LDAPMod **mods;
460 int i;
461 int j;
463 mods = *modlist;
465 if (attribute == NULL || *attribute == '\0')
466 return;
468 if (value == NULL || *value == '\0')
469 return;
471 if (mods == NULL)
473 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
474 if (mods == NULL)
476 DEBUG(0, ("make_a_mod: out of memory!\n"));
477 return;
479 mods[0] = NULL;
482 for (i = 0; mods[i] != NULL; ++i) {
483 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
484 break;
487 if (mods[i] == NULL)
489 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
490 if (mods == NULL)
492 DEBUG(0, ("make_a_mod: out of memory!\n"));
493 return;
495 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
496 if (mods[i] == NULL)
498 DEBUG(0, ("make_a_mod: out of memory!\n"));
499 return;
501 mods[i]->mod_op = modop;
502 mods[i]->mod_values = NULL;
503 mods[i]->mod_type = strdup(attribute);
504 mods[i + 1] = NULL;
507 if (value != NULL)
509 j = 0;
510 if (mods[i]->mod_values != NULL) {
511 for (; mods[i]->mod_values[j] != NULL; j++);
513 mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
514 (j + 2) * sizeof (char *));
516 if (mods[i]->mod_values == NULL) {
517 DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
518 return;
520 mods[i]->mod_values[j] = strdup(value);
521 mods[i]->mod_values[j + 1] = NULL;
523 *modlist = mods;
526 /* New Interface is being implemented here */
528 /**********************************************************************
529 Initialize SAM_ACCOUNT from an LDAP query
530 (Based on init_sam_from_buffer in pdb_tdb.c)
531 *********************************************************************/
532 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
533 SAM_ACCOUNT * sampass,
534 LDAP * ldap_struct, LDAPMessage * entry)
536 time_t logon_time,
537 logoff_time,
538 kickoff_time,
539 pass_last_set_time,
540 pass_can_change_time,
541 pass_must_change_time;
542 pstring username,
543 domain,
544 nt_username,
545 fullname,
546 homedir,
547 dir_drive,
548 logon_script,
549 profile_path,
550 acct_desc,
551 munged_dial,
552 workstations;
553 struct passwd *pw;
554 uint32 user_rid,
555 group_rid;
556 uint8 smblmpwd[16],
557 smbntpwd[16];
558 uint16 acct_ctrl,
559 logon_divs;
560 uint32 hours_len;
561 uint8 hours[MAX_HOURS_LEN];
562 pstring temp;
563 uid_t uid = -1;
564 gid_t gid = getegid();
568 * do a little initialization
570 username[0] = '\0';
571 domain[0] = '\0';
572 nt_username[0] = '\0';
573 fullname[0] = '\0';
574 homedir[0] = '\0';
575 dir_drive[0] = '\0';
576 logon_script[0] = '\0';
577 profile_path[0] = '\0';
578 acct_desc[0] = '\0';
579 munged_dial[0] = '\0';
580 workstations[0] = '\0';
583 if (sampass == NULL || ldap_struct == NULL || entry == NULL) {
584 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
585 return False;
588 get_single_attribute(ldap_struct, entry, "uid", username);
589 DEBUG(2, ("Entry found for user: %s\n", username));
591 pstrcpy(nt_username, username);
593 pstrcpy(domain, lp_workgroup());
595 get_single_attribute(ldap_struct, entry, "rid", temp);
596 user_rid = (uint32)atol(temp);
598 pdb_set_user_sid_from_rid(sampass, user_rid);
600 if (!get_single_attribute(ldap_struct, entry, "primaryGroupID", temp)) {
601 group_rid = 0;
602 } else {
603 group_rid = (uint32)atol(temp);
604 pdb_set_group_sid_from_rid(sampass, group_rid);
607 if ((ldap_state->permit_non_unix_accounts)
608 && (user_rid >= ldap_state->low_nua_rid)
609 && (user_rid <= ldap_state->high_nua_rid)) {
611 } else {
613 /* These values MAY be in LDAP, but they can also be retrieved through
614 * sys_getpw*() which is how we're doing it
617 pw = getpwnam_alloc(username);
618 if (pw == NULL) {
619 DEBUG (2,("init_sam_from_ldap: User [%s] does not exist via system getpwnam!\n", username));
620 return False;
622 uid = pw->pw_uid;
623 gid = pw->pw_gid;
625 pdb_set_unix_homedir(sampass, pw->pw_dir);
627 passwd_free(&pw);
629 pdb_set_uid(sampass, uid);
630 pdb_set_gid(sampass, gid);
632 if (group_rid == 0) {
633 GROUP_MAP map;
634 /* call the mapping code here */
635 if(get_group_map_from_gid(gid, &map, MAPPING_WITHOUT_PRIV)) {
636 pdb_set_group_sid(sampass, &map.sid);
638 else {
639 pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid));
644 if (!get_single_attribute(ldap_struct, entry, "pwdLastSet", temp)) {
645 /* leave as default */
646 } else {
647 pass_last_set_time = (time_t) atol(temp);
648 pdb_set_pass_last_set_time(sampass, pass_last_set_time);
651 if (!get_single_attribute(ldap_struct, entry, "logonTime", temp)) {
652 /* leave as default */
653 } else {
654 logon_time = (time_t) atol(temp);
655 pdb_set_logon_time(sampass, logon_time, True);
658 if (!get_single_attribute(ldap_struct, entry, "logoffTime", temp)) {
659 /* leave as default */
660 } else {
661 logoff_time = (time_t) atol(temp);
662 pdb_set_logoff_time(sampass, logoff_time, True);
665 if (!get_single_attribute(ldap_struct, entry, "kickoffTime", temp)) {
666 /* leave as default */
667 } else {
668 kickoff_time = (time_t) atol(temp);
669 pdb_set_kickoff_time(sampass, kickoff_time, True);
672 if (!get_single_attribute(ldap_struct, entry, "pwdCanChange", temp)) {
673 /* leave as default */
674 } else {
675 pass_can_change_time = (time_t) atol(temp);
676 pdb_set_pass_can_change_time(sampass, pass_can_change_time, True);
679 if (!get_single_attribute(ldap_struct, entry, "pwdMustChange", temp)) {
680 /* leave as default */
681 } else {
682 pass_must_change_time = (time_t) atol(temp);
683 pdb_set_pass_must_change_time(sampass, pass_must_change_time, True);
686 /* recommend that 'gecos' and 'displayName' should refer to the same
687 * attribute OID. userFullName depreciated, only used by Samba
688 * primary rules of LDAP: don't make a new attribute when one is already defined
689 * that fits your needs; using cn then displayName rather than 'userFullName'
692 if (!get_single_attribute(ldap_struct, entry, "cn", fullname)) {
693 if (!get_single_attribute(ldap_struct, entry, "displayName", fullname)) {
694 /* leave as default */
695 } else {
696 pdb_set_fullname(sampass, fullname);
698 } else {
699 pdb_set_fullname(sampass, fullname);
702 if (!get_single_attribute(ldap_struct, entry, "homeDrive", dir_drive)) {
703 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx,
704 lp_logon_drive(),
705 username, domain,
706 uid, gid),
707 False);
708 } else {
709 pdb_set_dir_drive(sampass, dir_drive, True);
712 if (!get_single_attribute(ldap_struct, entry, "smbHome", homedir)) {
713 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx,
714 lp_logon_home(),
715 username, domain,
716 uid, gid),
717 False);
718 } else {
719 pdb_set_homedir(sampass, homedir, True);
722 if (!get_single_attribute(ldap_struct, entry, "scriptPath", logon_script)) {
723 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx,
724 lp_logon_script(),
725 username, domain,
726 uid, gid),
727 False);
728 } else {
729 pdb_set_logon_script(sampass, logon_script, True);
732 if (!get_single_attribute(ldap_struct, entry, "profilePath", profile_path)) {
733 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx,
734 lp_logon_path(),
735 username, domain,
736 uid, gid),
737 False);
738 } else {
739 pdb_set_profile_path(sampass, profile_path, True);
742 if (!get_single_attribute(ldap_struct, entry, "description", acct_desc)) {
743 /* leave as default */
744 } else {
745 pdb_set_acct_desc(sampass, acct_desc);
748 if (!get_single_attribute(ldap_struct, entry, "userWorkstations", workstations)) {
749 /* leave as default */;
750 } else {
751 pdb_set_workstations(sampass, workstations);
754 /* FIXME: hours stuff should be cleaner */
756 logon_divs = 168;
757 hours_len = 21;
758 memset(hours, 0xff, hours_len);
760 if (!get_single_attribute (ldap_struct, entry, "lmPassword", temp)) {
761 /* leave as default */
762 } else {
763 pdb_gethexpwd(temp, smblmpwd);
764 memset((char *)temp, '\0', sizeof(temp));
765 if (!pdb_set_lanman_passwd(sampass, smblmpwd))
766 return False;
769 if (!get_single_attribute (ldap_struct, entry, "ntPassword", temp)) {
770 /* leave as default */
771 } else {
772 pdb_gethexpwd(temp, smbntpwd);
773 memset((char *)temp, '\0', sizeof(temp));
774 if (!pdb_set_nt_passwd(sampass, smbntpwd))
775 return False;
778 if (!get_single_attribute (ldap_struct, entry, "acctFlags", temp)) {
779 acct_ctrl |= ACB_NORMAL;
780 } else {
781 acct_ctrl = pdb_decode_acct_ctrl(temp);
783 if (acct_ctrl == 0)
784 acct_ctrl |= ACB_NORMAL;
786 pdb_set_acct_ctrl(sampass, acct_ctrl);
789 pdb_set_hours_len(sampass, hours_len);
790 pdb_set_logon_divs(sampass, logon_divs);
792 pdb_set_username(sampass, username);
794 pdb_set_domain(sampass, domain);
795 pdb_set_nt_username(sampass, nt_username);
797 pdb_set_munged_dial(sampass, munged_dial);
799 /* pdb_set_unknown_3(sampass, unknown3); */
800 /* pdb_set_unknown_5(sampass, unknown5); */
801 /* pdb_set_unknown_6(sampass, unknown6); */
803 pdb_set_hours(sampass, hours);
805 return True;
808 /**********************************************************************
809 Initialize SAM_ACCOUNT from an LDAP query
810 (Based on init_buffer_from_sam in pdb_tdb.c)
811 *********************************************************************/
812 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
813 LDAPMod *** mods, int ldap_op,
814 const SAM_ACCOUNT * sampass)
816 pstring temp;
817 uint32 rid;
819 if (mods == NULL || sampass == NULL) {
820 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
821 return False;
824 *mods = NULL;
827 * took out adding "objectclass: sambaAccount"
828 * do this on a per-mod basis
831 make_a_mod(mods, ldap_op, "uid", pdb_get_username(sampass));
832 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
834 if ( pdb_get_user_rid(sampass) ) {
835 rid = pdb_get_user_rid(sampass);
836 } else if (IS_SAM_SET(sampass, FLAG_SAM_UID)) {
837 rid = fallback_pdb_uid_to_user_rid(pdb_get_uid(sampass));
838 } else if (ldap_state->permit_non_unix_accounts) {
839 rid = ldapsam_get_next_available_nua_rid(ldap_state);
840 if (rid == 0) {
841 DEBUG(0, ("NO user RID specified on account %s, and findining next available NUA RID failed, cannot store!\n", pdb_get_username(sampass)));
842 return False;
844 } else {
845 DEBUG(0, ("NO user RID specified on account %s, cannot store!\n", pdb_get_username(sampass)));
846 return False;
849 slprintf(temp, sizeof(temp) - 1, "%i", rid);
850 make_a_mod(mods, ldap_op, "rid", temp);
852 if ( pdb_get_group_rid(sampass) ) {
853 rid = pdb_get_group_rid(sampass);
854 } else if (IS_SAM_SET(sampass, FLAG_SAM_GID)) {
855 rid = pdb_gid_to_group_rid(pdb_get_gid(sampass));
856 } else if (ldap_state->permit_non_unix_accounts) {
857 rid = DOMAIN_GROUP_RID_USERS;
858 } else {
859 DEBUG(0, ("NO group RID specified on account %s, cannot store!\n", pdb_get_username(sampass)));
860 return False;
863 slprintf(temp, sizeof(temp) - 1, "%i", rid);
864 make_a_mod(mods, ldap_op, "primaryGroupID", temp);
866 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
867 make_a_mod(mods, ldap_op, "pwdLastSet", temp);
869 /* displayName, cn, and gecos should all be the same
870 * most easily accomplished by giving them the same OID
871 * gecos isn't set here b/c it should be handled by the
872 * add-user script
875 make_a_mod(mods, ldap_op, "displayName", pdb_get_fullname(sampass));
876 make_a_mod(mods, ldap_op, "cn", pdb_get_fullname(sampass));
877 make_a_mod(mods, ldap_op, "description", pdb_get_acct_desc(sampass));
878 make_a_mod(mods, ldap_op, "userWorkstations", pdb_get_workstations(sampass));
881 * Only updates fields which have been set (not defaults from smb.conf)
884 if (IS_SAM_SET(sampass, FLAG_SAM_SMBHOME))
885 make_a_mod(mods, ldap_op, "smbHome", pdb_get_homedir(sampass));
887 if (IS_SAM_SET(sampass, FLAG_SAM_DRIVE))
888 make_a_mod(mods, ldap_op, "homeDrive", pdb_get_dir_drive(sampass));
890 if (IS_SAM_SET(sampass, FLAG_SAM_LOGONSCRIPT))
891 make_a_mod(mods, ldap_op, "scriptPath", pdb_get_logon_script(sampass));
893 if (IS_SAM_SET(sampass, FLAG_SAM_PROFILE))
894 make_a_mod(mods, ldap_op, "profilePath", pdb_get_profile_path(sampass));
896 if (IS_SAM_SET(sampass, FLAG_SAM_LOGONTIME)) {
897 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
898 make_a_mod(mods, ldap_op, "logonTime", temp);
901 if (IS_SAM_SET(sampass, FLAG_SAM_LOGOFFTIME)) {
902 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
903 make_a_mod(mods, ldap_op, "logoffTime", temp);
906 if (IS_SAM_SET(sampass, FLAG_SAM_KICKOFFTIME)) {
907 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass));
908 make_a_mod(mods, ldap_op, "kickoffTime", temp);
911 if (IS_SAM_SET(sampass, FLAG_SAM_CANCHANGETIME)) {
912 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
913 make_a_mod(mods, ldap_op, "pwdCanChange", temp);
916 if (IS_SAM_SET(sampass, FLAG_SAM_MUSTCHANGETIME)) {
917 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass));
918 make_a_mod(mods, ldap_op, "pwdMustChange", temp);
921 /* FIXME: Hours stuff goes in LDAP */
922 pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass), pdb_get_acct_ctrl(sampass));
923 make_a_mod (mods, ldap_op, "lmPassword", temp);
925 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass), pdb_get_acct_ctrl(sampass));
926 make_a_mod (mods, ldap_op, "ntPassword", temp);
928 make_a_mod (mods, ldap_op, "acctFlags", pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
929 NEW_PW_FORMAT_SPACE_PADDED_LEN));
931 return True;
935 /**********************************************************************
936 Connect to LDAP server and find the next available RID.
937 *********************************************************************/
938 static uint32 check_nua_rid_is_avail(struct ldapsam_privates *ldap_state, uint32 top_rid, LDAP *ldap_struct)
940 LDAPMessage *result;
941 uint32 final_rid = (top_rid & (~USER_RID_TYPE)) + RID_MULTIPLIER;
942 if (top_rid == 0) {
943 return 0;
946 if (final_rid < ldap_state->low_nua_rid || final_rid > ldap_state->high_nua_rid) {
947 return 0;
950 if (ldapsam_search_one_user_by_rid(ldap_state, ldap_struct, final_rid, &result) != LDAP_SUCCESS) {
951 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the confirmation search failed!\n", final_rid, final_rid));
952 final_rid = 0;
953 ldap_msgfree(result);
956 if (ldap_count_entries(ldap_struct, result) != 0)
958 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the RID is already in use!!\n", final_rid, final_rid));
959 final_rid = 0;
960 ldap_msgfree(result);
963 DEBUG(5, ("NUA RID %d (0x%x), declared valid\n", final_rid, final_rid));
964 return final_rid;
967 /**********************************************************************
968 Extract the RID from an LDAP entry
969 *********************************************************************/
970 static uint32 entry_to_user_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry, LDAP *ldap_struct) {
971 uint32 rid;
972 SAM_ACCOUNT *user = NULL;
973 if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
974 return 0;
977 if (init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) {
978 rid = pdb_get_user_rid(user);
979 } else {
980 rid =0;
982 pdb_free_sam(&user);
983 if (rid >= ldap_state->low_nua_rid && rid <= ldap_state->high_nua_rid) {
984 return rid;
986 return 0;
990 /**********************************************************************
991 Connect to LDAP server and find the next available RID.
992 *********************************************************************/
993 static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state, LDAP *ldap_struct)
995 int rc;
996 pstring filter;
997 LDAPMessage *result;
998 LDAPMessage *entry;
999 char *final_filter = NULL;
1000 uint32 top_rid = 0;
1001 uint32 count;
1002 uint32 rid;
1004 pstrcpy(filter, lp_ldap_filter());
1005 all_string_sub(filter, "%u", "*", sizeof(pstring));
1007 #if 0
1008 asprintf(&final_filter, "(&(%s)(&(rid>=%d)(rid<=%d)))", filter, ldap_state->low_nua_rid, ldap_state->high_nua_rid);
1009 #else
1010 final_filter = strdup(filter);
1011 #endif
1012 DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter));
1014 rc = ldap_search_s(ldap_struct, lp_ldap_suffix(),
1015 LDAP_SCOPE_SUBTREE, final_filter, attr, 0,
1016 &result);
1018 if (rc != LDAP_SUCCESS)
1021 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
1022 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1024 free(final_filter);
1025 ldap_msgfree(result);
1026 result = NULL;
1027 return 0;
1030 count = ldap_count_entries(ldap_struct, result);
1031 DEBUG(2, ("search_top_nua_rid: %d entries in the base!\n", count));
1033 if (count == 0) {
1034 DEBUG(3, ("LDAP search returned no records, assuming no non-unix-accounts present!: %s\n", ldap_err2string(rc)));
1035 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1036 free(final_filter);
1037 ldap_msgfree(result);
1038 result = NULL;
1039 return ldap_state->low_nua_rid;
1042 free(final_filter);
1043 entry = ldap_first_entry(ldap_struct,result);
1045 top_rid = entry_to_user_rid(ldap_state, entry, ldap_struct);
1047 while ((entry = ldap_next_entry(ldap_struct, entry))) {
1049 rid = entry_to_user_rid(ldap_state, entry, ldap_struct);
1050 if (rid > top_rid) {
1051 top_rid = rid;
1055 ldap_msgfree(result);
1057 if (top_rid < ldap_state->low_nua_rid)
1058 top_rid = ldap_state->low_nua_rid;
1060 return top_rid;
1063 /**********************************************************************
1064 Connect to LDAP server and find the next available RID.
1065 *********************************************************************/
1066 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state) {
1067 LDAP *ldap_struct;
1068 uint32 next_nua_rid;
1069 uint32 top_nua_rid;
1071 if (!ldapsam_open_connection(ldap_state, &ldap_struct))
1073 return 0;
1075 if (!ldapsam_connect_system(ldap_state, ldap_struct))
1077 ldap_unbind(ldap_struct);
1078 return 0;
1081 top_nua_rid = search_top_nua_rid(ldap_state, ldap_struct);
1083 next_nua_rid = check_nua_rid_is_avail(ldap_state,
1084 top_nua_rid, ldap_struct);
1086 ldap_unbind(ldap_struct);
1087 return next_nua_rid;
1090 /**********************************************************************
1091 Connect to LDAP server for password enumeration
1092 *********************************************************************/
1093 static BOOL ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
1095 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1096 int rc;
1097 pstring filter;
1099 if (!ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))
1101 return False;
1103 if (!ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))
1105 ldap_unbind(ldap_state->ldap_struct);
1106 return False;
1109 pstrcpy(filter, lp_ldap_filter());
1110 all_string_sub(filter, "%u", "*", sizeof(pstring));
1112 rc = ldap_search_s(ldap_state->ldap_struct, lp_ldap_suffix(),
1113 LDAP_SCOPE_SUBTREE, filter, attr, 0,
1114 &ldap_state->result);
1116 if (rc != LDAP_SUCCESS)
1118 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
1119 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1120 ldap_msgfree(ldap_state->result);
1121 ldap_unbind(ldap_state->ldap_struct);
1122 ldap_state->ldap_struct = NULL;
1123 ldap_state->result = NULL;
1124 return False;
1127 DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
1128 ldap_count_entries(ldap_state->ldap_struct,
1129 ldap_state->result)));
1131 ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
1132 ldap_state->result);
1133 ldap_state->index = 0;
1135 return True;
1138 /**********************************************************************
1139 End enumeration of the LDAP password list
1140 *********************************************************************/
1141 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1143 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1144 if (ldap_state->ldap_struct && ldap_state->result)
1146 ldap_msgfree(ldap_state->result);
1147 ldap_unbind(ldap_state->ldap_struct);
1148 ldap_state->ldap_struct = NULL;
1149 ldap_state->result = NULL;
1153 /**********************************************************************
1154 Get the next entry in the LDAP password database
1155 *********************************************************************/
1156 static BOOL ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT * user)
1158 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1159 BOOL ret = False;
1161 while (!ret) {
1162 if (!ldap_state->entry)
1163 return False;
1165 ldap_state->index++;
1166 ret = init_sam_from_ldap(ldap_state, user, ldap_state->ldap_struct,
1167 ldap_state->entry);
1169 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
1170 ldap_state->entry);
1174 return True;
1177 /**********************************************************************
1178 Get SAM_ACCOUNT entry from LDAP by username
1179 *********************************************************************/
1180 static BOOL ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const char *sname)
1182 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1183 LDAP *ldap_struct;
1184 LDAPMessage *result;
1185 LDAPMessage *entry;
1187 if (!ldapsam_open_connection(ldap_state, &ldap_struct))
1188 return False;
1189 if (!ldapsam_connect_system(ldap_state, ldap_struct))
1191 ldap_unbind(ldap_struct);
1192 return False;
1194 if (ldapsam_search_one_user_by_name(ldap_state, ldap_struct, sname, &result) != LDAP_SUCCESS)
1196 ldap_unbind(ldap_struct);
1197 return False;
1199 if (ldap_count_entries(ldap_struct, result) < 1)
1201 DEBUG(4,
1202 ("We don't find this user [%s] count=%d\n", sname,
1203 ldap_count_entries(ldap_struct, result)));
1204 ldap_unbind(ldap_struct);
1205 return False;
1207 entry = ldap_first_entry(ldap_struct, result);
1208 if (entry)
1210 if (!init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) {
1211 DEBUG(0,("ldapsam_getsampwnam: init_sam_from_ldap failed!\n"));
1212 ldap_msgfree(result);
1213 ldap_unbind(ldap_struct);
1214 return False;
1216 ldap_msgfree(result);
1217 ldap_unbind(ldap_struct);
1218 return True;
1220 else
1222 ldap_msgfree(result);
1223 ldap_unbind(ldap_struct);
1224 return False;
1228 /**********************************************************************
1229 Get SAM_ACCOUNT entry from LDAP by rid
1230 *********************************************************************/
1231 static BOOL ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, uint32 rid)
1233 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1234 LDAP *ldap_struct;
1235 LDAPMessage *result;
1236 LDAPMessage *entry;
1238 if (!ldapsam_open_connection(ldap_state, &ldap_struct))
1239 return False;
1241 if (!ldapsam_connect_system(ldap_state, ldap_struct))
1243 ldap_unbind(ldap_struct);
1244 return False;
1246 if (ldapsam_search_one_user_by_rid(ldap_state, ldap_struct, rid, &result) !=
1247 LDAP_SUCCESS)
1249 ldap_unbind(ldap_struct);
1250 return False;
1253 if (ldap_count_entries(ldap_struct, result) < 1)
1255 DEBUG(0,
1256 ("We don't find this rid [%i] count=%d\n", rid,
1257 ldap_count_entries(ldap_struct, result)));
1258 ldap_unbind(ldap_struct);
1259 return False;
1262 entry = ldap_first_entry(ldap_struct, result);
1263 if (entry)
1265 if (!init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) {
1266 DEBUG(0,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
1267 ldap_msgfree(result);
1268 ldap_unbind(ldap_struct);
1269 return False;
1271 ldap_msgfree(result);
1272 ldap_unbind(ldap_struct);
1273 return True;
1275 else
1277 ldap_msgfree(result);
1278 ldap_unbind(ldap_struct);
1279 return False;
1283 static BOOL ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, DOM_SID *sid)
1285 uint32 rid;
1286 if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
1287 return False;
1288 return ldapsam_getsampwrid(my_methods, user, rid);
1291 /**********************************************************************
1292 Delete entry from LDAP for username
1293 *********************************************************************/
1294 static BOOL ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
1296 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1297 const char *sname;
1298 int rc;
1299 char *dn;
1300 LDAP *ldap_struct;
1301 LDAPMessage *entry;
1302 LDAPMessage *result;
1304 if (!sam_acct) {
1305 DEBUG(0, ("sam_acct was NULL!\n"));
1306 return False;
1309 sname = pdb_get_username(sam_acct);
1311 if (!ldapsam_open_connection(ldap_state, &ldap_struct))
1312 return False;
1314 DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
1316 if (!ldapsam_connect_system(ldap_state, ldap_struct)) {
1317 ldap_unbind (ldap_struct);
1318 DEBUG(0, ("Failed to delete user %s from LDAP.\n", sname));
1319 return False;
1322 rc = ldapsam_search_one_user_by_name(ldap_state, ldap_struct, sname, &result);
1323 if (ldap_count_entries (ldap_struct, result) == 0) {
1324 DEBUG (0, ("User doesn't exit!\n"));
1325 ldap_msgfree (result);
1326 ldap_unbind (ldap_struct);
1327 return False;
1330 entry = ldap_first_entry (ldap_struct, result);
1331 dn = ldap_get_dn (ldap_struct, entry);
1333 rc = ldap_delete_s (ldap_struct, dn);
1335 ldap_memfree (dn);
1336 if (rc != LDAP_SUCCESS) {
1337 char *ld_error;
1338 ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1339 DEBUG (0,("failed to delete user with uid = %s with: %s\n\t%s\n",
1340 sname, ldap_err2string (rc), ld_error));
1341 free (ld_error);
1342 ldap_unbind (ldap_struct);
1343 return False;
1346 DEBUG (2,("successfully deleted uid = %s from the LDAP database\n", sname));
1347 ldap_unbind (ldap_struct);
1348 return True;
1351 /**********************************************************************
1352 Update SAM_ACCOUNT
1353 *********************************************************************/
1354 static BOOL ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1356 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1357 int rc;
1358 char *dn;
1359 LDAP *ldap_struct;
1360 LDAPMessage *result;
1361 LDAPMessage *entry;
1362 LDAPMod **mods;
1364 if (!ldapsam_open_connection(ldap_state, &ldap_struct)) /* open a connection to the server */
1365 return False;
1367 if (!ldapsam_connect_system(ldap_state, ldap_struct)) /* connect as system account */
1369 ldap_unbind(ldap_struct);
1370 return False;
1373 rc = ldapsam_search_one_user_by_name(ldap_state, ldap_struct,
1374 pdb_get_username(newpwd), &result);
1376 if (ldap_count_entries(ldap_struct, result) == 0)
1378 DEBUG(0, ("No user to modify!\n"));
1379 ldap_msgfree(result);
1380 ldap_unbind(ldap_struct);
1381 return False;
1384 if (!init_ldap_from_sam(ldap_state, &mods, LDAP_MOD_REPLACE, newpwd)) {
1385 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1386 ldap_msgfree(result);
1387 ldap_unbind(ldap_struct);
1388 return False;
1391 entry = ldap_first_entry(ldap_struct, result);
1392 dn = ldap_get_dn(ldap_struct, entry);
1394 rc = ldap_modify_s(ldap_struct, dn, mods);
1396 if (rc != LDAP_SUCCESS)
1398 char *ld_error;
1399 ldap_get_option(ldap_struct, LDAP_OPT_ERROR_STRING,
1400 &ld_error);
1401 DEBUG(0,
1402 ("failed to modify user with uid = %s with: %s\n\t%s\n",
1403 pdb_get_username(newpwd), ldap_err2string(rc),
1404 ld_error));
1405 free(ld_error);
1406 ldap_unbind(ldap_struct);
1407 return False;
1410 DEBUG(2,
1411 ("successfully modified uid = %s in the LDAP database\n",
1412 pdb_get_username(newpwd)));
1413 ldap_mods_free(mods, 1);
1414 ldap_unbind(ldap_struct);
1415 return True;
1418 /**********************************************************************
1419 Add SAM_ACCOUNT to LDAP
1420 *********************************************************************/
1421 static BOOL ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1423 struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1424 int rc;
1425 pstring filter;
1426 LDAP *ldap_struct = NULL;
1427 LDAPMessage *result = NULL;
1428 pstring dn;
1429 LDAPMod **mods = NULL;
1430 int ldap_op;
1431 uint32 num_result;
1433 const char *username = pdb_get_username(newpwd);
1434 if (!username || !*username) {
1435 DEBUG(0, ("Cannot add user without a username!\n"));
1436 return False;
1439 if (!ldapsam_open_connection(ldap_state, &ldap_struct)) /* open a connection to the server */
1441 return False;
1444 if (!ldapsam_connect_system(ldap_state, ldap_struct)) /* connect as system account */
1446 ldap_unbind(ldap_struct);
1447 return False;
1450 rc = ldapsam_search_one_user_by_name (ldap_state, ldap_struct, username, &result);
1452 if (ldap_count_entries(ldap_struct, result) != 0)
1454 DEBUG(0,("User already in the base, with samba properties\n"));
1455 ldap_msgfree(result);
1456 ldap_unbind(ldap_struct);
1457 return False;
1459 ldap_msgfree(result);
1461 slprintf (filter, sizeof (filter) - 1, "uid=%s", username);
1462 rc = ldapsam_search_one_user(ldap_state, ldap_struct, filter, &result);
1463 num_result = ldap_count_entries(ldap_struct, result);
1465 if (num_result > 1) {
1466 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1467 ldap_msgfree(result);
1468 return False;
1471 /* Check if we need to update an existing entry */
1472 if (num_result == 1) {
1473 char *tmp;
1474 LDAPMessage *entry;
1476 DEBUG(3,("User exists without samba properties: adding them\n"));
1477 ldap_op = LDAP_MOD_REPLACE;
1478 entry = ldap_first_entry (ldap_struct, result);
1479 tmp = ldap_get_dn (ldap_struct, entry);
1480 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1481 ldap_memfree (tmp);
1483 else {
1484 /* Check if we need to add an entry */
1485 DEBUG(3,("Adding new user\n"));
1486 ldap_op = LDAP_MOD_ADD;
1487 if (username[strlen(username)-1] == '$') {
1488 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
1489 } else {
1490 slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
1494 ldap_msgfree(result);
1496 if (!init_ldap_from_sam(ldap_state, &mods, ldap_op, newpwd)) {
1497 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
1498 ldap_mods_free(mods, 1);
1499 ldap_unbind(ldap_struct);
1500 return False;
1502 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
1504 if (ldap_op == LDAP_MOD_REPLACE) {
1505 rc = ldap_modify_s(ldap_struct, dn, mods);
1507 else {
1508 rc = ldap_add_s(ldap_struct, dn, mods);
1511 if (rc != LDAP_SUCCESS)
1513 char *ld_error;
1515 ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1516 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s) with: %s\n\t%s\n",
1517 pdb_get_username(newpwd), dn, ldap_err2string (rc), ld_error));
1518 free(ld_error);
1519 ldap_mods_free(mods, 1);
1520 ldap_unbind(ldap_struct);
1521 return False;
1524 DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
1525 ldap_mods_free(mods, 1);
1526 ldap_unbind(ldap_struct);
1527 return True;
1530 static void free_private_data(void **vp)
1532 struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
1534 if ((*ldap_state)->ldap_struct) {
1535 ldap_unbind((*ldap_state)->ldap_struct);
1538 *ldap_state = NULL;
1540 /* No need to free any further, as it is talloc()ed */
1543 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1545 NTSTATUS nt_status;
1546 struct ldapsam_privates *ldap_state;
1548 if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
1549 return nt_status;
1552 (*pdb_method)->name = "ldapsam";
1554 (*pdb_method)->setsampwent = ldapsam_setsampwent;
1555 (*pdb_method)->endsampwent = ldapsam_endsampwent;
1556 (*pdb_method)->getsampwent = ldapsam_getsampwent;
1557 (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
1558 (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
1559 (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
1560 (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
1561 (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
1563 /* TODO: Setup private data and free */
1565 ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
1567 if (!ldap_state) {
1568 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
1569 return NT_STATUS_NO_MEMORY;
1572 if (location) {
1573 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
1574 } else {
1575 ldap_state->uri = "ldap://localhost";
1578 (*pdb_method)->private_data = ldap_state;
1580 (*pdb_method)->free_private_data = free_private_data;
1582 return NT_STATUS_OK;
1585 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1587 NTSTATUS nt_status;
1588 struct ldapsam_privates *ldap_state;
1589 uint32 low_nua_uid, high_nua_uid;
1591 if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) {
1592 return nt_status;
1595 (*pdb_method)->name = "ldapsam_nua";
1597 ldap_state = (*pdb_method)->private_data;
1599 ldap_state->permit_non_unix_accounts = True;
1601 if (!lp_non_unix_account_range(&low_nua_uid, &high_nua_uid)) {
1602 DEBUG(0, ("cannot use ldapsam_nua without 'non unix account range' in smb.conf!\n"));
1603 return NT_STATUS_UNSUCCESSFUL;
1606 ldap_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid);
1608 ldap_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid);
1610 return NT_STATUS_OK;
1614 #else
1616 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1618 DEBUG(0, ("ldap not detected at configure time, ldapsam not availalble!\n"));
1619 return NT_STATUS_UNSUCCESSFUL;
1622 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1624 DEBUG(0, ("ldap not dectected at configure time, ldapsam_nua not available!\n"));
1625 return NT_STATUS_UNSUCCESSFUL;
1629 #endif