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