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