Try to make this easier to debug - display the username that failed.
[kai/samba.git] / source3 / passdb / pdb_ldap.c
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
8    
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.
13    
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.
18    
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.
22    
23 */
24
25 #include "includes.h"
26
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_PASSDB
29
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
34 *  
35 *  Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
36 *
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)
40 *
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)
43 */
44
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
49 */
50
51 #include <lber.h>
52 #include <ldap.h>
53
54 #ifndef SAM_ACCOUNT
55 #define SAM_ACCOUNT struct sam_passwd
56 #endif
57
58 struct ldapsam_privates {
59
60         /* Former statics */
61         LDAP *ldap_struct;
62         LDAPMessage *result;
63         LDAPMessage *entry;
64         int index;
65         
66         /* retrive-once info */
67         const char *uri;
68         
69         BOOL permit_non_unix_accounts;
70         
71         uint32 low_nua_rid; 
72         uint32 high_nua_rid; 
73
74         char *bind_dn;
75         char *bind_secret;
76 };
77
78
79 static struct ldapsam_privates *static_ldap_state;
80
81 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state);
82
83 /*******************************************************************
84  find the ldap password
85 ******************************************************************/
86 static BOOL fetch_ldapsam_pw(char **dn, char** pw)
87 {
88         char *key = NULL;
89         size_t size;
90         
91         *dn = smb_xstrdup(lp_ldap_admin_dn());
92         
93         if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
94                 SAFE_FREE(*dn);
95                 DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
96         }
97         
98         *pw=secrets_fetch(key, &size);
99         if (!size) {
100                 /* Upgrade 2.2 style entry */
101                 char *p;
102                 char* old_style_key = strdup(*dn);
103                 char *data;
104                 fstring old_style_pw;
105                 
106                 if (!old_style_key) {
107                         DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
108                         return False;
109                 }
110
111                 for (p=old_style_key; *p; p++)
112                         if (*p == ',') *p = '/';
113         
114                 data=secrets_fetch(old_style_key, &size);
115                 if (!size && size < sizeof(old_style_pw)) {
116                         DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
117                         SAFE_FREE(old_style_key);
118                         SAFE_FREE(*dn);
119                         return False;
120                 }
121
122                 strncpy(old_style_pw, data, size);
123                 old_style_pw[size] = 0;
124
125                 SAFE_FREE(data);
126
127                 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
128                         DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
129                         SAFE_FREE(old_style_key);
130                         SAFE_FREE(*dn);
131                         return False;                   
132                 }
133                 if (!secrets_delete(old_style_key)) {
134                         DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
135                 }
136
137                 SAFE_FREE(old_style_key);
138
139                 *pw = smb_xstrdup(old_style_pw);                
140         }
141         
142         return True;
143 }
144
145 static const char *attr[] = {"uid", "pwdLastSet", "logonTime",
146                 "logoffTime", "kickoffTime", "cn",
147                 "pwdCanChange", "pwdMustChange",
148                 "displayName", "homeDrive",
149                 "smbHome", "scriptPath",
150                 "profilePath", "description",
151                 "userWorkstations", "rid",
152                 "primaryGroupID", "lmPassword",
153                 "ntPassword", "acctFlags",
154                 "domain", "description", NULL };
155
156 /*******************************************************************
157  open a connection to the ldap server.
158 ******************************************************************/
159 static BOOL ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct)
160 {
161
162         if (geteuid() != 0) {
163                 DEBUG(0, ("ldap_open_connection: cannot access LDAP when not root..\n"));
164                 return False;
165         }
166
167 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
168         DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
169         
170         if (ldap_initialize(ldap_struct, ldap_state->uri) != LDAP_SUCCESS) {
171                 DEBUG(0, ("ldap_initialize: %s\n", strerror(errno)));
172                 return (False);
173         }
174 #else 
175
176         /* Parse the string manually */
177
178         {
179                 int rc;
180                 int tls = LDAP_OPT_X_TLS_HARD;
181                 int port = 0;
182                 int version;
183                 fstring protocol;
184                 fstring host;
185                 const char *p = ldap_state->uri; 
186                 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
187                 
188                 /* skip leading "URL:" (if any) */
189                 if ( strncasecmp( p, "URL:", 4 ) == 0 ) {
190                         p += 4;
191                 }
192
193                 sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port);
194                 
195                 if (port == 0) {
196                         if (strequal(protocol, "ldap")) {
197                                 port = LDAP_PORT;
198                         } else if (strequal(protocol, "ldaps")) {
199                                 port = LDAPS_PORT;
200                         } else {
201                                 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
202                         }
203                 }
204
205                 if ((*ldap_struct = ldap_init(host, port)) == NULL)     {
206                         DEBUG(0, ("ldap_init failed !\n"));
207                         return False;
208                 }
209
210                 /* Connect to older servers using SSL and V2 rather than Start TLS */
211                 if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
212                 {
213                         if (version != LDAP_VERSION2)
214                         {
215                                 version = LDAP_VERSION2;
216                                 ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
217                         }
218                 }
219
220                 if (strequal(protocol, "ldaps")) { 
221                         if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
222                                 if (ldap_get_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, 
223                                                      &version) == LDAP_OPT_SUCCESS)
224                                 {
225                                         if (version < LDAP_VERSION3)
226                                         {
227                                                 version = LDAP_VERSION3;
228                                                 ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION,
229                                                                  &version);
230                                         }
231                                 }
232                                 if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
233                                 {
234                                         DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
235                                                  ldap_err2string(rc)));
236                                         return False;
237                                 }
238                                 DEBUG (2, ("StartTLS issued: using a TLS connection\n"));
239                         } else {
240                                 
241                                 if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
242                                 {
243                                         DEBUG(0, ("Failed to setup a TLS session\n"));
244                                 }
245                         }
246                 } else {
247                         /* 
248                          * No special needs to setup options prior to the LDAP
249                          * bind (which should be called next via ldap_connect_system()
250                          */
251                 }
252         }
253 #endif
254
255         DEBUG(2, ("ldap_open_connection: connection opened\n"));
256         return True;
257 }
258
259
260 /*******************************************************************
261  a rebind function for authenticated referrals
262  This version takes a void* that we can shove useful stuff in :-)
263 ******************************************************************/
264
265 static int rebindproc_with_state  (LDAP * ld, char **whop, char **credp, 
266                                    int *methodp, int freeit, void *arg)
267 {
268         struct ldapsam_privates *ldap_state = arg;
269         
270         /** @TODO Should we be doing something to check what servers we rebind to?
271             Could we get a referral to a machine that we don't want to give our
272             username and password to? */
273         
274         if (freeit) {
275                 SAFE_FREE(*whop);
276                 memset(*credp, '\0', strlen(*credp));
277                 SAFE_FREE(*credp);
278         } else {
279                 DEBUG(5,("ldap_connect_system: Rebinding as \"%s\"\n", 
280                           ldap_state->bind_dn));
281
282                 *whop = strdup(ldap_state->bind_dn);
283                 if (!*whop) {
284                         return LDAP_NO_MEMORY;
285                 }
286                 *credp = strdup(ldap_state->bind_secret);
287                 if (!*credp) {
288                         SAFE_FREE(*whop);
289                         return LDAP_NO_MEMORY;
290                 }
291                 *methodp = LDAP_AUTH_SIMPLE;
292         }
293         return 0;
294 }
295
296 /*******************************************************************
297  a rebind function for authenticated referrals
298  This version takes a void* that we can shove useful stuff in :-)
299  and actually does the connection.
300 ******************************************************************/
301
302 static int rebindproc_connect_with_state (LDAP *ldap_struct, 
303                                           LDAP_CONST char *url, 
304                                           ber_tag_t request,
305                                           ber_int_t msgid, void *arg)
306 {
307         struct ldapsam_privates *ldap_state = arg;
308         int rc;
309         DEBUG(5,("ldap_connect_system: Rebinding as \"%s\"\n", 
310                  ldap_state->bind_dn));
311         
312         /** @TODO Should we be doing something to check what servers we rebind to?
313             Could we get a referral to a machine that we don't want to give our
314             username and password to? */
315
316         rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
317         
318         return rc;
319 }
320
321 /*******************************************************************
322  Add a rebind function for authenticated referrals
323 ******************************************************************/
324
325 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
326                        int *method, int freeit )
327 {
328         return rebindproc_with_state(ldap_struct, whop, credp,
329                                    method, freeit, static_ldap_state);
330         
331 }
332
333 /*******************************************************************
334  a rebind function for authenticated referrals
335  this also does the connection, but no void*.
336 ******************************************************************/
337
338 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
339                                ber_int_t msgid)
340 {
341         return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid, 
342                                              static_ldap_state);
343 }
344
345
346 /*******************************************************************
347  connect to the ldap server under system privilege.
348 ******************************************************************/
349 static BOOL ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
350 {
351         int rc;
352         char *ldap_dn;
353         char *ldap_secret;
354
355         /* The rebind proc needs this *HACK*.  We are not multithreaded, so
356            this will work, but it's not nice. */
357         static_ldap_state = ldap_state;
358
359         /* get the password */
360         if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
361         {
362                 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
363                 return False;
364         }
365
366         ldap_state->bind_dn = ldap_dn;
367         ldap_state->bind_secret = ldap_secret;
368
369         /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite 
370            (OpenLDAP) doesnt' seem to support it */
371            
372         DEBUG(10,("ldap_connect_system: Binding to ldap server as \"%s\"\n",
373                 ldap_dn));
374
375 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
376 # if LDAP_SET_REBIND_PROC_ARGS == 2     
377         ldap_set_rebind_proc(ldap_struct, &rebindproc_connect); 
378 # endif
379 # if LDAP_SET_REBIND_PROC_ARGS == 3     
380         ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);  
381 # endif
382 #else
383 # if LDAP_SET_REBIND_PROC_ARGS == 2     
384         ldap_set_rebind_proc(ldap_struct, &rebindproc); 
385 # endif
386 # if LDAP_SET_REBIND_PROC_ARGS == 3     
387         ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);  
388 # endif
389 #endif
390         rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
391
392         if (rc != LDAP_SUCCESS)
393         {
394                 DEBUG(0, ("Bind failed: %s\n", ldap_err2string(rc)));
395                 return False;
396         }
397         
398         DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
399         return True;
400 }
401
402 /*******************************************************************
403  run the search by name.
404 ******************************************************************/
405 static int ldapsam_search_one_user (struct ldapsam_privates *ldap_state, LDAP * ldap_struct, const char *filter, LDAPMessage ** result)
406 {
407         int scope = LDAP_SCOPE_SUBTREE;
408         int rc;
409
410         DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter));
411
412         rc = ldap_search_s(ldap_struct, lp_ldap_suffix (), scope, filter, attr, 0, result);
413
414         if (rc != LDAP_SUCCESS) {
415                 DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s\n", 
416                         ldap_err2string (rc)));
417                 DEBUG(3,("ldapsam_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(), 
418                         filter));
419         }
420         
421         return rc;
422 }
423
424 /*******************************************************************
425  run the search by name.
426 ******************************************************************/
427 static int ldapsam_search_one_user_by_name (struct ldapsam_privates *ldap_state, LDAP * ldap_struct, const char *user,
428                              LDAPMessage ** result)
429 {
430         pstring filter;
431         
432         /*
433          * in the filter expression, replace %u with the real name
434          * so in ldap filter, %u MUST exist :-)
435          */
436         pstrcpy(filter, lp_ldap_filter());
437
438         /* 
439          * have to use this here because $ is filtered out
440            * in pstring_sub
441          */
442         all_string_sub(filter, "%u", user, sizeof(pstring));
443
444         return ldapsam_search_one_user(ldap_state, ldap_struct, filter, result);
445 }
446
447 /*******************************************************************
448  run the search by uid.
449 ******************************************************************/
450 static int ldapsam_search_one_user_by_uid(struct ldapsam_privates *ldap_state, 
451                                           LDAP * ldap_struct, int uid,
452                                           LDAPMessage ** result)
453 {
454         struct passwd *user;
455         pstring filter;
456
457         /* Get the username from the system and look that up in the LDAP */
458         
459         if ((user = getpwuid_alloc(uid)) == NULL) {
460                 DEBUG(3,("ldapsam_search_one_user_by_uid: Failed to locate uid [%d]\n", uid));
461                 return LDAP_NO_SUCH_OBJECT;
462         }
463         
464         pstrcpy(filter, lp_ldap_filter());
465         
466         all_string_sub(filter, "%u", user->pw_name, sizeof(pstring));
467
468         passwd_free(&user);
469
470         return ldapsam_search_one_user(ldap_state, ldap_struct, filter, result);
471 }
472
473 /*******************************************************************
474  run the search by rid.
475 ******************************************************************/
476 static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state, 
477                                            LDAP * ldap_struct, uint32 rid,
478                                            LDAPMessage ** result)
479 {
480         pstring filter;
481         int rc;
482
483         /* check if the user rid exsists, if not, try searching on the uid */
484         
485         snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
486         rc = ldapsam_search_one_user(ldap_state, ldap_struct, filter, result);
487         
488         if (rc != LDAP_SUCCESS)
489                 rc = ldapsam_search_one_user_by_uid(ldap_state, ldap_struct, 
490                                                     fallback_pdb_user_rid_to_uid(rid), 
491                                                     result);
492
493         return rc;
494 }
495
496 /*******************************************************************
497 search an attribute and return the first value found.
498 ******************************************************************/
499 static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
500                                   char *attribute, pstring value)
501 {
502         char **values;
503
504         if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
505                 value = NULL;
506                 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
507                 
508                 return False;
509         }
510         
511         pstrcpy(value, values[0]);
512         ldap_value_free(values);
513 #ifdef DEBUG_PASSWORDS
514         DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
515 #endif  
516         return True;
517 }
518
519 /************************************************************************
520 Routine to manage the LDAPMod structure array
521 manage memory used by the array, by each struct, and values
522
523 ************************************************************************/
524 static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
525 {
526         LDAPMod **mods;
527         int i;
528         int j;
529
530         mods = *modlist;
531
532         if (attribute == NULL || *attribute == '\0')
533                 return;
534
535         if (value == NULL || *value == '\0')
536                 return;
537
538         if (mods == NULL) 
539         {
540                 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
541                 if (mods == NULL)
542                 {
543                         DEBUG(0, ("make_a_mod: out of memory!\n"));
544                         return;
545                 }
546                 mods[0] = NULL;
547         }
548
549         for (i = 0; mods[i] != NULL; ++i) {
550                 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
551                         break;
552         }
553
554         if (mods[i] == NULL)
555         {
556                 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
557                 if (mods == NULL)
558                 {
559                         DEBUG(0, ("make_a_mod: out of memory!\n"));
560                         return;
561                 }
562                 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
563                 if (mods[i] == NULL)
564                 {
565                         DEBUG(0, ("make_a_mod: out of memory!\n"));
566                         return;
567                 }
568                 mods[i]->mod_op = modop;
569                 mods[i]->mod_values = NULL;
570                 mods[i]->mod_type = strdup(attribute);
571                 mods[i + 1] = NULL;
572         }
573
574         if (value != NULL)
575         {
576                 j = 0;
577                 if (mods[i]->mod_values != NULL) {
578                         for (; mods[i]->mod_values[j] != NULL; j++);
579                 }
580                 mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
581                                                (j + 2) * sizeof (char *));
582                                                
583                 if (mods[i]->mod_values == NULL) {
584                         DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
585                         return;
586                 }
587                 mods[i]->mod_values[j] = strdup(value);
588                 mods[i]->mod_values[j + 1] = NULL;
589         }
590         *modlist = mods;
591 }
592
593 /* New Interface is being implemented here */
594
595 /**********************************************************************
596 Initialize SAM_ACCOUNT from an LDAP query
597 (Based on init_sam_from_buffer in pdb_tdb.c)
598 *********************************************************************/
599 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, 
600                                 SAM_ACCOUNT * sampass,
601                                 LDAP * ldap_struct, LDAPMessage * entry)
602 {
603         time_t  logon_time,
604                         logoff_time,
605                         kickoff_time,
606                         pass_last_set_time, 
607                         pass_can_change_time, 
608                         pass_must_change_time;
609         pstring         username, 
610                         domain,
611                         nt_username,
612                         fullname,
613                         homedir,
614                         dir_drive,
615                         logon_script,
616                         profile_path,
617                         acct_desc,
618                         munged_dial,
619                         workstations;
620         struct passwd   *pw;
621         uint32          user_rid, 
622                         group_rid;
623         uint8           smblmpwd[16],
624                         smbntpwd[16];
625         uint16          acct_ctrl, 
626                         logon_divs;
627         uint32 hours_len;
628         uint8           hours[MAX_HOURS_LEN];
629         pstring temp;
630         uid_t           uid = -1;
631         gid_t           gid = getegid();
632
633
634         /*
635          * do a little initialization
636          */
637         username[0]     = '\0';
638         domain[0]       = '\0';
639         nt_username[0]  = '\0';
640         fullname[0]     = '\0';
641         homedir[0]      = '\0';
642         dir_drive[0]    = '\0';
643         logon_script[0] = '\0';
644         profile_path[0] = '\0';
645         acct_desc[0]    = '\0';
646         munged_dial[0]  = '\0';
647         workstations[0] = '\0';
648          
649
650         if (sampass == NULL || ldap_struct == NULL || entry == NULL) {
651                 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
652                 return False;
653         }
654
655         get_single_attribute(ldap_struct, entry, "uid", username);
656         DEBUG(2, ("Entry found for user: %s\n", username));
657
658         pstrcpy(nt_username, username);
659
660         pstrcpy(domain, lp_workgroup());
661
662         get_single_attribute(ldap_struct, entry, "rid", temp);
663         user_rid = (uint32)atol(temp);
664
665         pdb_set_user_sid_from_rid(sampass, user_rid);
666
667         if (!get_single_attribute(ldap_struct, entry, "primaryGroupID", temp)) {
668                 group_rid = 0;
669         } else {
670                 group_rid = (uint32)atol(temp);
671                 pdb_set_group_sid_from_rid(sampass, group_rid);
672         }
673
674         if ((ldap_state->permit_non_unix_accounts) 
675             && (user_rid >= ldap_state->low_nua_rid)
676             && (user_rid <= ldap_state->high_nua_rid)) {
677                 
678         } else {
679                 
680                 /* These values MAY be in LDAP, but they can also be retrieved through 
681                  *  sys_getpw*() which is how we're doing it 
682                  */
683         
684                 pw = getpwnam_alloc(username);
685                 if (pw == NULL) {
686                         DEBUG (2,("init_sam_from_ldap: User [%s] does not exist via system getpwnam!\n", username));
687                         return False;
688                 }
689                 uid = pw->pw_uid;
690                 gid = pw->pw_gid;
691
692                 pdb_set_unix_homedir(sampass, pw->pw_dir);
693
694                 passwd_free(&pw);
695
696                 pdb_set_uid(sampass, uid);
697                 pdb_set_gid(sampass, gid);
698
699                 if (group_rid == 0) {
700                         GROUP_MAP map;
701                         /* call the mapping code here */
702                         if(get_group_map_from_gid(gid, &map, MAPPING_WITHOUT_PRIV)) {
703                                 pdb_set_group_sid(sampass, &map.sid);
704                         } 
705                         else {
706                                 pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid));
707                         }
708                 }
709         }
710
711         if (!get_single_attribute(ldap_struct, entry, "pwdLastSet", temp)) {
712                 /* leave as default */
713         } else {
714                 pass_last_set_time = (time_t) atol(temp);
715                 pdb_set_pass_last_set_time(sampass, pass_last_set_time);
716         }
717
718         if (!get_single_attribute(ldap_struct, entry, "logonTime", temp)) {
719                 /* leave as default */
720         } else {
721                 logon_time = (time_t) atol(temp);
722                 pdb_set_logon_time(sampass, logon_time, True);
723         }
724
725         if (!get_single_attribute(ldap_struct, entry, "logoffTime", temp)) {
726                 /* leave as default */
727         } else {
728                 logoff_time = (time_t) atol(temp);
729                 pdb_set_logoff_time(sampass, logoff_time, True);
730         }
731
732         if (!get_single_attribute(ldap_struct, entry, "kickoffTime", temp)) {
733                 /* leave as default */
734         } else {
735                 kickoff_time = (time_t) atol(temp);
736                 pdb_set_kickoff_time(sampass, kickoff_time, True);
737         }
738
739         if (!get_single_attribute(ldap_struct, entry, "pwdCanChange", temp)) {
740                 /* leave as default */
741         } else {
742                 pass_can_change_time = (time_t) atol(temp);
743                 pdb_set_pass_can_change_time(sampass, pass_can_change_time, True);
744         }
745
746         if (!get_single_attribute(ldap_struct, entry, "pwdMustChange", temp)) {
747                 /* leave as default */
748         } else {
749                 pass_must_change_time = (time_t) atol(temp);
750                 pdb_set_pass_must_change_time(sampass, pass_must_change_time, True);
751         }
752
753         /* recommend that 'gecos' and 'displayName' should refer to the same
754          * attribute OID.  userFullName depreciated, only used by Samba
755          * primary rules of LDAP: don't make a new attribute when one is already defined
756          * that fits your needs; using cn then displayName rather than 'userFullName'
757          */
758
759         if (!get_single_attribute(ldap_struct, entry, "cn", fullname)) {
760                 if (!get_single_attribute(ldap_struct, entry, "displayName", fullname)) {
761                         /* leave as default */
762                 } else {
763                         pdb_set_fullname(sampass, fullname);
764                 }
765         } else {
766                 pdb_set_fullname(sampass, fullname);
767         }
768
769         if (!get_single_attribute(ldap_struct, entry, "homeDrive", dir_drive)) {
770                 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx, 
771                                                                   lp_logon_drive(),
772                                                                   username, domain, 
773                                                                   uid, gid),
774                                   False);
775         } else {
776                 pdb_set_dir_drive(sampass, dir_drive, True);
777         }
778
779         if (!get_single_attribute(ldap_struct, entry, "smbHome", homedir)) {
780                 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx, 
781                                                                   lp_logon_home(),
782                                                                   username, domain, 
783                                                                   uid, gid), 
784                                   False);
785         } else {
786                 pdb_set_homedir(sampass, homedir, True);
787         }
788
789         if (!get_single_attribute(ldap_struct, entry, "scriptPath", logon_script)) {
790                 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx, 
791                                                                      lp_logon_script(),
792                                                                      username, domain, 
793                                                                      uid, gid), 
794                                      False);
795         } else {
796                 pdb_set_logon_script(sampass, logon_script, True);
797         }
798
799         if (!get_single_attribute(ldap_struct, entry, "profilePath", profile_path)) {
800                 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx, 
801                                                                      lp_logon_path(),
802                                                                      username, domain, 
803                                                                      uid, gid), 
804                                      False);
805         } else {
806                 pdb_set_profile_path(sampass, profile_path, True);
807         }
808
809         if (!get_single_attribute(ldap_struct, entry, "description", acct_desc)) {
810                 /* leave as default */
811         } else {
812                 pdb_set_acct_desc(sampass, acct_desc);
813         }
814
815         if (!get_single_attribute(ldap_struct, entry, "userWorkstations", workstations)) {
816                 /* leave as default */;
817         } else {
818                 pdb_set_workstations(sampass, workstations);
819         }
820
821         /* FIXME: hours stuff should be cleaner */
822         
823         logon_divs = 168;
824         hours_len = 21;
825         memset(hours, 0xff, hours_len);
826
827         if (!get_single_attribute (ldap_struct, entry, "lmPassword", temp)) {
828                 /* leave as default */
829         } else {
830                 pdb_gethexpwd(temp, smblmpwd);
831                 memset((char *)temp, '\0', strlen(temp)+1);
832                 if (!pdb_set_lanman_passwd(sampass, smblmpwd))
833                         return False;
834                 ZERO_STRUCT(smblmpwd);
835         }
836
837         if (!get_single_attribute (ldap_struct, entry, "ntPassword", temp)) {
838                 /* leave as default */
839         } else {
840                 pdb_gethexpwd(temp, smbntpwd);
841                 memset((char *)temp, '\0', strlen(temp)+1);
842                 if (!pdb_set_nt_passwd(sampass, smbntpwd))
843                         return False;
844                 ZERO_STRUCT(smbntpwd);
845         }
846
847         if (!get_single_attribute (ldap_struct, entry, "acctFlags", temp)) {
848                 acct_ctrl |= ACB_NORMAL;
849         } else {
850                 acct_ctrl = pdb_decode_acct_ctrl(temp);
851
852                 if (acct_ctrl == 0)
853                         acct_ctrl |= ACB_NORMAL;
854
855                 pdb_set_acct_ctrl(sampass, acct_ctrl);
856         }
857
858         pdb_set_hours_len(sampass, hours_len);
859         pdb_set_logon_divs(sampass, logon_divs);
860
861         pdb_set_username(sampass, username);
862
863         pdb_set_domain(sampass, domain);
864         pdb_set_nt_username(sampass, nt_username);
865
866         pdb_set_munged_dial(sampass, munged_dial);
867         
868         /* pdb_set_unknown_3(sampass, unknown3); */
869         /* pdb_set_unknown_5(sampass, unknown5); */
870         /* pdb_set_unknown_6(sampass, unknown6); */
871
872         pdb_set_hours(sampass, hours);
873
874         return True;
875 }
876
877 /**********************************************************************
878 Initialize SAM_ACCOUNT from an LDAP query
879 (Based on init_buffer_from_sam in pdb_tdb.c)
880 *********************************************************************/
881 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, 
882                                 LDAPMod *** mods, int ldap_op, 
883                                 const SAM_ACCOUNT * sampass)
884 {
885         pstring temp;
886         uint32 rid;
887
888         if (mods == NULL || sampass == NULL) {
889                 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
890                 return False;
891         }
892
893         *mods = NULL;
894
895         /* 
896          * took out adding "objectclass: sambaAccount"
897          * do this on a per-mod basis
898          */
899
900         make_a_mod(mods, ldap_op, "uid", pdb_get_username(sampass));
901         DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
902
903         if ( pdb_get_user_rid(sampass) ) {
904                 rid = pdb_get_user_rid(sampass);
905         } else if (IS_SAM_SET(sampass, FLAG_SAM_UID)) {
906                 rid = fallback_pdb_uid_to_user_rid(pdb_get_uid(sampass));
907         } else if (ldap_state->permit_non_unix_accounts) {
908                 rid = ldapsam_get_next_available_nua_rid(ldap_state);
909                 if (rid == 0) {
910                         DEBUG(0, ("NO user RID specified on account %s, and findining next available NUA RID failed, cannot store!\n", pdb_get_username(sampass)));
911                         return False;
912                 }
913         } else {
914                 DEBUG(0, ("NO user RID specified on account %s, cannot store!\n", pdb_get_username(sampass)));
915                 return False;
916         }
917
918         slprintf(temp, sizeof(temp) - 1, "%i", rid);
919         make_a_mod(mods, ldap_op, "rid", temp);
920
921         if ( pdb_get_group_rid(sampass) ) {
922                 rid = pdb_get_group_rid(sampass);
923         } else if (IS_SAM_SET(sampass, FLAG_SAM_GID)) {
924                 rid = pdb_gid_to_group_rid(pdb_get_gid(sampass));
925         } else if (ldap_state->permit_non_unix_accounts) {
926                 rid = DOMAIN_GROUP_RID_USERS;
927         } else {
928                 DEBUG(0, ("NO group RID specified on account %s, cannot store!\n", pdb_get_username(sampass)));
929                 return False;
930         }
931
932         slprintf(temp, sizeof(temp) - 1, "%i", rid);
933         make_a_mod(mods, ldap_op, "primaryGroupID", temp);
934
935         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
936         make_a_mod(mods, ldap_op, "pwdLastSet", temp);
937
938         /* displayName, cn, and gecos should all be the same
939            *  most easily accomplished by giving them the same OID
940            *  gecos isn't set here b/c it should be handled by the 
941            *  add-user script
942          */
943
944         make_a_mod(mods, ldap_op, "displayName", pdb_get_fullname(sampass));
945         make_a_mod(mods, ldap_op, "cn", pdb_get_fullname(sampass));
946         make_a_mod(mods, ldap_op, "description", pdb_get_acct_desc(sampass));
947         make_a_mod(mods, ldap_op, "userWorkstations", pdb_get_workstations(sampass));
948
949         /*
950          * Only updates fields which have been set (not defaults from smb.conf)
951          */
952
953         if (IS_SAM_SET(sampass, FLAG_SAM_SMBHOME))
954                 make_a_mod(mods, ldap_op, "smbHome", pdb_get_homedir(sampass));
955                 
956         if (IS_SAM_SET(sampass, FLAG_SAM_DRIVE))
957                 make_a_mod(mods, ldap_op, "homeDrive", pdb_get_dir_drive(sampass));
958         
959         if (IS_SAM_SET(sampass, FLAG_SAM_LOGONSCRIPT))
960                 make_a_mod(mods, ldap_op, "scriptPath", pdb_get_logon_script(sampass));
961
962         if (IS_SAM_SET(sampass, FLAG_SAM_PROFILE))
963                 make_a_mod(mods, ldap_op, "profilePath", pdb_get_profile_path(sampass));
964
965         if (IS_SAM_SET(sampass, FLAG_SAM_LOGONTIME)) {
966                 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
967                 make_a_mod(mods, ldap_op, "logonTime", temp);
968         }
969
970         if (IS_SAM_SET(sampass, FLAG_SAM_LOGOFFTIME)) {
971                 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
972                 make_a_mod(mods, ldap_op, "logoffTime", temp);
973         }
974
975         if (IS_SAM_SET(sampass, FLAG_SAM_KICKOFFTIME)) {
976                 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass));
977                 make_a_mod(mods, ldap_op, "kickoffTime", temp);
978         }
979
980         if (IS_SAM_SET(sampass, FLAG_SAM_CANCHANGETIME)) {
981                 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
982                 make_a_mod(mods, ldap_op, "pwdCanChange", temp);
983         }
984
985         if (IS_SAM_SET(sampass, FLAG_SAM_MUSTCHANGETIME)) {
986                 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass));
987                 make_a_mod(mods, ldap_op, "pwdMustChange", temp);
988         }
989
990         /* FIXME: Hours stuff goes in LDAP  */
991         pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass), pdb_get_acct_ctrl(sampass));
992         make_a_mod (mods, ldap_op, "lmPassword", temp);
993         
994         pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass), pdb_get_acct_ctrl(sampass));
995         make_a_mod (mods, ldap_op, "ntPassword", temp);
996         
997         make_a_mod (mods, ldap_op, "acctFlags", pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
998                 NEW_PW_FORMAT_SPACE_PADDED_LEN));
999
1000         return True;
1001 }
1002
1003
1004 /**********************************************************************
1005 Connect to LDAP server and find the next available RID.
1006 *********************************************************************/
1007 static uint32 check_nua_rid_is_avail(struct ldapsam_privates *ldap_state, uint32 top_rid, LDAP *ldap_struct) 
1008 {
1009         LDAPMessage *result;
1010         uint32 final_rid = (top_rid & (~USER_RID_TYPE)) + RID_MULTIPLIER;
1011         if (top_rid == 0) {
1012                 return 0;
1013         }
1014         
1015         if (final_rid < ldap_state->low_nua_rid || final_rid > ldap_state->high_nua_rid) {
1016                 return 0;
1017         }
1018
1019         if (ldapsam_search_one_user_by_rid(ldap_state, ldap_struct, final_rid, &result) != LDAP_SUCCESS) {
1020                 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the confirmation search failed!\n", final_rid, final_rid));
1021                 final_rid = 0;
1022                 ldap_msgfree(result);
1023         }
1024
1025         if (ldap_count_entries(ldap_struct, result) != 0)
1026         {
1027                 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the RID is already in use!!\n", final_rid, final_rid));
1028                 final_rid = 0;
1029                 ldap_msgfree(result);
1030         }
1031
1032         DEBUG(5, ("NUA RID %d (0x%x), declared valid\n", final_rid, final_rid));
1033         return final_rid;
1034 }
1035
1036 /**********************************************************************
1037 Extract the RID from an LDAP entry
1038 *********************************************************************/
1039 static uint32 entry_to_user_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry, LDAP *ldap_struct) {
1040         uint32 rid;
1041         SAM_ACCOUNT *user = NULL;
1042         if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
1043                 return 0;
1044         }
1045
1046         if (init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) {
1047                 rid = pdb_get_user_rid(user);
1048         } else {
1049                 rid =0;
1050         }
1051         pdb_free_sam(&user);
1052         if (rid >= ldap_state->low_nua_rid && rid <= ldap_state->high_nua_rid) {
1053                 return rid;
1054         }
1055         return 0;
1056 }
1057
1058
1059 /**********************************************************************
1060 Connect to LDAP server and find the next available RID.
1061 *********************************************************************/
1062 static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state, LDAP *ldap_struct)
1063 {
1064         int rc;
1065         pstring filter;
1066         LDAPMessage *result;
1067         LDAPMessage *entry;
1068         char *final_filter = NULL;
1069         uint32 top_rid = 0;
1070         uint32 count;
1071         uint32 rid;
1072
1073         pstrcpy(filter, lp_ldap_filter());
1074         all_string_sub(filter, "%u", "*", sizeof(pstring));
1075
1076 #if 0
1077         asprintf(&final_filter, "(&(%s)(&(rid>=%d)(rid<=%d)))", filter, ldap_state->low_nua_rid, ldap_state->high_nua_rid);
1078 #else 
1079         final_filter = strdup(filter);
1080 #endif  
1081         DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter));
1082
1083         rc = ldap_search_s(ldap_struct, lp_ldap_suffix(),
1084                            LDAP_SCOPE_SUBTREE, final_filter, attr, 0,
1085                            &result);
1086
1087         if (rc != LDAP_SUCCESS)
1088         {
1089                 
1090                 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
1091                 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1092
1093                 free(final_filter);
1094                 ldap_msgfree(result);
1095                 result = NULL;
1096                 return 0;
1097         }
1098         
1099         count = ldap_count_entries(ldap_struct, result);
1100         DEBUG(2, ("search_top_nua_rid: %d entries in the base!\n", count));
1101         
1102         if (count == 0) {
1103                 DEBUG(3, ("LDAP search returned no records, assuming no non-unix-accounts present!: %s\n", ldap_err2string(rc)));
1104                 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1105                 free(final_filter);
1106                 ldap_msgfree(result);
1107                 result = NULL;
1108                 return ldap_state->low_nua_rid;
1109         }
1110         
1111         free(final_filter);
1112         entry = ldap_first_entry(ldap_struct,result);
1113
1114         top_rid = entry_to_user_rid(ldap_state, entry, ldap_struct);
1115
1116         while ((entry = ldap_next_entry(ldap_struct, entry))) {
1117
1118                 rid = entry_to_user_rid(ldap_state, entry, ldap_struct);
1119                 if (rid > top_rid) {
1120                         top_rid = rid;
1121                 }
1122         }
1123
1124         ldap_msgfree(result);
1125
1126         if (top_rid < ldap_state->low_nua_rid) 
1127                 top_rid = ldap_state->low_nua_rid;
1128
1129         return top_rid;
1130 }
1131
1132 /**********************************************************************
1133 Connect to LDAP server and find the next available RID.
1134 *********************************************************************/
1135 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state) {
1136         LDAP *ldap_struct;
1137         uint32 next_nua_rid;
1138         uint32 top_nua_rid;
1139
1140         if (!ldapsam_open_connection(ldap_state, &ldap_struct))
1141         {
1142                 return 0;
1143         }
1144         if (!ldapsam_connect_system(ldap_state, ldap_struct))
1145         {
1146                 ldap_unbind(ldap_struct);
1147                 return 0;
1148         }
1149         
1150         top_nua_rid = search_top_nua_rid(ldap_state, ldap_struct);
1151
1152         next_nua_rid = check_nua_rid_is_avail(ldap_state, 
1153                                               top_nua_rid, ldap_struct);
1154         
1155         ldap_unbind(ldap_struct);
1156         return next_nua_rid;
1157 }
1158
1159 /**********************************************************************
1160 Connect to LDAP server for password enumeration
1161 *********************************************************************/
1162 static BOOL ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
1163 {
1164         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1165         int rc;
1166         pstring filter;
1167
1168         if (!ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))
1169         {
1170                 return False;
1171         }
1172         if (!ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))
1173         {
1174                 ldap_unbind(ldap_state->ldap_struct);
1175                 return False;
1176         }
1177
1178         pstrcpy(filter, lp_ldap_filter());
1179         all_string_sub(filter, "%u", "*", sizeof(pstring));
1180
1181         rc = ldap_search_s(ldap_state->ldap_struct, lp_ldap_suffix(),
1182                            LDAP_SCOPE_SUBTREE, filter, attr, 0,
1183                            &ldap_state->result);
1184
1185         if (rc != LDAP_SUCCESS)
1186         {
1187                 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
1188                 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1189                 ldap_msgfree(ldap_state->result);
1190                 ldap_unbind(ldap_state->ldap_struct);
1191                 ldap_state->ldap_struct = NULL;
1192                 ldap_state->result = NULL;
1193                 return False;
1194         }
1195
1196         DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
1197                 ldap_count_entries(ldap_state->ldap_struct,
1198                 ldap_state->result)));
1199
1200         ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
1201                                  ldap_state->result);
1202         ldap_state->index = 0;
1203
1204         return True;
1205 }
1206
1207 /**********************************************************************
1208 End enumeration of the LDAP password list 
1209 *********************************************************************/
1210 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1211 {
1212         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1213         if (ldap_state->ldap_struct && ldap_state->result)
1214         {
1215                 ldap_msgfree(ldap_state->result);
1216                 ldap_unbind(ldap_state->ldap_struct);
1217                 ldap_state->ldap_struct = NULL;
1218                 ldap_state->result = NULL;
1219         }
1220 }
1221
1222 /**********************************************************************
1223 Get the next entry in the LDAP password database 
1224 *********************************************************************/
1225 static BOOL ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT * user)
1226 {
1227         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1228         BOOL ret = False;
1229
1230         /* The rebind proc needs this *HACK*.  We are not multithreaded, so
1231            this will work, but it's not nice. */
1232         static_ldap_state = ldap_state;
1233
1234         while (!ret) {
1235                 if (!ldap_state->entry)
1236                         return False;
1237                 
1238                 ldap_state->index++;
1239                 ret = init_sam_from_ldap(ldap_state, user, ldap_state->ldap_struct,
1240                                          ldap_state->entry);
1241                 
1242                 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
1243                                             ldap_state->entry);
1244                 
1245         }
1246
1247         return True;
1248 }
1249
1250 /**********************************************************************
1251 Get SAM_ACCOUNT entry from LDAP by username 
1252 *********************************************************************/
1253 static BOOL ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const char *sname)
1254 {
1255         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1256         LDAP *ldap_struct;
1257         LDAPMessage *result;
1258         LDAPMessage *entry;
1259
1260         if (!ldapsam_open_connection(ldap_state, &ldap_struct))
1261                 return False;
1262         if (!ldapsam_connect_system(ldap_state, ldap_struct))
1263         {
1264                 ldap_unbind(ldap_struct);
1265                 return False;
1266         }
1267         if (ldapsam_search_one_user_by_name(ldap_state, ldap_struct, sname, &result) != LDAP_SUCCESS)
1268         {
1269                 ldap_unbind(ldap_struct);
1270                 return False;
1271         }
1272         if (ldap_count_entries(ldap_struct, result) < 1)
1273         {
1274                 DEBUG(4,
1275                       ("We don't find this user [%s] count=%d\n", sname,
1276                        ldap_count_entries(ldap_struct, result)));
1277                 ldap_unbind(ldap_struct);
1278                 return False;
1279         }
1280         entry = ldap_first_entry(ldap_struct, result);
1281         if (entry)
1282         {
1283                 if (!init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) {
1284                         DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
1285                         ldap_msgfree(result);
1286                         ldap_unbind(ldap_struct);
1287                         return False;
1288                 }
1289                 ldap_msgfree(result);
1290                 ldap_unbind(ldap_struct);
1291                 return True;
1292         }
1293         else
1294         {
1295                 ldap_msgfree(result);
1296                 ldap_unbind(ldap_struct);
1297                 return False;
1298         }
1299 }
1300
1301 /**********************************************************************
1302 Get SAM_ACCOUNT entry from LDAP by rid 
1303 *********************************************************************/
1304 static BOOL ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, uint32 rid)
1305 {
1306         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1307         LDAP *ldap_struct;
1308         LDAPMessage *result;
1309         LDAPMessage *entry;
1310
1311         if (!ldapsam_open_connection(ldap_state, &ldap_struct))
1312                 return False;
1313
1314         if (!ldapsam_connect_system(ldap_state, ldap_struct))
1315         {
1316                 ldap_unbind(ldap_struct);
1317                 return False;
1318         }
1319         if (ldapsam_search_one_user_by_rid(ldap_state, ldap_struct, rid, &result) !=
1320             LDAP_SUCCESS)
1321         {
1322                 ldap_unbind(ldap_struct);
1323                 return False;
1324         }
1325
1326         if (ldap_count_entries(ldap_struct, result) < 1)
1327         {
1328                 DEBUG(4,
1329                       ("We don't find this rid [%i] count=%d\n", rid,
1330                        ldap_count_entries(ldap_struct, result)));
1331                 ldap_unbind(ldap_struct);
1332                 return False;
1333         }
1334
1335         entry = ldap_first_entry(ldap_struct, result);
1336         if (entry)
1337         {
1338                 if (!init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) {
1339                         DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
1340                         ldap_msgfree(result);
1341                         ldap_unbind(ldap_struct);
1342                         return False;
1343                 }
1344                 ldap_msgfree(result);
1345                 ldap_unbind(ldap_struct);
1346                 return True;
1347         }
1348         else
1349         {
1350                 ldap_msgfree(result);
1351                 ldap_unbind(ldap_struct);
1352                 return False;
1353         }
1354 }
1355
1356 static BOOL ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, DOM_SID *sid)
1357 {
1358         uint32 rid;
1359         if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
1360                 return False;
1361         return ldapsam_getsampwrid(my_methods, user, rid);
1362 }       
1363
1364 /**********************************************************************
1365 Delete entry from LDAP for username 
1366 *********************************************************************/
1367 static BOOL ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
1368 {
1369         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1370         const char *sname;
1371         int rc;
1372         char *dn;
1373         LDAP *ldap_struct;
1374         LDAPMessage *entry;
1375         LDAPMessage *result;
1376
1377         if (!sam_acct) {
1378                 DEBUG(0, ("sam_acct was NULL!\n"));
1379                 return False;
1380         }
1381
1382         sname = pdb_get_username(sam_acct);
1383
1384         if (!ldapsam_open_connection(ldap_state, &ldap_struct))
1385                 return False;
1386
1387         DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
1388         
1389         if (!ldapsam_connect_system(ldap_state, ldap_struct)) {
1390                 ldap_unbind (ldap_struct);
1391                 DEBUG(0, ("Failed to delete user %s from LDAP.\n", sname));
1392                 return False;
1393         }
1394
1395         rc = ldapsam_search_one_user_by_name(ldap_state, ldap_struct, sname, &result);
1396         if (ldap_count_entries (ldap_struct, result) == 0) {
1397                 DEBUG (0, ("User doesn't exit!\n"));
1398                 ldap_msgfree (result);
1399                 ldap_unbind (ldap_struct);
1400                 return False;
1401         }
1402
1403         entry = ldap_first_entry (ldap_struct, result);
1404         dn = ldap_get_dn (ldap_struct, entry);
1405
1406         rc = ldap_delete_s (ldap_struct, dn);
1407
1408         ldap_memfree (dn);
1409         if (rc != LDAP_SUCCESS) {
1410                 char *ld_error;
1411                 ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1412                 DEBUG (0,("failed to delete user with uid = %s with: %s\n\t%s\n",
1413                         sname, ldap_err2string (rc), ld_error));
1414                 free (ld_error);
1415                 ldap_unbind (ldap_struct);
1416                 return False;
1417         }
1418
1419         DEBUG (2,("successfully deleted uid = %s from the LDAP database\n", sname));
1420         ldap_unbind (ldap_struct);
1421         return True;
1422 }
1423
1424 /**********************************************************************
1425 Update SAM_ACCOUNT 
1426 *********************************************************************/
1427 static BOOL ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1428 {
1429         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1430         int rc;
1431         char *dn;
1432         LDAP *ldap_struct;
1433         LDAPMessage *result;
1434         LDAPMessage *entry;
1435         LDAPMod **mods;
1436
1437         if (!ldapsam_open_connection(ldap_state, &ldap_struct)) /* open a connection to the server */
1438                 return False;
1439
1440         if (!ldapsam_connect_system(ldap_state, ldap_struct))   /* connect as system account */
1441         {
1442                 ldap_unbind(ldap_struct);
1443                 return False;
1444         }
1445
1446         rc = ldapsam_search_one_user_by_name(ldap_state, ldap_struct,
1447                                              pdb_get_username(newpwd), &result);
1448
1449         if (ldap_count_entries(ldap_struct, result) == 0)
1450         {
1451                 DEBUG(0, ("No user to modify!\n"));
1452                 ldap_msgfree(result);
1453                 ldap_unbind(ldap_struct);
1454                 return False;
1455         }
1456
1457         if (!init_ldap_from_sam(ldap_state, &mods, LDAP_MOD_REPLACE, newpwd)) {
1458                 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1459                 ldap_msgfree(result);
1460                 ldap_unbind(ldap_struct);
1461                 return False;
1462         }
1463
1464         entry = ldap_first_entry(ldap_struct, result);
1465         dn = ldap_get_dn(ldap_struct, entry);
1466
1467         rc = ldap_modify_s(ldap_struct, dn, mods);
1468
1469         if (rc != LDAP_SUCCESS)
1470         {
1471                 char *ld_error;
1472                 ldap_get_option(ldap_struct, LDAP_OPT_ERROR_STRING,
1473                                 &ld_error);
1474                 DEBUG(0,
1475                       ("failed to modify user with uid = %s with: %s\n\t%s\n",
1476                        pdb_get_username(newpwd), ldap_err2string(rc),
1477                        ld_error));
1478                 free(ld_error);
1479                 ldap_unbind(ldap_struct);
1480                 return False;
1481         }
1482
1483         DEBUG(2,
1484               ("successfully modified uid = %s in the LDAP database\n",
1485                pdb_get_username(newpwd)));
1486         ldap_mods_free(mods, 1);
1487         ldap_unbind(ldap_struct);
1488         return True;
1489 }
1490
1491 /**********************************************************************
1492 Add SAM_ACCOUNT to LDAP 
1493 *********************************************************************/
1494 static BOOL ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1495 {
1496         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1497         int rc;
1498         pstring filter;
1499         LDAP *ldap_struct = NULL;
1500         LDAPMessage *result = NULL;
1501         pstring dn;
1502         LDAPMod **mods = NULL;
1503         int             ldap_op;
1504         uint32          num_result;
1505
1506         const char *username = pdb_get_username(newpwd);
1507         if (!username || !*username) {
1508                 DEBUG(0, ("Cannot add user without a username!\n"));
1509                 return False;
1510         }
1511
1512         if (!ldapsam_open_connection(ldap_state, &ldap_struct)) /* open a connection to the server */
1513         {
1514                 return False;
1515         }
1516
1517         if (!ldapsam_connect_system(ldap_state, ldap_struct))   /* connect as system account */
1518         {
1519                 ldap_unbind(ldap_struct);
1520                 return False;
1521         }
1522
1523         rc = ldapsam_search_one_user_by_name (ldap_state, ldap_struct, username, &result);
1524
1525         if (ldap_count_entries(ldap_struct, result) != 0)
1526         {
1527                 DEBUG(0,("User already in the base, with samba properties\n"));
1528                 ldap_msgfree(result);
1529                 ldap_unbind(ldap_struct);
1530                 return False;
1531         }
1532         ldap_msgfree(result);
1533
1534         slprintf (filter, sizeof (filter) - 1, "uid=%s", username);
1535         rc = ldapsam_search_one_user(ldap_state, ldap_struct, filter, &result);
1536         num_result = ldap_count_entries(ldap_struct, result);
1537         
1538         if (num_result > 1) {
1539                 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1540                 ldap_msgfree(result);
1541                 return False;
1542         }
1543         
1544         /* Check if we need to update an existing entry */
1545         if (num_result == 1) {
1546                 char *tmp;
1547                 LDAPMessage *entry;
1548                 
1549                 DEBUG(3,("User exists without samba properties: adding them\n"));
1550                 ldap_op = LDAP_MOD_REPLACE;
1551                 entry = ldap_first_entry (ldap_struct, result);
1552                 tmp = ldap_get_dn (ldap_struct, entry);
1553                 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1554                 ldap_memfree (tmp);
1555         }
1556         else {
1557                 /* Check if we need to add an entry */
1558                 DEBUG(3,("Adding new user\n"));
1559                 ldap_op = LDAP_MOD_ADD;
1560                 if (username[strlen(username)-1] == '$') {
1561                         slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
1562                 } else {
1563                         slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
1564                 }
1565         }
1566
1567         ldap_msgfree(result);
1568
1569         if (!init_ldap_from_sam(ldap_state, &mods, ldap_op, newpwd)) {
1570                 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
1571                 ldap_mods_free(mods, 1);
1572                 ldap_unbind(ldap_struct);
1573                 return False;           
1574         }
1575         make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
1576
1577         if (ldap_op == LDAP_MOD_REPLACE) {
1578                 rc = ldap_modify_s(ldap_struct, dn, mods);
1579         }
1580         else {
1581                 rc = ldap_add_s(ldap_struct, dn, mods);
1582         }
1583
1584         if (rc != LDAP_SUCCESS)
1585         {
1586                 char *ld_error;
1587
1588                 ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1589                 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s) with: %s\n\t%s\n",
1590                         pdb_get_username(newpwd), dn, ldap_err2string (rc), ld_error));
1591                 free(ld_error);
1592                 ldap_mods_free(mods, 1);
1593                 ldap_unbind(ldap_struct);
1594                 return False;
1595         }
1596         
1597         DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
1598         ldap_mods_free(mods, 1);
1599         ldap_unbind(ldap_struct);
1600         return True;
1601 }
1602
1603 static void free_private_data(void **vp) 
1604 {
1605         struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
1606
1607         if ((*ldap_state)->ldap_struct) {
1608                 ldap_unbind((*ldap_state)->ldap_struct);
1609         }
1610
1611         if ((*ldap_state)->bind_secret) {
1612                 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
1613         }
1614
1615         SAFE_FREE((*ldap_state)->bind_dn);
1616         SAFE_FREE((*ldap_state)->bind_secret);
1617
1618         *ldap_state = NULL;
1619
1620         /* No need to free any further, as it is talloc()ed */
1621 }
1622
1623 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1624 {
1625         NTSTATUS nt_status;
1626         struct ldapsam_privates *ldap_state;
1627
1628         if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
1629                 return nt_status;
1630         }
1631
1632         (*pdb_method)->name = "ldapsam";
1633
1634         (*pdb_method)->setsampwent = ldapsam_setsampwent;
1635         (*pdb_method)->endsampwent = ldapsam_endsampwent;
1636         (*pdb_method)->getsampwent = ldapsam_getsampwent;
1637         (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
1638         (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
1639         (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
1640         (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
1641         (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
1642
1643         /* TODO: Setup private data and free */
1644
1645         ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
1646
1647         if (!ldap_state) {
1648                 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
1649                 return NT_STATUS_NO_MEMORY;
1650         }
1651
1652         if (location) {
1653                 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
1654         } else {
1655                 ldap_state->uri = "ldap://localhost";
1656         }
1657
1658         (*pdb_method)->private_data = ldap_state;
1659
1660         (*pdb_method)->free_private_data = free_private_data;
1661
1662         return NT_STATUS_OK;
1663 }
1664
1665 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1666 {
1667         NTSTATUS nt_status;
1668         struct ldapsam_privates *ldap_state;
1669         uint32 low_nua_uid, high_nua_uid;
1670
1671         if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) {
1672                 return nt_status;
1673         }
1674
1675         (*pdb_method)->name = "ldapsam_nua";
1676
1677         ldap_state = (*pdb_method)->private_data;
1678         
1679         ldap_state->permit_non_unix_accounts = True;
1680
1681         if (!lp_non_unix_account_range(&low_nua_uid, &high_nua_uid)) {
1682                 DEBUG(0, ("cannot use ldapsam_nua without 'non unix account range' in smb.conf!\n"));
1683                 return NT_STATUS_UNSUCCESSFUL;
1684         }
1685
1686         ldap_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid);
1687
1688         ldap_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid);
1689
1690         return NT_STATUS_OK;
1691 }
1692
1693
1694 #else
1695
1696 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1697 {
1698         DEBUG(0, ("ldap not detected at configure time, ldapsam not availalble!\n"));
1699         return NT_STATUS_UNSUCCESSFUL;
1700 }
1701
1702 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
1703 {
1704         DEBUG(0, ("ldap not dectected at configure time, ldapsam_nua not available!\n"));
1705         return NT_STATUS_UNSUCCESSFUL;
1706 }
1707
1708
1709 #endif