Use True, not TRUE and False, not FALSE
[kai/samba.git] / source3 / 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 /* 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         time_t last_ping;
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 #define LDAPSAM_DONT_PING_TIME 10       /* ping only all 10 seconds */
80
81 static struct ldapsam_privates *static_ldap_state;
82
83 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state);
84
85 /*******************************************************************
86  find the ldap password
87 ******************************************************************/
88 static BOOL fetch_ldapsam_pw(char **dn, char** pw)
89 {
90         char *key = NULL;
91         size_t size;
92         
93         *dn = smb_xstrdup(lp_ldap_admin_dn());
94         
95         if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
96                 SAFE_FREE(*dn);
97                 DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
98         }
99         
100         *pw=secrets_fetch(key, &size);
101         if (!size) {
102                 /* Upgrade 2.2 style entry */
103                 char *p;
104                 char* old_style_key = strdup(*dn);
105                 char *data;
106                 fstring old_style_pw;
107                 
108                 if (!old_style_key) {
109                         DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
110                         return False;
111                 }
112
113                 for (p=old_style_key; *p; p++)
114                         if (*p == ',') *p = '/';
115         
116                 data=secrets_fetch(old_style_key, &size);
117                 if (!size && size < sizeof(old_style_pw)) {
118                         DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
119                         SAFE_FREE(old_style_key);
120                         SAFE_FREE(*dn);
121                         return False;
122                 }
123
124                 strncpy(old_style_pw, data, size);
125                 old_style_pw[size] = 0;
126
127                 SAFE_FREE(data);
128
129                 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
130                         DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
131                         SAFE_FREE(old_style_key);
132                         SAFE_FREE(*dn);
133                         return False;                   
134                 }
135                 if (!secrets_delete(old_style_key)) {
136                         DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
137                 }
138
139                 SAFE_FREE(old_style_key);
140
141                 *pw = smb_xstrdup(old_style_pw);                
142         }
143         
144         return True;
145 }
146
147 static const char *attr[] = {"uid", "pwdLastSet", "logonTime",
148                              "logoffTime", "kickoffTime", "cn",
149                              "pwdCanChange", "pwdMustChange",
150                              "displayName", "homeDrive",
151                              "smbHome", "scriptPath",
152                              "profilePath", "description",
153                              "userWorkstations", "rid",
154                              "primaryGroupID", "lmPassword",
155                              "ntPassword", "acctFlags",
156                              "domain", "objectClass", 
157                              "uidNumber", "gidNumber", 
158                              "homeDirectory", NULL };
159
160 /*******************************************************************
161  open a connection to the ldap server.
162 ******************************************************************/
163 static int ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct)
164 {
165         int rc = LDAP_SUCCESS;
166         int version;
167         BOOL ldap_v3 = False;
168
169 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
170         DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
171         
172         if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) {
173                 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
174                 return rc;
175         }
176         
177 #else 
178
179         /* Parse the string manually */
180
181         {
182                 int port = 0;
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 LDAP_OPERATIONS_ERROR;
208                 }
209                 
210                 if (strequal(protocol, "ldaps")) {
211 #ifdef LDAP_OPT_X_TLS
212                         int tls = LDAP_OPT_X_TLS_HARD;
213                         if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
214                         {
215                                 DEBUG(0, ("Failed to setup a TLS session\n"));
216                         }
217                         
218                         DEBUG(3,("LDAPS option set...!\n"));
219 #else
220                         DEBUG(0,("ldapsam_open_connection: Secure connection not supported by LDAP client libraries!\n"));
221                         return LDAP_OPERATIONS_ERROR;
222 #endif
223                 }
224         }
225 #endif
226
227         if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
228         {
229                 if (version != LDAP_VERSION3)
230                 {
231                         version = LDAP_VERSION3;
232                         if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
233                                 ldap_v3 = True;
234                         }
235                 } else {
236                         ldap_v3 = True;
237                 }
238         }
239
240         if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
241 #ifdef LDAP_OPT_X_TLS
242                 if (ldap_v3) {
243                         if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
244                         {
245                                 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
246                                          ldap_err2string(rc)));
247                                 return rc;
248                         }
249                         DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
250                 } else {
251                         
252                         DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
253                         return LDAP_OPERATIONS_ERROR;
254                 }
255 #else
256                 DEBUG(0,("ldapsam_open_connection: StartTLS not supported by LDAP client libraries!\n"));
257                 return LDAP_OPERATIONS_ERROR;
258 #endif
259         }
260
261         DEBUG(2, ("ldapsam_open_connection: connection opened\n"));
262         return rc;
263 }
264
265
266 /*******************************************************************
267  a rebind function for authenticated referrals
268  This version takes a void* that we can shove useful stuff in :-)
269 ******************************************************************/
270 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
271 #else
272 static int rebindproc_with_state  (LDAP * ld, char **whop, char **credp, 
273                                    int *methodp, int freeit, void *arg)
274 {
275         struct ldapsam_privates *ldap_state = arg;
276         
277         /** @TODO Should we be doing something to check what servers we rebind to?
278             Could we get a referral to a machine that we don't want to give our
279             username and password to? */
280         
281         if (freeit) {
282                 SAFE_FREE(*whop);
283                 memset(*credp, '\0', strlen(*credp));
284                 SAFE_FREE(*credp);
285         } else {
286                 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n", 
287                           ldap_state->bind_dn));
288
289                 *whop = strdup(ldap_state->bind_dn);
290                 if (!*whop) {
291                         return LDAP_NO_MEMORY;
292                 }
293                 *credp = strdup(ldap_state->bind_secret);
294                 if (!*credp) {
295                         SAFE_FREE(*whop);
296                         return LDAP_NO_MEMORY;
297                 }
298                 *methodp = LDAP_AUTH_SIMPLE;
299         }
300         return 0;
301 }
302 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
303
304 /*******************************************************************
305  a rebind function for authenticated referrals
306  This version takes a void* that we can shove useful stuff in :-)
307  and actually does the connection.
308 ******************************************************************/
309 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
310 static int rebindproc_connect_with_state (LDAP *ldap_struct, 
311                                           LDAP_CONST char *url, 
312                                           ber_tag_t request,
313                                           ber_int_t msgid, void *arg)
314 {
315         struct ldapsam_privates *ldap_state = arg;
316         int rc;
317         DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n", 
318                  ldap_state->bind_dn));
319         
320         /** @TODO Should we be doing something to check what servers we rebind to?
321             Could we get a referral to a machine that we don't want to give our
322             username and password to? */
323
324         rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
325         
326         return rc;
327 }
328 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
329
330 /*******************************************************************
331  Add a rebind function for authenticated referrals
332 ******************************************************************/
333 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
334 #else
335 # if LDAP_SET_REBIND_PROC_ARGS == 2
336 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
337                        int *method, int freeit )
338 {
339         return rebindproc_with_state(ldap_struct, whop, credp,
340                                    method, freeit, static_ldap_state);
341         
342 }
343 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
344 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
345
346 /*******************************************************************
347  a rebind function for authenticated referrals
348  this also does the connection, but no void*.
349 ******************************************************************/
350 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
351 # if LDAP_SET_REBIND_PROC_ARGS == 2
352 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
353                                ber_int_t msgid)
354 {
355         return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid, 
356                                              static_ldap_state);
357 }
358 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
359 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
360
361 /*******************************************************************
362  connect to the ldap server under system privilege.
363 ******************************************************************/
364 static int ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
365 {
366         int rc;
367         char *ldap_dn;
368         char *ldap_secret;
369
370         /* The rebind proc needs this *HACK*.  We are not multithreaded, so
371            this will work, but it's not nice. */
372         static_ldap_state = ldap_state;
373
374         /* get the password */
375         if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
376         {
377                 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
378                 return LDAP_INVALID_CREDENTIALS;
379         }
380
381         ldap_state->bind_dn = ldap_dn;
382         ldap_state->bind_secret = ldap_secret;
383
384         /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite 
385            (OpenLDAP) doesnt' seem to support it */
386            
387         DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
388                   ldap_state->uri, ldap_dn));
389
390 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
391 # if LDAP_SET_REBIND_PROC_ARGS == 2     
392         ldap_set_rebind_proc(ldap_struct, &rebindproc_connect); 
393 # endif
394 # if LDAP_SET_REBIND_PROC_ARGS == 3     
395         ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);  
396 # endif
397 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
398 # if LDAP_SET_REBIND_PROC_ARGS == 2     
399         ldap_set_rebind_proc(ldap_struct, &rebindproc); 
400 # endif
401 # if LDAP_SET_REBIND_PROC_ARGS == 3     
402         ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);  
403 # endif
404 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
405
406         rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
407
408         if (rc != LDAP_SUCCESS) {
409                 char *ld_error;
410                 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
411                                 &ld_error);
412                 DEBUG(0,
413                       ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
414                                ldap_dn, ldap_err2string(rc),
415                                ld_error));
416                 free(ld_error);
417                 return rc;
418         }
419         
420         DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n"));
421         return rc;
422 }
423
424 /**********************************************************************
425 Connect to LDAP server 
426 *********************************************************************/
427 static int ldapsam_open(struct ldapsam_privates *ldap_state)
428 {
429         int rc;
430         SMB_ASSERT(ldap_state);
431                 
432 #ifndef NO_LDAP_SECURITY
433         if (geteuid() != 0) {
434                 DEBUG(0, ("ldapsam_open: cannot access LDAP when not root..\n"));
435                 return  LDAP_INSUFFICIENT_ACCESS;
436         }
437 #endif
438
439         if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + LDAPSAM_DONT_PING_TIME) < time(NULL))) {
440                 struct sockaddr_un addr;
441                 socklen_t len;
442                 int sd;
443                 if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 &&
444                     getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
445                         /* the other end has died. reopen. */
446                         ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
447                         ldap_state->ldap_struct = NULL;
448                         ldap_state->last_ping = (time_t)0;
449                 } else {
450                         ldap_state->last_ping = time(NULL);
451                 } 
452         }
453
454         if (ldap_state->ldap_struct != NULL) {
455                 DEBUG(5,("ldapsam_open: allready connected to the LDAP server\n"));
456                 return LDAP_SUCCESS;
457         }
458
459         if ((rc = ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))) {
460                 return rc;
461         }
462
463         if ((rc = ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))) {
464                 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
465                 ldap_state->ldap_struct = NULL;
466                 return rc;
467         }
468
469
470         ldap_state->last_ping = time(NULL);
471         DEBUG(4,("The LDAP server is succesful connected\n"));
472
473         return LDAP_SUCCESS;
474 }
475
476 /**********************************************************************
477 Disconnect from LDAP server 
478 *********************************************************************/
479 static NTSTATUS ldapsam_close(struct ldapsam_privates *ldap_state)
480 {
481         if (!ldap_state)
482                 return NT_STATUS_INVALID_PARAMETER;
483                 
484         if (ldap_state->ldap_struct != NULL) {
485                 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
486                 ldap_state->ldap_struct = NULL;
487         }
488         
489         DEBUG(5,("The connection to the LDAP server was closed\n"));
490         /* maybe free the results here --metze */
491         
492         return NT_STATUS_OK;
493 }
494
495 static int ldapsam_retry_open(struct ldapsam_privates *ldap_state, int *attempts)
496 {
497         int rc;
498
499         SMB_ASSERT(ldap_state && attempts);
500                 
501         if (*attempts != 0) {
502                 /* we retry after 0.5, 2, 4.5, 8, 12.5, 18, 24.5 seconds */
503                 msleep((((*attempts)*(*attempts))/2)*1000);
504         }
505         (*attempts)++;
506
507         if ((rc = ldapsam_open(ldap_state))) {
508                 DEBUG(0,("Connection to LDAP Server failed for the %d try!\n",*attempts));
509                 return rc;
510         } 
511         
512         return LDAP_SUCCESS;            
513 }
514
515
516 static int ldapsam_search(struct ldapsam_privates *ldap_state, 
517                           const char *base, int scope, const char *filter, 
518                           const char *attrs[], int attrsonly, 
519                           LDAPMessage **res)
520 {
521         int             rc = LDAP_SERVER_DOWN;
522         int             attempts = 0;
523         
524         SMB_ASSERT(ldap_state);
525
526         while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
527                 
528                 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
529                         continue;
530                 
531                 rc = ldap_search_s(ldap_state->ldap_struct, base, scope, 
532                                    filter, attrs, attrsonly, res);
533         }
534         
535         if (rc == LDAP_SERVER_DOWN) {
536                 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
537                 ldapsam_close(ldap_state);      
538         }
539         
540         return rc;
541 }
542
543 static int ldapsam_modify(struct ldapsam_privates *ldap_state, char *dn, LDAPMod *attrs[])
544 {
545         int             rc = LDAP_SERVER_DOWN;
546         int             attempts = 0;
547         
548         if (!ldap_state)
549                 return (-1);
550
551         while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
552                 
553                 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
554                         continue;
555                 
556                 rc = ldap_modify_s(ldap_state->ldap_struct, dn, attrs);
557         }
558         
559         if (rc == LDAP_SERVER_DOWN) {
560                 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
561                 ldapsam_close(ldap_state);      
562         }
563         
564         return rc;
565 }
566
567 static int ldapsam_add(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[])
568 {
569         int             rc = LDAP_SERVER_DOWN;
570         int             attempts = 0;
571         
572         if (!ldap_state)
573                 return (-1);
574
575         while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
576                 
577                 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
578                         continue;
579                 
580                 rc = ldap_add_s(ldap_state->ldap_struct, dn, attrs);
581         }
582         
583         if (rc == LDAP_SERVER_DOWN) {
584                 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
585                 ldapsam_close(ldap_state);      
586         }
587                 
588         return rc;
589 }
590
591 static int ldapsam_delete(struct ldapsam_privates *ldap_state, char *dn)
592 {
593         int             rc = LDAP_SERVER_DOWN;
594         int             attempts = 0;
595         
596         if (!ldap_state)
597                 return (-1);
598
599         while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
600                 
601                 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
602                         continue;
603                 
604                 rc = ldap_delete_s(ldap_state->ldap_struct, dn);
605         }
606         
607         if (rc == LDAP_SERVER_DOWN) {
608                 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
609                 ldapsam_close(ldap_state);      
610         }
611                 
612         return rc;
613 }
614
615 static int ldapsam_extended_operation(struct ldapsam_privates *ldap_state, LDAP_CONST char *reqoid, struct berval *reqdata, LDAPControl **serverctrls, LDAPControl **clientctrls, char **retoidp, struct berval **retdatap)
616 {
617         int             rc = LDAP_SERVER_DOWN;
618         int             attempts = 0;
619         
620         if (!ldap_state)
621                 return (-1);
622
623         while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
624                 
625                 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
626                         continue;
627                 
628                 rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap);
629         }
630         
631         if (rc == LDAP_SERVER_DOWN) {
632                 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
633                 ldapsam_close(ldap_state);      
634         }
635                 
636         return rc;
637 }
638
639 /*******************************************************************
640  run the search by name.
641 ******************************************************************/
642 static int ldapsam_search_one_user (struct ldapsam_privates *ldap_state, const char *filter, LDAPMessage ** result)
643 {
644         int scope = LDAP_SCOPE_SUBTREE;
645         int rc;
646
647         DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter));
648
649         rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope, filter, attr, 0, result);
650
651         if (rc != LDAP_SUCCESS) {
652                 DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s\n", 
653                         ldap_err2string (rc)));
654                 DEBUG(3,("ldapsam_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(), 
655                         filter));
656         }
657         
658         return rc;
659 }
660
661 /*******************************************************************
662  run the search by name.
663 ******************************************************************/
664 static int ldapsam_search_one_user_by_name (struct ldapsam_privates *ldap_state, const char *user,
665                              LDAPMessage ** result)
666 {
667         pstring filter;
668         char *escape_user = escape_ldap_string_alloc(user);
669
670         if (!escape_user) {
671                 return LDAP_NO_MEMORY;
672         }
673
674         /*
675          * in the filter expression, replace %u with the real name
676          * so in ldap filter, %u MUST exist :-)
677          */
678         pstrcpy(filter, lp_ldap_filter());
679
680         /* 
681          * have to use this here because $ is filtered out
682            * in pstring_sub
683          */
684         
685
686         all_string_sub(filter, "%u", escape_user, sizeof(pstring));
687         SAFE_FREE(escape_user);
688
689         return ldapsam_search_one_user(ldap_state, filter, result);
690 }
691
692 /*******************************************************************
693  run the search by uid.
694 ******************************************************************/
695 static int ldapsam_search_one_user_by_uid(struct ldapsam_privates *ldap_state, 
696                                           int uid,
697                                           LDAPMessage ** result)
698 {
699         struct passwd *user;
700         pstring filter;
701         char *escape_user;
702
703         /* Get the username from the system and look that up in the LDAP */
704         
705         if ((user = getpwuid_alloc(uid)) == NULL) {
706                 DEBUG(3,("ldapsam_search_one_user_by_uid: Failed to locate uid [%d]\n", uid));
707                 return LDAP_NO_SUCH_OBJECT;
708         }
709         
710         pstrcpy(filter, lp_ldap_filter());
711         
712         escape_user = escape_ldap_string_alloc(user->pw_name);
713         if (!escape_user) {
714                 passwd_free(&user);
715                 return LDAP_NO_MEMORY;
716         }
717
718         all_string_sub(filter, "%u", escape_user, sizeof(pstring));
719
720         passwd_free(&user);
721         SAFE_FREE(escape_user);
722
723         return ldapsam_search_one_user(ldap_state, filter, result);
724 }
725
726 /*******************************************************************
727  run the search by rid.
728 ******************************************************************/
729 static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state, 
730                                            uint32 rid,
731                                            LDAPMessage ** result)
732 {
733         pstring filter;
734         int rc;
735
736         /* check if the user rid exsists, if not, try searching on the uid */
737         
738         snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
739         rc = ldapsam_search_one_user(ldap_state, filter, result);
740         
741         if (rc != LDAP_SUCCESS)
742                 rc = ldapsam_search_one_user_by_uid(ldap_state,
743                                                     fallback_pdb_user_rid_to_uid(rid), 
744                                                     result);
745
746         return rc;
747 }
748
749 /*******************************************************************
750 search an attribute and return the first value found.
751 ******************************************************************/
752 static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
753                                   const char *attribute, pstring value)
754 {
755         char **values;
756
757         if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
758                 value = NULL;
759                 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
760                 
761                 return False;
762         }
763         
764         pstrcpy(value, values[0]);
765         ldap_value_free(values);
766 #ifdef DEBUG_PASSWORDS
767         DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
768 #endif  
769         return True;
770 }
771
772 /************************************************************************
773 Routine to manage the LDAPMod structure array
774 manage memory used by the array, by each struct, and values
775
776 ************************************************************************/
777 static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
778 {
779         LDAPMod **mods;
780         int i;
781         int j;
782
783         mods = *modlist;
784
785         if (attribute == NULL || *attribute == '\0')
786                 return;
787
788 #if 0
789         /* Why do we need this??? -- vl */
790         if (value == NULL || *value == '\0')
791                 return;
792 #endif
793
794         if (mods == NULL) 
795         {
796                 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
797                 if (mods == NULL)
798                 {
799                         DEBUG(0, ("make_a_mod: out of memory!\n"));
800                         return;
801                 }
802                 mods[0] = NULL;
803         }
804
805         for (i = 0; mods[i] != NULL; ++i) {
806                 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
807                         break;
808         }
809
810         if (mods[i] == NULL)
811         {
812                 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
813                 if (mods == NULL)
814                 {
815                         DEBUG(0, ("make_a_mod: out of memory!\n"));
816                         return;
817                 }
818                 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
819                 if (mods[i] == NULL)
820                 {
821                         DEBUG(0, ("make_a_mod: out of memory!\n"));
822                         return;
823                 }
824                 mods[i]->mod_op = modop;
825                 mods[i]->mod_values = NULL;
826                 mods[i]->mod_type = strdup(attribute);
827                 mods[i + 1] = NULL;
828         }
829
830         if (value != NULL)
831         {
832                 j = 0;
833                 if (mods[i]->mod_values != NULL) {
834                         for (; mods[i]->mod_values[j] != NULL; j++);
835                 }
836                 mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
837                                                (j + 2) * sizeof (char *));
838                                                
839                 if (mods[i]->mod_values == NULL) {
840                         DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
841                         return;
842                 }
843                 mods[i]->mod_values[j] = strdup(value);
844                 mods[i]->mod_values[j + 1] = NULL;
845         }
846         *modlist = mods;
847 }
848
849 /*******************************************************************
850  Delete complete object or objectclass and attrs from
851  object found in search_result depending on lp_ldap_del_only_sam
852 ******************************************************************/
853 static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
854                                      LDAPMessage *result,
855                                      const char *objectclass,
856                                      const char **attrs)
857 {
858         int rc;
859         LDAPMessage *entry;
860         LDAPMod **mods = NULL;
861         char *name, *dn;
862         BerElement *ptr = NULL;
863
864         rc = ldap_count_entries(ldap_state->ldap_struct, result);
865
866         if (rc != 1) {
867                 DEBUG(0, ("Entry must exist exactly once!\n"));
868                 return NT_STATUS_UNSUCCESSFUL;
869         }
870
871         entry = ldap_first_entry(ldap_state->ldap_struct, result);
872         dn    = ldap_get_dn(ldap_state->ldap_struct, entry);
873
874         if (!lp_ldap_del_only_sam()) {
875                 NTSTATUS ret = NT_STATUS_OK;
876                 rc = ldapsam_delete(ldap_state, dn);
877
878                 if (rc != LDAP_SUCCESS) {
879                         DEBUG(0, ("Could not delete object %s\n", dn));
880                         ret = NT_STATUS_UNSUCCESSFUL;
881                 }
882                 ldap_memfree(dn);
883                 return ret;
884         }
885
886         /* Ok, delete only the SAM attributes */
887
888         for (name = ldap_first_attribute(ldap_state->ldap_struct, entry, &ptr);
889              name != NULL;
890              name = ldap_next_attribute(ldap_state->ldap_struct, entry, ptr)) {
891
892                 const char **attrib;
893
894                 /* We are only allowed to delete the attributes that
895                    really exist. */
896
897                 for (attrib = attrs; *attrib != NULL; attrib++) {
898                         if (StrCaseCmp(*attrib, name) == 0) {
899                                 DEBUG(10, ("deleting attribute %s\n", name));
900                                 make_a_mod(&mods, LDAP_MOD_DELETE, name, NULL);
901                         }
902                 }
903
904                 ldap_memfree(name);
905         }
906
907         if (ptr != NULL) {
908                 ber_free(ptr, 0);
909         }
910         
911         make_a_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
912
913         rc = ldapsam_modify(ldap_state, dn, mods);
914         ldap_mods_free(mods, 1);
915
916         if (rc != LDAP_SUCCESS) {
917                 DEBUG(0, ("could not delete attributes for %s, error: %s\n",
918                           dn, ldap_err2string(rc)));
919                 ldap_memfree(dn);
920                 return NT_STATUS_UNSUCCESSFUL;
921         }
922
923         ldap_memfree(dn);
924         return NT_STATUS_OK;
925 }
926                                           
927 /* New Interface is being implemented here */
928
929 /**********************************************************************
930 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
931 *********************************************************************/
932 static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state, 
933                                 SAM_ACCOUNT * sampass,
934                                 LDAPMessage * entry)
935 {
936         pstring  homedir;
937         pstring  temp;
938         uid_t uid;
939         gid_t gid;
940         char **ldap_values;
941         char **values;
942
943         if ((ldap_values = ldap_get_values (ldap_state->ldap_struct, entry, "objectClass")) == NULL) {
944                 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
945                 return False;
946         }
947
948         for (values=ldap_values;*values;values++) {
949                 if (strcasecmp(*values, "posixAccount") == 0) {
950                         break;
951                 }
952         }
953         
954         if (!*values) { /*end of array, no posixAccount */
955                 DEBUG(10, ("user does not have posixAcccount attributes\n"));
956                 ldap_value_free(ldap_values);
957                 return False;
958         }
959         ldap_value_free(ldap_values);
960
961         if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDirectory", homedir)) 
962                 return False;
963         
964         if (!get_single_attribute(ldap_state->ldap_struct, entry, "uidNumber", temp))
965                 return False;
966         
967         uid = (uid_t)atol(temp);
968         
969         if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber", temp))
970                 return False;
971         
972         gid = (gid_t)atol(temp);
973
974         pdb_set_unix_homedir(sampass, homedir, PDB_SET);
975         pdb_set_uid(sampass, uid, PDB_SET);
976         pdb_set_gid(sampass, gid, PDB_SET);
977         
978         DEBUG(10, ("user has posixAcccount attributes\n"));
979         return True;
980 }
981
982
983 /**********************************************************************
984 Initialize SAM_ACCOUNT from an LDAP query
985 (Based on init_sam_from_buffer in pdb_tdb.c)
986 *********************************************************************/
987 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, 
988                                 SAM_ACCOUNT * sampass,
989                                 LDAPMessage * entry)
990 {
991         time_t  logon_time,
992                         logoff_time,
993                         kickoff_time,
994                         pass_last_set_time, 
995                         pass_can_change_time, 
996                         pass_must_change_time;
997         pstring         username, 
998                         domain,
999                         nt_username,
1000                         fullname,
1001                         homedir,
1002                         dir_drive,
1003                         logon_script,
1004                         profile_path,
1005                         acct_desc,
1006                         munged_dial,
1007                         workstations;
1008         struct passwd   *pw;
1009         uint32          user_rid, 
1010                         group_rid;
1011         uint8           smblmpwd[LM_HASH_LEN],
1012                         smbntpwd[NT_HASH_LEN];
1013         uint16          acct_ctrl = 0, 
1014                         logon_divs;
1015         uint32 hours_len;
1016         uint8           hours[MAX_HOURS_LEN];
1017         pstring temp;
1018         uid_t           uid = -1;
1019         gid_t           gid = getegid();
1020
1021
1022         /*
1023          * do a little initialization
1024          */
1025         username[0]     = '\0';
1026         domain[0]       = '\0';
1027         nt_username[0]  = '\0';
1028         fullname[0]     = '\0';
1029         homedir[0]      = '\0';
1030         dir_drive[0]    = '\0';
1031         logon_script[0] = '\0';
1032         profile_path[0] = '\0';
1033         acct_desc[0]    = '\0';
1034         munged_dial[0]  = '\0';
1035         workstations[0] = '\0';
1036          
1037
1038         if (sampass == NULL || ldap_state == NULL || entry == NULL) {
1039                 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
1040                 return False;
1041         }
1042
1043         if (ldap_state->ldap_struct == NULL) {
1044                 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
1045                 return False;
1046         }
1047         
1048         get_single_attribute(ldap_state->ldap_struct, entry, "uid", username);
1049         DEBUG(2, ("Entry found for user: %s\n", username));
1050
1051         pstrcpy(nt_username, username);
1052
1053         pstrcpy(domain, lp_workgroup());
1054         
1055         pdb_set_username(sampass, username, PDB_SET);
1056
1057         pdb_set_domain(sampass, domain, PDB_DEFAULT);
1058         pdb_set_nt_username(sampass, nt_username, PDB_SET);
1059
1060         get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp);
1061         user_rid = (uint32)atol(temp);
1062
1063         pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1064
1065         if (!get_single_attribute(ldap_state->ldap_struct, entry, "primaryGroupID", temp)) {
1066                 group_rid = 0;
1067         } else {
1068                 group_rid = (uint32)atol(temp);
1069                 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1070         }
1071
1072
1073         /* 
1074          * If so configured, try and get the values from LDAP 
1075          */
1076
1077         if (!lp_ldap_trust_ids() || (!get_unix_attributes(ldap_state, sampass, entry))) {
1078                 
1079                 /* 
1080                  * Otherwise just ask the system getpw() calls.
1081                  */
1082         
1083                 pw = getpwnam_alloc(username);
1084                 if (pw == NULL) {
1085                         if (! ldap_state->permit_non_unix_accounts) {
1086                                 DEBUG (2,("init_sam_from_ldap: User [%s] does not exist via system getpwnam!\n", username));
1087                                 return False;
1088                         }
1089                 } else {
1090                         uid = pw->pw_uid;
1091                         pdb_set_uid(sampass, uid, PDB_SET);
1092                         gid = pw->pw_gid;
1093                         pdb_set_gid(sampass, gid, PDB_SET);
1094                         
1095                         pdb_set_unix_homedir(sampass, pw->pw_dir, PDB_SET);
1096
1097                         passwd_free(&pw);
1098                 }
1099         }
1100
1101         if (group_rid == 0 && pdb_get_init_flags(sampass,PDB_GID) != PDB_DEFAULT) {
1102                 GROUP_MAP map;
1103                 gid = pdb_get_gid(sampass);
1104                 /* call the mapping code here */
1105                 if(pdb_getgrgid(&map, gid, MAPPING_WITHOUT_PRIV)) {
1106                         pdb_set_group_sid(sampass, &map.sid, PDB_SET);
1107                 } 
1108                 else {
1109                         pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
1110                 }
1111         }
1112
1113         if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdLastSet", temp)) {
1114                 /* leave as default */
1115         } else {
1116                 pass_last_set_time = (time_t) atol(temp);
1117                 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1118         }
1119
1120         if (!get_single_attribute(ldap_state->ldap_struct, entry, "logonTime", temp)) {
1121                 /* leave as default */
1122         } else {
1123                 logon_time = (time_t) atol(temp);
1124                 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1125         }
1126
1127         if (!get_single_attribute(ldap_state->ldap_struct, entry, "logoffTime", temp)) {
1128                 /* leave as default */
1129         } else {
1130                 logoff_time = (time_t) atol(temp);
1131                 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1132         }
1133
1134         if (!get_single_attribute(ldap_state->ldap_struct, entry, "kickoffTime", temp)) {
1135                 /* leave as default */
1136         } else {
1137                 kickoff_time = (time_t) atol(temp);
1138                 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1139         }
1140
1141         if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdCanChange", temp)) {
1142                 /* leave as default */
1143         } else {
1144                 pass_can_change_time = (time_t) atol(temp);
1145                 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1146         }
1147
1148         if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdMustChange", temp)) {
1149                 /* leave as default */
1150         } else {
1151                 pass_must_change_time = (time_t) atol(temp);
1152                 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1153         }
1154
1155         /* recommend that 'gecos' and 'displayName' should refer to the same
1156          * attribute OID.  userFullName depreciated, only used by Samba
1157          * primary rules of LDAP: don't make a new attribute when one is already defined
1158          * that fits your needs; using cn then displayName rather than 'userFullName'
1159          */
1160
1161         if (!get_single_attribute(ldap_state->ldap_struct, entry, "cn", fullname)) {
1162                 if (!get_single_attribute(ldap_state->ldap_struct, entry, "displayName", fullname)) {
1163                         /* leave as default */
1164                 } else {
1165                         pdb_set_fullname(sampass, fullname, PDB_SET);
1166                 }
1167         } else {
1168                 pdb_set_fullname(sampass, fullname, PDB_SET);
1169         }
1170
1171         if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDrive", dir_drive)) {
1172                 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx, 
1173                                                                   lp_logon_drive(),
1174                                                                   username, domain, 
1175                                                                   uid, gid),
1176                                   PDB_DEFAULT);
1177         } else {
1178                 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1179         }
1180
1181         if (!get_single_attribute(ldap_state->ldap_struct, entry, "smbHome", homedir)) {
1182                 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx, 
1183                                                                   lp_logon_home(),
1184                                                                   username, domain, 
1185                                                                   uid, gid), 
1186                                   PDB_DEFAULT);
1187         } else {
1188                 pdb_set_homedir(sampass, homedir, PDB_SET);
1189         }
1190
1191         if (!get_single_attribute(ldap_state->ldap_struct, entry, "scriptPath", logon_script)) {
1192                 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx, 
1193                                                                      lp_logon_script(),
1194                                                                      username, domain, 
1195                                                                      uid, gid), 
1196                                      PDB_DEFAULT);
1197         } else {
1198                 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1199         }
1200
1201         if (!get_single_attribute(ldap_state->ldap_struct, entry, "profilePath", profile_path)) {
1202                 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx, 
1203                                                                      lp_logon_path(),
1204                                                                      username, domain, 
1205                                                                      uid, gid), 
1206                                      PDB_DEFAULT);
1207         } else {
1208                 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1209         }
1210
1211         if (!get_single_attribute(ldap_state->ldap_struct, entry, "description", acct_desc)) {
1212                 /* leave as default */
1213         } else {
1214                 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1215         }
1216
1217         if (!get_single_attribute(ldap_state->ldap_struct, entry, "userWorkstations", workstations)) {
1218                 /* leave as default */;
1219         } else {
1220                 pdb_set_workstations(sampass, workstations, PDB_SET);
1221         }
1222
1223         /* FIXME: hours stuff should be cleaner */
1224         
1225         logon_divs = 168;
1226         hours_len = 21;
1227         memset(hours, 0xff, hours_len);
1228
1229         if (!get_single_attribute (ldap_state->ldap_struct, entry, "lmPassword", temp)) {
1230                 /* leave as default */
1231         } else {
1232                 pdb_gethexpwd(temp, smblmpwd);
1233                 memset((char *)temp, '\0', strlen(temp)+1);
1234                 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
1235                         return False;
1236                 ZERO_STRUCT(smblmpwd);
1237         }
1238
1239         if (!get_single_attribute (ldap_state->ldap_struct, entry, "ntPassword", temp)) {
1240                 /* leave as default */
1241         } else {
1242                 pdb_gethexpwd(temp, smbntpwd);
1243                 memset((char *)temp, '\0', strlen(temp)+1);
1244                 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
1245                         return False;
1246                 ZERO_STRUCT(smbntpwd);
1247         }
1248
1249         if (!get_single_attribute (ldap_state->ldap_struct, entry, "acctFlags", temp)) {
1250                 acct_ctrl |= ACB_NORMAL;
1251         } else {
1252                 acct_ctrl = pdb_decode_acct_ctrl(temp);
1253
1254                 if (acct_ctrl == 0)
1255                         acct_ctrl |= ACB_NORMAL;
1256
1257                 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1258         }
1259
1260         pdb_set_hours_len(sampass, hours_len, PDB_SET);
1261         pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1262
1263         pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1264         
1265         /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
1266         /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
1267         /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
1268
1269         pdb_set_hours(sampass, hours, PDB_SET);
1270
1271         return True;
1272 }
1273
1274 static BOOL need_ldap_mod(BOOL pdb_add, const SAM_ACCOUNT * sampass, enum pdb_elements element) {
1275         if (pdb_add) {
1276                 return (!IS_SAM_DEFAULT(sampass, element));
1277         } else {
1278                 return IS_SAM_CHANGED(sampass, element);
1279         }
1280 }
1281
1282 /**********************************************************************
1283 Initialize SAM_ACCOUNT from an LDAP query
1284 (Based on init_buffer_from_sam in pdb_tdb.c)
1285 *********************************************************************/
1286 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, 
1287                                 LDAPMod *** mods, int ldap_op, 
1288                                 BOOL pdb_add,
1289                                 const SAM_ACCOUNT * sampass)
1290 {
1291         pstring temp;
1292         uint32 rid;
1293
1294         if (mods == NULL || sampass == NULL) {
1295                 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1296                 return False;
1297         }
1298
1299         *mods = NULL;
1300
1301         /* 
1302          * took out adding "objectclass: sambaAccount"
1303          * do this on a per-mod basis
1304          */
1305         if (need_ldap_mod(pdb_add, sampass, PDB_USERNAME)) {
1306                 make_a_mod(mods, ldap_op, "uid", pdb_get_username(sampass));
1307                 DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
1308         }
1309         
1310         if ((rid = pdb_get_user_rid(sampass))!=0 ) {
1311                 if (need_ldap_mod(pdb_add, sampass, PDB_USERSID)) {             
1312                         slprintf(temp, sizeof(temp) - 1, "%i", rid);
1313                         make_a_mod(mods, ldap_op, "rid", temp);
1314                 }
1315         } else if (!IS_SAM_DEFAULT(sampass, PDB_UID)) {
1316                 rid = fallback_pdb_uid_to_user_rid(pdb_get_uid(sampass));
1317                 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1318                 make_a_mod(mods, ldap_op, "rid", temp);
1319         } else if (ldap_state->permit_non_unix_accounts) {
1320                 rid = ldapsam_get_next_available_nua_rid(ldap_state);
1321                 if (rid == 0) {
1322                         DEBUG(0, ("NO user RID specified on account %s, and findining next available NUA RID failed, cannot store!\n", pdb_get_username(sampass)));
1323                         return False;
1324                 }
1325                 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1326                 make_a_mod(mods, ldap_op, "rid", temp);
1327         } else {
1328                 DEBUG(0, ("NO user RID specified on account %s, cannot store!\n", pdb_get_username(sampass)));
1329                 return False;
1330         }
1331
1332
1333
1334         if ((rid = pdb_get_group_rid(sampass))!=0 ) {
1335                 if (need_ldap_mod(pdb_add, sampass, PDB_GROUPSID)) {            
1336                         slprintf(temp, sizeof(temp) - 1, "%i", rid);
1337                         make_a_mod(mods, ldap_op, "primaryGroupID", temp);
1338                 }
1339         } else if (!IS_SAM_DEFAULT(sampass, PDB_GID)) {
1340                 rid = pdb_gid_to_group_rid(pdb_get_gid(sampass));
1341                 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1342                 make_a_mod(mods, ldap_op, "primaryGroupID", temp);
1343         } else if (ldap_state->permit_non_unix_accounts) {
1344                 rid = DOMAIN_GROUP_RID_USERS;
1345                 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1346                 make_a_mod(mods, ldap_op, "primaryGroupID", temp);
1347         } else {
1348                 DEBUG(0, ("NO group RID specified on account %s, cannot store!\n", pdb_get_username(sampass)));
1349                 return False;
1350         }
1351
1352
1353         /* displayName, cn, and gecos should all be the same
1354          *  most easily accomplished by giving them the same OID
1355          *  gecos isn't set here b/c it should be handled by the 
1356          *  add-user script
1357          */
1358         if (need_ldap_mod(pdb_add, sampass, PDB_FULLNAME)) {
1359                 make_a_mod(mods, ldap_op, "displayName", pdb_get_fullname(sampass));
1360                 make_a_mod(mods, ldap_op, "cn", pdb_get_fullname(sampass));
1361         }
1362         if (need_ldap_mod(pdb_add, sampass, PDB_ACCTDESC)) {    
1363                 make_a_mod(mods, ldap_op, "description", pdb_get_acct_desc(sampass));
1364         }
1365         if (need_ldap_mod(pdb_add, sampass, PDB_WORKSTATIONS)) {        
1366                 make_a_mod(mods, ldap_op, "userWorkstations", pdb_get_workstations(sampass));
1367         }
1368         /*
1369          * Only updates fields which have been set (not defaults from smb.conf)
1370          */
1371
1372         if (need_ldap_mod(pdb_add, sampass, PDB_SMBHOME)) {
1373                 make_a_mod(mods, ldap_op, "smbHome", pdb_get_homedir(sampass));
1374         }
1375                         
1376         if (need_ldap_mod(pdb_add, sampass, PDB_DRIVE)) {
1377                 make_a_mod(mods, ldap_op, "homeDrive", pdb_get_dir_drive(sampass));
1378         }
1379         
1380         if (need_ldap_mod(pdb_add, sampass, PDB_LOGONSCRIPT)) {
1381                 make_a_mod(mods, ldap_op, "scriptPath", pdb_get_logon_script(sampass));
1382         }
1383         
1384         if (need_ldap_mod(pdb_add, sampass, PDB_PROFILE))
1385                 make_a_mod(mods, ldap_op, "profilePath", pdb_get_profile_path(sampass));
1386
1387         if (need_ldap_mod(pdb_add, sampass, PDB_LOGONTIME)) {
1388                 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
1389                 make_a_mod(mods, ldap_op, "logonTime", temp);
1390         }
1391
1392         if (need_ldap_mod(pdb_add, sampass, PDB_LOGOFFTIME)) {
1393                 slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
1394                 make_a_mod(mods, ldap_op, "logoffTime", temp);
1395         }
1396
1397         if (need_ldap_mod(pdb_add, sampass, PDB_KICKOFFTIME)) {
1398                 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass));
1399                 make_a_mod(mods, ldap_op, "kickoffTime", temp);
1400         }
1401
1402
1403         if (need_ldap_mod(pdb_add, sampass, PDB_CANCHANGETIME)) {
1404                 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
1405                 make_a_mod(mods, ldap_op, "pwdCanChange", temp);
1406         }
1407
1408         if (need_ldap_mod(pdb_add, sampass, PDB_MUSTCHANGETIME)) {
1409                 slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass));
1410                 make_a_mod(mods, ldap_op, "pwdMustChange", temp);
1411         }
1412
1413         if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))||
1414                 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
1415
1416                 if (need_ldap_mod(pdb_add, sampass, PDB_LMPASSWD)) {
1417                         pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass), pdb_get_acct_ctrl(sampass));
1418                         make_a_mod (mods, ldap_op, "lmPassword", temp);
1419                 }
1420                 
1421                 if (need_ldap_mod(pdb_add, sampass, PDB_NTPASSWD)) {
1422                         pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass), pdb_get_acct_ctrl(sampass));
1423                         make_a_mod (mods, ldap_op, "ntPassword", temp);
1424                 }
1425                 
1426                 if (need_ldap_mod(pdb_add, sampass, PDB_PASSLASTSET)) {
1427                         slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
1428                         make_a_mod(mods, ldap_op, "pwdLastSet", temp);
1429                 }
1430         }
1431
1432         /* FIXME: Hours stuff goes in LDAP  */
1433         if (need_ldap_mod(pdb_add, sampass, PDB_ACCTCTRL)) {
1434                 make_a_mod (mods, ldap_op, "acctFlags", pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
1435                         NEW_PW_FORMAT_SPACE_PADDED_LEN));
1436         }
1437         
1438         return True;
1439 }
1440
1441
1442 /**********************************************************************
1443 Connect to LDAP server and find the next available RID.
1444 *********************************************************************/
1445 static uint32 check_nua_rid_is_avail(struct ldapsam_privates *ldap_state, uint32 top_rid) 
1446 {
1447         LDAPMessage *result;
1448         uint32 final_rid = (top_rid & (~USER_RID_TYPE)) + RID_MULTIPLIER;
1449         if (top_rid == 0) {
1450                 return 0;
1451         }
1452         
1453         if (final_rid < ldap_state->low_nua_rid || final_rid > ldap_state->high_nua_rid) {
1454                 return 0;
1455         }
1456
1457         if (ldapsam_search_one_user_by_rid(ldap_state, final_rid, &result) != LDAP_SUCCESS) {
1458                 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the confirmation search failed!\n", final_rid, final_rid));
1459                 return 0;
1460         }
1461
1462         if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
1463                 DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the RID is already in use!!\n", final_rid, final_rid));
1464                 ldap_msgfree(result);
1465                 return 0;
1466         }
1467
1468         DEBUG(5, ("NUA RID %d (0x%x), declared valid\n", final_rid, final_rid));
1469         ldap_msgfree(result);
1470         return final_rid;
1471 }
1472
1473 /**********************************************************************
1474 Extract the RID from an LDAP entry
1475 *********************************************************************/
1476 static uint32 entry_to_user_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry) {
1477         uint32 rid;
1478         SAM_ACCOUNT *user = NULL;
1479         if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
1480                 return 0;
1481         }
1482
1483         if (init_sam_from_ldap(ldap_state, user, entry)) {
1484                 rid = pdb_get_user_rid(user);
1485         } else {
1486                 rid =0;
1487         }
1488         pdb_free_sam(&user);
1489         if (rid >= ldap_state->low_nua_rid && rid <= ldap_state->high_nua_rid) {
1490                 return rid;
1491         }
1492         return 0;
1493 }
1494
1495
1496 /**********************************************************************
1497 Connect to LDAP server and find the next available RID.
1498 *********************************************************************/
1499 static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state)
1500 {
1501         int rc;
1502         pstring filter;
1503         LDAPMessage *result;
1504         LDAPMessage *entry;
1505         char *final_filter = NULL;
1506         uint32 top_rid = 0;
1507         uint32 count;
1508         uint32 rid;
1509
1510         pstrcpy(filter, lp_ldap_filter());
1511         all_string_sub(filter, "%u", "*", sizeof(pstring));
1512
1513 #if 0
1514         asprintf(&final_filter, "(&(%s)(&(rid>=%d)(rid<=%d)))", filter, ldap_state->low_nua_rid, ldap_state->high_nua_rid);
1515 #else 
1516         final_filter = strdup(filter);
1517 #endif  
1518         DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter));
1519
1520         rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
1521                            LDAP_SCOPE_SUBTREE, final_filter, attr, 0,
1522                            &result);
1523
1524         if (rc != LDAP_SUCCESS) {
1525                 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
1526                 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1527
1528                 free(final_filter);
1529                 result = NULL;
1530                 return 0;
1531         }
1532         
1533         count = ldap_count_entries(ldap_state->ldap_struct, result);
1534         DEBUG(2, ("search_top_nua_rid: %d entries in the base!\n", count));
1535         
1536         if (count == 0) {
1537                 DEBUG(3, ("LDAP search returned no records, assuming no non-unix-accounts present!: %s\n", ldap_err2string(rc)));
1538                 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
1539                 free(final_filter);
1540                 ldap_msgfree(result);
1541                 result = NULL;
1542                 return ldap_state->low_nua_rid;
1543         }
1544         
1545         free(final_filter);
1546         entry = ldap_first_entry(ldap_state->ldap_struct,result);
1547
1548         top_rid = entry_to_user_rid(ldap_state, entry);
1549
1550         while ((entry = ldap_next_entry(ldap_state->ldap_struct, entry))) {
1551
1552                 rid = entry_to_user_rid(ldap_state, entry);
1553                 if (rid > top_rid) {
1554                         top_rid = rid;
1555                 }
1556         }
1557
1558         ldap_msgfree(result);
1559
1560         if (top_rid < ldap_state->low_nua_rid) 
1561                 top_rid = ldap_state->low_nua_rid;
1562
1563         return top_rid;
1564 }
1565
1566 /**********************************************************************
1567 Connect to LDAP server and find the next available RID.
1568 *********************************************************************/
1569 static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state) {
1570         uint32 next_nua_rid;
1571         uint32 top_nua_rid;
1572
1573         top_nua_rid = search_top_nua_rid(ldap_state);
1574
1575         next_nua_rid = check_nua_rid_is_avail(ldap_state, 
1576                                               top_nua_rid);
1577         
1578         return next_nua_rid;
1579 }
1580
1581 /**********************************************************************
1582 Connect to LDAP server for password enumeration
1583 *********************************************************************/
1584 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
1585 {
1586         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1587         int rc;
1588         pstring filter;
1589
1590         pstrcpy(filter, lp_ldap_filter());
1591         all_string_sub(filter, "%u", "*", sizeof(pstring));
1592
1593         rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
1594                            LDAP_SCOPE_SUBTREE, filter, attr, 0,
1595                            &ldap_state->result);
1596
1597         if (rc != LDAP_SUCCESS) {
1598                 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
1599                 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1600                 ldap_msgfree(ldap_state->result);
1601                 ldap_state->result = NULL;
1602                 return NT_STATUS_UNSUCCESSFUL;
1603         }
1604
1605         DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
1606                 ldap_count_entries(ldap_state->ldap_struct,
1607                 ldap_state->result)));
1608
1609         ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
1610                                  ldap_state->result);
1611         ldap_state->index = 0;
1612
1613         return NT_STATUS_OK;
1614 }
1615
1616 /**********************************************************************
1617 End enumeration of the LDAP password list 
1618 *********************************************************************/
1619 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
1620 {
1621         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1622         if (ldap_state->result) {
1623                 ldap_msgfree(ldap_state->result);
1624                 ldap_state->result = NULL;
1625         }
1626 }
1627
1628 /**********************************************************************
1629 Get the next entry in the LDAP password database 
1630 *********************************************************************/
1631 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
1632 {
1633         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1634         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1635         BOOL bret = False;
1636
1637         /* The rebind proc needs this *HACK*.  We are not multithreaded, so
1638            this will work, but it's not nice. */
1639         static_ldap_state = ldap_state;
1640
1641         while (!bret) {
1642                 if (!ldap_state->entry)
1643                         return ret;
1644                 
1645                 ldap_state->index++;
1646                 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
1647                 
1648                 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
1649                                             ldap_state->entry); 
1650         }
1651
1652         return NT_STATUS_OK;
1653 }
1654
1655 /**********************************************************************
1656 Get SAM_ACCOUNT entry from LDAP by username 
1657 *********************************************************************/
1658 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
1659 {
1660         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1661         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1662         LDAPMessage *result;
1663         LDAPMessage *entry;
1664         int count;
1665         
1666         if (ldapsam_search_one_user_by_name(ldap_state, sname, &result) != LDAP_SUCCESS) {
1667                 return NT_STATUS_NO_SUCH_USER;
1668         }
1669         
1670         count = ldap_count_entries(ldap_state->ldap_struct, result);
1671         
1672         if (count < 1) {
1673                 DEBUG(4,
1674                       ("We don't find this user [%s] count=%d\n", sname,
1675                        count));
1676                 return NT_STATUS_NO_SUCH_USER;
1677         } else if (count > 1) {
1678                 DEBUG(1,
1679                       ("Duplicate entries for this user [%s] Failing. count=%d\n", sname,
1680                        count));
1681                 return NT_STATUS_NO_SUCH_USER;
1682         }
1683
1684         entry = ldap_first_entry(ldap_state->ldap_struct, result);
1685         if (entry) {
1686                 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1687                         DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
1688                         ldap_msgfree(result);
1689                         return NT_STATUS_NO_SUCH_USER;
1690                 }
1691                 ldap_msgfree(result);
1692                 ret = NT_STATUS_OK;
1693         } else {
1694                 ldap_msgfree(result);
1695         }
1696         return ret;
1697 }
1698
1699 /**********************************************************************
1700 Get SAM_ACCOUNT entry from LDAP by rid 
1701 *********************************************************************/
1702 static NTSTATUS ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT *user, uint32 rid)
1703 {
1704         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1705         struct ldapsam_privates *ldap_state = 
1706                 (struct ldapsam_privates *)my_methods->private_data;
1707         LDAPMessage *result;
1708         LDAPMessage *entry;
1709         int count;
1710
1711         if (ldapsam_search_one_user_by_rid(ldap_state, rid, &result) != LDAP_SUCCESS) {
1712                 return NT_STATUS_NO_SUCH_USER;
1713         }
1714
1715         count = ldap_count_entries(ldap_state->ldap_struct, result);
1716                 
1717         if (count < 1) {
1718                 DEBUG(4,
1719                       ("We don't find this rid [%i] count=%d\n", rid,
1720                        count));
1721                 return NT_STATUS_NO_SUCH_USER;
1722         } else if (count > 1) {
1723                 DEBUG(1,
1724                       ("More than one user with rid [%i]. Failing. count=%d\n", rid,
1725                        count));
1726                 return NT_STATUS_NO_SUCH_USER;
1727         }
1728
1729         entry = ldap_first_entry(ldap_state->ldap_struct, result);
1730         if (entry) {
1731                 if (!init_sam_from_ldap(ldap_state, user, entry)) {
1732                         DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
1733                         ldap_msgfree(result);
1734                         return NT_STATUS_NO_SUCH_USER;
1735                 }
1736                 ldap_msgfree(result);
1737                 ret = NT_STATUS_OK;
1738         } else {
1739                 ldap_msgfree(result);
1740         }
1741         return ret;
1742 }
1743
1744 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
1745 {
1746         uint32 rid;
1747         if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
1748                 return NT_STATUS_NO_SUCH_USER;
1749         return ldapsam_getsampwrid(my_methods, user, rid);
1750 }       
1751
1752 /********************************************************************
1753 Do the actual modification - also change a plaittext passord if 
1754 it it set.
1755 **********************************************************************/
1756
1757 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, 
1758                                      SAM_ACCOUNT *newpwd, char *dn,
1759                                      LDAPMod **mods, int ldap_op, BOOL pdb_add)
1760 {
1761         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1762         int rc;
1763         
1764         if (!my_methods || !newpwd || !dn) {
1765                 return NT_STATUS_INVALID_PARAMETER;
1766         }
1767         
1768         if (!mods) {
1769                 DEBUG(5,("mods is empty: nothing to modify\n"));
1770                 /* may be password change below however */
1771         } else {
1772                 switch(ldap_op)
1773                 {
1774                         case LDAP_MOD_ADD: 
1775                                 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
1776                                 rc = ldapsam_add(ldap_state, dn, mods);
1777                                 break;
1778                         case LDAP_MOD_REPLACE: 
1779                                 rc = ldapsam_modify(ldap_state, dn ,mods);
1780                                 break;
1781                         default:        
1782                                 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
1783                                 return NT_STATUS_UNSUCCESSFUL;
1784                 }
1785                 
1786                 if (rc!=LDAP_SUCCESS) {
1787                         char *ld_error;
1788                         ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1789                                         &ld_error);
1790                         DEBUG(1,
1791                               ("failed to %s user dn= %s with: %s\n\t%s\n",
1792                                ldap_op == LDAP_MOD_ADD ? "add" : "modify",
1793                                dn, ldap_err2string(rc),
1794                                ld_error));
1795                         free(ld_error);
1796                         return NT_STATUS_UNSUCCESSFUL;
1797                 }  
1798         }
1799         
1800 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
1801         if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))&&
1802                 (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_OFF)&&
1803                 need_ldap_mod(pdb_add, newpwd, PDB_PLAINTEXT_PW)&&
1804                 (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
1805                 BerElement *ber;
1806                 struct berval *bv;
1807                 char *retoid;
1808                 struct berval *retdata;
1809
1810                 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
1811                         DEBUG(0,("ber_alloc_t returns NULL\n"));
1812                         return NT_STATUS_UNSUCCESSFUL;
1813                 }
1814                 ber_printf (ber, "{");
1815                 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID,dn);
1816                 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, pdb_get_plaintext_passwd(newpwd));
1817                 ber_printf (ber, "N}");
1818
1819                 if ((rc = ber_flatten (ber, &bv))<0) {
1820                         DEBUG(0,("ber_flatten returns a value <0\n"));
1821                         return NT_STATUS_UNSUCCESSFUL;
1822                 }
1823                 
1824                 ber_free(ber,1);
1825
1826                 if ((rc = ldapsam_extended_operation(ldap_state, LDAP_EXOP_X_MODIFY_PASSWD,
1827                                                     bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) {
1828                         DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
1829                                 pdb_get_username(newpwd),ldap_err2string(rc)));
1830                 } else {
1831                         DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
1832     
1833                         ber_bvfree(retdata);
1834                         ber_memfree(retoid);
1835                 }
1836                 ber_bvfree(bv);
1837         }
1838 #else
1839         DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
1840 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */
1841         return NT_STATUS_OK;
1842 }
1843
1844 /**********************************************************************
1845 Delete entry from LDAP for username 
1846 *********************************************************************/
1847 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
1848 {
1849         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1850         const char *sname;
1851         int rc;
1852         LDAPMessage *result;
1853         NTSTATUS ret;
1854         const char *sam_user_attrs[] =
1855         { "lmPassword", "ntPassword", "pwdLastSet", "logonTime", "logoffTime",
1856           "kickoffTime", "pwdCanChange", "pwdMustChange", "acctFlags",
1857           "displayName", "smbHome", "homeDrive", "scriptPath", "profilePath",
1858           "userWorkstations", "primaryGroupID", "domain", "rid", NULL };
1859
1860         if (!sam_acct) {
1861                 DEBUG(0, ("sam_acct was NULL!\n"));
1862                 return NT_STATUS_INVALID_PARAMETER;
1863         }
1864
1865         sname = pdb_get_username(sam_acct);
1866
1867         DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
1868
1869         rc = ldapsam_search_one_user_by_name(ldap_state, sname, &result);
1870         if (rc != LDAP_SUCCESS) {
1871                 return NT_STATUS_NO_SUCH_USER;
1872         }
1873
1874         ret = ldapsam_delete_entry(ldap_state, result, "sambaAccount",
1875                                    sam_user_attrs);
1876         ldap_msgfree(result);
1877         return ret;
1878 }
1879
1880 /**********************************************************************
1881 Update SAM_ACCOUNT 
1882 *********************************************************************/
1883 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1884 {
1885         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1886         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1887         int rc;
1888         char *dn;
1889         LDAPMessage *result;
1890         LDAPMessage *entry;
1891         LDAPMod **mods;
1892
1893         if (!init_ldap_from_sam(ldap_state, &mods, LDAP_MOD_REPLACE, False, newpwd)) {
1894                 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
1895                 return NT_STATUS_UNSUCCESSFUL;
1896         }
1897         
1898         if (mods == NULL) {
1899                 DEBUG(4,("mods is empty: nothing to update for user: %s\n",pdb_get_username(newpwd)));
1900                 return NT_STATUS_OK;
1901         }
1902         
1903         rc = ldapsam_search_one_user_by_name(ldap_state, pdb_get_username(newpwd), &result);
1904         if (rc != LDAP_SUCCESS) {
1905                 ldap_mods_free(mods, 1);
1906                 return NT_STATUS_UNSUCCESSFUL;
1907         }
1908
1909         if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
1910                 DEBUG(0, ("No user to modify!\n"));
1911                 ldap_msgfree(result);
1912                 ldap_mods_free(mods, 1);
1913                 return NT_STATUS_UNSUCCESSFUL;
1914         }
1915
1916         entry = ldap_first_entry(ldap_state->ldap_struct, result);
1917         dn = ldap_get_dn(ldap_state->ldap_struct, entry);
1918         ldap_msgfree(result);
1919         
1920         ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, False);
1921         if (NT_STATUS_IS_ERR(ret)) {
1922                 DEBUG(0,("failed to modify user with uid = %s\n",
1923                                         pdb_get_username(newpwd)));
1924                 ldap_mods_free(mods,1);
1925                 return ret;
1926         }
1927
1928
1929         DEBUG(2,
1930               ("successfully modified uid = %s in the LDAP database\n",
1931                pdb_get_username(newpwd)));
1932         ldap_mods_free(mods, 1);
1933         return NT_STATUS_OK;
1934 }
1935
1936 /**********************************************************************
1937 Add SAM_ACCOUNT to LDAP 
1938 *********************************************************************/
1939 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
1940 {
1941         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1942         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
1943         int rc;
1944         pstring filter;
1945         LDAPMessage *result = NULL;
1946         pstring dn;
1947         LDAPMod **mods = NULL;
1948         int             ldap_op;
1949         uint32          num_result;
1950         
1951         const char *username = pdb_get_username(newpwd);
1952         if (!username || !*username) {
1953                 DEBUG(0, ("Cannot add user without a username!\n"));
1954                 return NT_STATUS_INVALID_PARAMETER;
1955         }
1956
1957         rc = ldapsam_search_one_user_by_name (ldap_state, username, &result);
1958         if (rc != LDAP_SUCCESS) {
1959                 return NT_STATUS_UNSUCCESSFUL;
1960         }
1961
1962         if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
1963                 DEBUG(0,("User '%s' already in the base, with samba properties\n", 
1964                          username));
1965                 ldap_msgfree(result);
1966                 return NT_STATUS_UNSUCCESSFUL;
1967         }
1968         ldap_msgfree(result);
1969
1970         slprintf (filter, sizeof (filter) - 1, "uid=%s", username);
1971         rc = ldapsam_search_one_user(ldap_state, filter, &result);
1972         if (rc != LDAP_SUCCESS) {
1973                 return NT_STATUS_UNSUCCESSFUL;
1974         }
1975
1976         num_result = ldap_count_entries(ldap_state->ldap_struct, result);
1977         
1978         if (num_result > 1) {
1979                 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
1980                 ldap_msgfree(result);
1981                 return NT_STATUS_UNSUCCESSFUL;
1982         }
1983         
1984         /* Check if we need to update an existing entry */
1985         if (num_result == 1) {
1986                 char *tmp;
1987                 LDAPMessage *entry;
1988                 
1989                 DEBUG(3,("User exists without samba properties: adding them\n"));
1990                 ldap_op = LDAP_MOD_REPLACE;
1991                 entry = ldap_first_entry (ldap_state->ldap_struct, result);
1992                 tmp = ldap_get_dn (ldap_state->ldap_struct, entry);
1993                 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
1994                 ldap_memfree (tmp);
1995         } else {
1996                 /* Check if we need to add an entry */
1997                 DEBUG(3,("Adding new user\n"));
1998                 ldap_op = LDAP_MOD_ADD;
1999                 if (username[strlen(username)-1] == '$') {
2000                         slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
2001                 } else {
2002                         slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
2003                 }
2004         }
2005
2006         ldap_msgfree(result);
2007
2008         if (!init_ldap_from_sam(ldap_state, &mods, ldap_op, True, newpwd)) {
2009                 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
2010                 ldap_mods_free(mods, 1);
2011                 return NT_STATUS_UNSUCCESSFUL;          
2012         }
2013         
2014         if (mods == NULL) {
2015                 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
2016                 return NT_STATUS_UNSUCCESSFUL;
2017         }
2018         
2019         make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
2020
2021         ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, True);
2022         if (NT_STATUS_IS_ERR(ret)) {
2023                 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
2024                          pdb_get_username(newpwd),dn));
2025                 ldap_mods_free(mods,1);
2026                 return ret;
2027         }
2028
2029         DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
2030         ldap_mods_free(mods, 1);
2031         return NT_STATUS_OK;
2032 }
2033
2034 static void free_private_data(void **vp) 
2035 {
2036         struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
2037
2038         ldapsam_close(*ldap_state);
2039
2040         if ((*ldap_state)->bind_secret) {
2041                 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
2042         }
2043
2044         ldapsam_close(*ldap_state);
2045                 
2046         SAFE_FREE((*ldap_state)->bind_dn);
2047         SAFE_FREE((*ldap_state)->bind_secret);
2048
2049         *ldap_state = NULL;
2050
2051         /* No need to free any further, as it is talloc()ed */
2052 }
2053
2054 static const char *group_attr[] = {"gid", "ntSid", "ntGroupType",
2055                                    "gidNumber",
2056                                    "displayName", "description",
2057                                    NULL };
2058                                    
2059 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
2060                                      const char *filter,
2061                                      LDAPMessage ** result)
2062 {
2063         int scope = LDAP_SCOPE_SUBTREE;
2064         int rc;
2065
2066         DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
2067
2068         rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope,
2069                             filter, group_attr, 0, result);
2070
2071         if (rc != LDAP_SUCCESS) {
2072                 DEBUG(0, ("ldapsam_search_one_group: "
2073                           "Problem during the LDAP search: %s\n",
2074                           ldap_err2string(rc)));
2075                 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
2076                           lp_ldap_suffix(), filter));
2077         }
2078
2079         return rc;
2080 }
2081
2082 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
2083                                  GROUP_MAP *map, LDAPMessage *entry)
2084 {
2085         pstring temp;
2086
2087         if (ldap_state == NULL || map == NULL || entry == NULL ||
2088             ldap_state->ldap_struct == NULL) {
2089                 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
2090                 return False;
2091         }
2092
2093         if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber",
2094                                   temp)) {
2095                 DEBUG(0, ("Mandatory attribute gidNumber not found\n"));
2096                 return False;
2097         }
2098         DEBUG(2, ("Entry found for group: %s\n", temp));
2099
2100         map->gid = (uint32)atol(temp);
2101
2102         if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntSid",
2103                                   temp)) {
2104                 DEBUG(0, ("Mandatory attribute ntSid not found\n"));
2105                 return False;
2106         }
2107         string_to_sid(&map->sid, temp);
2108
2109         if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntGroupType",
2110                                   temp)) {
2111                 DEBUG(0, ("Mandatory attribute ntGroupType not found\n"));
2112                 return False;
2113         }
2114         map->sid_name_use = (uint32)atol(temp);
2115
2116         if ((map->sid_name_use < SID_NAME_USER) ||
2117             (map->sid_name_use > SID_NAME_UNKNOWN)) {
2118                 DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use));
2119                 return False;
2120         }
2121
2122         if (!get_single_attribute(ldap_state->ldap_struct, entry, "displayName",
2123                                   temp)) {
2124                 DEBUG(3, ("Attribute displayName not found\n"));
2125                 temp[0] = '\0';
2126         }
2127         fstrcpy(map->nt_name, temp);
2128
2129         if (!get_single_attribute(ldap_state->ldap_struct, entry, "description",
2130                                   temp)) {
2131                 DEBUG(3, ("Attribute description not found\n"));
2132                 temp[0] = '\0';
2133         }
2134         fstrcpy(map->comment, temp);
2135
2136         map->systemaccount = 0;
2137         init_privilege(&map->priv_set);
2138
2139         return True;
2140 }
2141
2142 static BOOL init_ldap_from_group(struct ldapsam_privates *ldap_state,
2143                                  LDAPMod ***mods, int ldap_op,
2144                                  const GROUP_MAP *map)
2145 {
2146         pstring tmp;
2147
2148         if (mods == NULL || map == NULL) {
2149                 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
2150                 return False;
2151         }
2152
2153         *mods = NULL;
2154
2155         sid_to_string(tmp, &map->sid);
2156         make_a_mod(mods, ldap_op, "ntSid", tmp);
2157
2158         snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use);
2159         make_a_mod(mods, ldap_op, "ntGroupType", tmp);
2160
2161         make_a_mod(mods, ldap_op, "displayName", map->nt_name);
2162         make_a_mod(mods, ldap_op, "description", map->comment);
2163
2164         return True;
2165 }
2166
2167 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
2168                                  const char *filter,
2169                                  GROUP_MAP *map)
2170 {
2171         struct ldapsam_privates *ldap_state =
2172                 (struct ldapsam_privates *)methods->private_data;
2173         LDAPMessage *result;
2174         LDAPMessage *entry;
2175         int count;
2176
2177         if (ldapsam_search_one_group(ldap_state, filter, &result)
2178             != LDAP_SUCCESS) {
2179                 return NT_STATUS_NO_SUCH_GROUP;
2180         }
2181
2182         count = ldap_count_entries(ldap_state->ldap_struct, result);
2183
2184         if (count < 1) {
2185                 DEBUG(4, ("Did not find group for filter %s\n", filter));
2186                 return NT_STATUS_NO_SUCH_GROUP;
2187         }
2188
2189         if (count > 1) {
2190                 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
2191                           filter, count));
2192                 return NT_STATUS_NO_SUCH_GROUP;
2193         }
2194
2195         entry = ldap_first_entry(ldap_state->ldap_struct, result);
2196
2197         if (!entry) {
2198                 ldap_msgfree(result);
2199                 return NT_STATUS_UNSUCCESSFUL;
2200         }
2201
2202         if (!init_group_from_ldap(ldap_state, map, entry)) {
2203                 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
2204                           filter));
2205                 ldap_msgfree(result);
2206                 return NT_STATUS_NO_SUCH_GROUP;
2207         }
2208
2209         ldap_msgfree(result);
2210         return NT_STATUS_OK;
2211 }
2212
2213 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
2214                                  DOM_SID sid, BOOL with_priv)
2215 {
2216         pstring filter;
2217
2218         snprintf(filter, sizeof(filter)-1,
2219                  "(&(objectClass=sambaGroupMapping)(ntSid=%s))",
2220                  sid_string_static(&sid));
2221
2222         return ldapsam_getgroup(methods, filter, map);
2223 }
2224
2225 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
2226                                  gid_t gid, BOOL with_priv)
2227 {
2228         pstring filter;
2229
2230         snprintf(filter, sizeof(filter)-1,
2231                  "(&(objectClass=sambaGroupMapping)(gidNumber=%d))",
2232                  gid);
2233
2234         return ldapsam_getgroup(methods, filter, map);
2235 }
2236
2237 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
2238                                  char *name, BOOL with_priv)
2239 {
2240         pstring filter;
2241
2242         /* TODO: Escaping of name? */
2243
2244         snprintf(filter, sizeof(filter)-1,
2245                  "(&(objectClass=sambaGroupMapping)(displayName=%s))",
2246                  name);
2247
2248         return ldapsam_getgroup(methods, filter, map);
2249 }
2250
2251 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
2252                                            gid_t gid,
2253                                            LDAPMessage **result)
2254 {
2255         pstring filter;
2256
2257         snprintf(filter, sizeof(filter)-1,
2258                  "(&(objectClass=posixGroup)(gidNumber=%i))", gid);
2259
2260         return ldapsam_search_one_group(ldap_state, filter, result);
2261 }
2262
2263 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
2264                                                 GROUP_MAP *map)
2265 {
2266         struct ldapsam_privates *ldap_state =
2267                 (struct ldapsam_privates *)methods->private_data;
2268         LDAPMessage *result = NULL;
2269         LDAPMod **mods = NULL;
2270
2271         char *tmp;
2272         pstring dn;
2273         LDAPMessage *entry;
2274
2275         GROUP_MAP dummy;
2276
2277         int rc;
2278
2279         if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
2280                                              map->gid, False))) {
2281                 DEBUG(0, ("Group %i already exists in LDAP\n", map->gid));
2282                 return NT_STATUS_UNSUCCESSFUL;
2283         }
2284
2285         rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2286         if (rc != LDAP_SUCCESS) {
2287                 return NT_STATUS_UNSUCCESSFUL;
2288         }
2289
2290         if (ldap_count_entries(ldap_state->ldap_struct, result) != 1) {
2291                 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
2292                           map->gid));
2293                 ldap_msgfree(result);
2294                 return NT_STATUS_UNSUCCESSFUL;
2295         }
2296
2297         entry = ldap_first_entry(ldap_state->ldap_struct, result);
2298         tmp = ldap_get_dn(ldap_state->ldap_struct, entry);
2299         pstrcpy(dn, tmp);
2300         ldap_memfree(tmp);
2301         ldap_msgfree(result);
2302
2303         if (!init_ldap_from_group(ldap_state, &mods, LDAP_MOD_ADD, map)) {
2304                 DEBUG(0, ("init_ldap_from_group failed!\n"));
2305                 ldap_mods_free(mods, 1);
2306                 return NT_STATUS_UNSUCCESSFUL;
2307         }
2308
2309         if (mods == NULL) {
2310                 DEBUG(0, ("mods is empty\n"));
2311                 return NT_STATUS_UNSUCCESSFUL;
2312         }
2313
2314         make_a_mod(&mods, LDAP_MOD_ADD, "objectClass",
2315                    "sambaGroupMapping");
2316
2317         rc = ldapsam_modify(ldap_state, dn, mods);
2318         ldap_mods_free(mods, 1);
2319
2320         if (rc != LDAP_SUCCESS) {
2321                 DEBUG(0, ("failed to modify group %i\n", map->gid));
2322                 return NT_STATUS_UNSUCCESSFUL;
2323         }
2324
2325         DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2326         return NT_STATUS_OK;
2327 }
2328
2329 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
2330                                                    GROUP_MAP *map)
2331 {
2332         struct ldapsam_privates *ldap_state =
2333                 (struct ldapsam_privates *)methods->private_data;
2334         int rc;
2335         char *dn;
2336         LDAPMessage *result;
2337         LDAPMessage *entry;
2338         LDAPMod **mods;
2339
2340         if (!init_ldap_from_group(ldap_state, &mods, LDAP_MOD_REPLACE, map)) {
2341                 DEBUG(0, ("init_ldap_from_group failed\n"));
2342                 return NT_STATUS_UNSUCCESSFUL;
2343         }
2344
2345         if (mods == NULL) {
2346                 DEBUG(4, ("mods is empty: nothing to do\n"));
2347                 return NT_STATUS_UNSUCCESSFUL;
2348         }
2349
2350         rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2351
2352         if (rc != LDAP_SUCCESS) {
2353                 ldap_mods_free(mods, 1);
2354                 return NT_STATUS_UNSUCCESSFUL;
2355         }
2356
2357         if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2358                 DEBUG(0, ("No group to modify!\n"));
2359                 ldap_msgfree(result);
2360                 ldap_mods_free(mods, 1);
2361                 return NT_STATUS_UNSUCCESSFUL;
2362         }
2363
2364         entry = ldap_first_entry(ldap_state->ldap_struct, result);
2365         dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2366         ldap_msgfree(result);
2367
2368         rc = ldapsam_modify(ldap_state, dn, mods);
2369
2370         ldap_mods_free(mods, 1);
2371
2372         if (rc != LDAP_SUCCESS) {
2373                 DEBUG(0, ("failed to modify group %i\n", map->gid));
2374         }
2375
2376         DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2377         return NT_STATUS_OK;
2378 }
2379
2380 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
2381                                                    DOM_SID sid)
2382 {
2383         struct ldapsam_privates *ldap_state =
2384                 (struct ldapsam_privates *)methods->private_data;
2385         pstring sidstring, filter;
2386         LDAPMessage *result;
2387         int rc;
2388         NTSTATUS ret;
2389
2390         const char *sam_group_attrs[] = { "ntSid", "ntGroupType",
2391                                           "description", "displayName",
2392                                           NULL };
2393         sid_to_string(sidstring, &sid);
2394         snprintf(filter, sizeof(filter)-1,
2395                  "(&(objectClass=sambaGroupMapping)(ntSid=%s))", sidstring);
2396
2397         rc = ldapsam_search_one_group(ldap_state, filter, &result);
2398
2399         if (rc != LDAP_SUCCESS) {
2400                 return NT_STATUS_NO_SUCH_GROUP;
2401         }
2402
2403         ret = ldapsam_delete_entry(ldap_state, result, "sambaGroupMapping",
2404                                    sam_group_attrs);
2405         ldap_msgfree(result);
2406         return ret;
2407 }
2408
2409 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
2410                                     BOOL update)
2411 {
2412         struct ldapsam_privates *ldap_state =
2413                 (struct ldapsam_privates *)my_methods->private_data;
2414         const char *filter = "(objectClass=sambaGroupMapping)";
2415         int rc;
2416
2417         rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
2418                             LDAP_SCOPE_SUBTREE, filter,
2419                             group_attr, 0, &ldap_state->result);
2420
2421         if (rc != LDAP_SUCCESS) {
2422                 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2423                 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
2424                 ldap_msgfree(ldap_state->result);
2425                 ldap_state->result = NULL;
2426                 return NT_STATUS_UNSUCCESSFUL;
2427         }
2428
2429         DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2430                   ldap_count_entries(ldap_state->ldap_struct,
2431                                      ldap_state->result)));
2432
2433         ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
2434                                  ldap_state->result);
2435         ldap_state->index = 0;
2436
2437         return NT_STATUS_OK;
2438 }
2439
2440 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
2441 {
2442         ldapsam_endsampwent(my_methods);
2443 }
2444
2445 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
2446                                     GROUP_MAP *map)
2447 {
2448         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2449         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2450         BOOL bret = False;
2451
2452         /* The rebind proc needs this *HACK*.  We are not multithreaded, so
2453            this will work, but it's not nice. */
2454         static_ldap_state = ldap_state;
2455
2456         while (!bret) {
2457                 if (!ldap_state->entry)
2458                         return ret;
2459                 
2460                 ldap_state->index++;
2461                 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
2462                 
2463                 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
2464                                             ldap_state->entry); 
2465         }
2466
2467         return NT_STATUS_OK;
2468 }
2469
2470 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
2471                                            enum SID_NAME_USE sid_name_use,
2472                                            GROUP_MAP **rmap, int *num_entries,
2473                                            BOOL unix_only, BOOL with_priv)
2474 {
2475         GROUP_MAP map;
2476         GROUP_MAP *mapt;
2477         int entries = 0;
2478         NTSTATUS nt_status;
2479
2480         *num_entries = 0;
2481         *rmap = NULL;
2482
2483         if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
2484                 DEBUG(0, ("Unable to open passdb\n"));
2485                 return NT_STATUS_ACCESS_DENIED;
2486         }
2487
2488         while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) {
2489                 if (sid_name_use != SID_NAME_UNKNOWN &&
2490                     sid_name_use != map.sid_name_use) {
2491                         DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
2492                         continue;
2493                 }
2494                 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
2495                         DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
2496                         continue;
2497                 }
2498
2499                 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
2500                 if (!mapt) {
2501                         DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
2502                         SAFE_FREE(*rmap);
2503                         return NT_STATUS_UNSUCCESSFUL;
2504                 }
2505                 else
2506                         (*rmap) = mapt;
2507
2508                 mapt[entries] = map;
2509
2510                 entries += 1;
2511
2512         }
2513         ldapsam_endsamgrent(methods);
2514
2515         *num_entries = entries;
2516
2517         return NT_STATUS_OK;
2518 }
2519
2520 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2521 {
2522         NTSTATUS nt_status;
2523         struct ldapsam_privates *ldap_state;
2524
2525         if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
2526                 return nt_status;
2527         }
2528
2529         (*pdb_method)->name = "ldapsam";
2530
2531         (*pdb_method)->setsampwent = ldapsam_setsampwent;
2532         (*pdb_method)->endsampwent = ldapsam_endsampwent;
2533         (*pdb_method)->getsampwent = ldapsam_getsampwent;
2534         (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
2535         (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
2536         (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
2537         (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
2538         (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
2539
2540         (*pdb_method)->getgrsid = ldapsam_getgrsid;
2541         (*pdb_method)->getgrgid = ldapsam_getgrgid;
2542         (*pdb_method)->getgrnam = ldapsam_getgrnam;
2543         (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
2544         (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
2545         (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
2546         (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
2547
2548         /* TODO: Setup private data and free */
2549
2550         ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
2551
2552         if (!ldap_state) {
2553                 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
2554                 return NT_STATUS_NO_MEMORY;
2555         }
2556
2557         if (location) {
2558                 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
2559 #ifdef WITH_LDAP_SAMCONFIG
2560         } else {
2561                 int ldap_port = lp_ldap_port();
2562                         
2563                 /* remap default port if not using SSL (ie clear or TLS) */
2564                 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
2565                         ldap_port = 389;
2566                 }
2567
2568                 ldap_state->uri = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port);
2569                 if (!ldap_state->uri) {
2570                         return NT_STATUS_NO_MEMORY;
2571                 }
2572 #else
2573         } else {
2574                 ldap_state->uri = "ldap://localhost";
2575 #endif
2576         }
2577
2578         (*pdb_method)->private_data = ldap_state;
2579
2580         (*pdb_method)->free_private_data = free_private_data;
2581
2582         return NT_STATUS_OK;
2583 }
2584
2585 NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
2586 {
2587         NTSTATUS nt_status;
2588         struct ldapsam_privates *ldap_state;
2589         uint32 low_nua_uid, high_nua_uid;
2590
2591         if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) {
2592                 return nt_status;
2593         }
2594
2595         (*pdb_method)->name = "ldapsam_nua";
2596
2597         ldap_state = (*pdb_method)->private_data;
2598         
2599         ldap_state->permit_non_unix_accounts = True;
2600
2601         if (!lp_non_unix_account_range(&low_nua_uid, &high_nua_uid)) {
2602                 DEBUG(0, ("cannot use ldapsam_nua without 'non unix account range' in smb.conf!\n"));
2603                 return NT_STATUS_UNSUCCESSFUL;
2604         }
2605
2606         ldap_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid);
2607
2608         ldap_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid);
2609
2610         return NT_STATUS_OK;
2611 }
2612
2613 int pdb_ldap_init(void)
2614 {
2615         smb_register_passdb("ldapsam", pdb_init_ldapsam, PASSDB_INTERFACE_VERSION);
2616         smb_register_passdb("ldapsam_nua", pdb_init_ldapsam_nua, PASSDB_INTERFACE_VERSION);
2617         return True;
2618 }