Merge Samba 3.0 pdb_ldap from 3.0 into HEAD, so as to allow idra to continue
[tprouty/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 LDAP_OPT_SUCCESS
55 #define LDAP_OPT_SUCCESS 0
56 #endif
57
58 #ifndef SAM_ACCOUNT
59 #define SAM_ACCOUNT struct sam_passwd
60 #endif
61
62 struct ldapsam_privates {
63         /* Former statics */
64         LDAP *ldap_struct;
65         LDAPMessage *result;
66         LDAPMessage *entry;
67         int index;
68         
69         time_t last_ping;
70         /* retrive-once info */
71         const char *uri;
72         const char *domain_name;
73         DOM_SID domain_sid;
74         
75         /* configuration items */
76         BOOL use_ntsid;
77
78         BOOL permit_non_unix_accounts;
79         
80         uint32 low_allocated_user_rid; 
81         uint32 high_allocated_user_rid; 
82
83         uint32 low_allocated_group_rid; 
84         uint32 high_allocated_group_rid; 
85
86         char *bind_dn;
87         char *bind_secret;
88
89         unsigned int num_failures;
90 };
91
92 #define LDAPSAM_DONT_PING_TIME 10       /* ping only all 10 seconds */
93
94 static struct ldapsam_privates *static_ldap_state;
95
96 /*******************************************************************
97  find the ldap password
98 ******************************************************************/
99 static BOOL fetch_ldapsam_pw(char **dn, char** pw)
100 {
101         char *key = NULL;
102         size_t size;
103         
104         *dn = smb_xstrdup(lp_ldap_admin_dn());
105         
106         if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
107                 SAFE_FREE(*dn);
108                 DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n"));
109         }
110         
111         *pw=secrets_fetch(key, &size);
112         SAFE_FREE(key);
113
114         if (!size) {
115                 /* Upgrade 2.2 style entry */
116                 char *p;
117                 char* old_style_key = strdup(*dn);
118                 char *data;
119                 fstring old_style_pw;
120                 
121                 if (!old_style_key) {
122                         DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n"));
123                         return False;
124                 }
125
126                 for (p=old_style_key; *p; p++)
127                         if (*p == ',') *p = '/';
128         
129                 data=secrets_fetch(old_style_key, &size);
130                 if (!size && size < sizeof(old_style_pw)) {
131                         DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
132                         SAFE_FREE(old_style_key);
133                         SAFE_FREE(*dn);
134                         return False;
135                 }
136
137                 strncpy(old_style_pw, data, size);
138                 old_style_pw[size] = 0;
139
140                 SAFE_FREE(data);
141
142                 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
143                         DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
144                         SAFE_FREE(old_style_key);
145                         SAFE_FREE(*dn);
146                         return False;                   
147                 }
148                 if (!secrets_delete(old_style_key)) {
149                         DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
150                 }
151
152                 SAFE_FREE(old_style_key);
153
154                 *pw = smb_xstrdup(old_style_pw);                
155         }
156         
157         return True;
158 }
159
160 static const char *attr[] = {"uid", "pwdLastSet", "logonTime",
161                              "logoffTime", "kickoffTime", "cn",
162                              "pwdCanChange", "pwdMustChange",
163                              "displayName", "homeDrive",
164                              "smbHome", "scriptPath",
165                              "profilePath", "description",
166                              "userWorkstations", "rid", "ntSid",
167                              "primaryGroupID", "lmPassword",
168                              "ntPassword", "acctFlags",
169                              "domain", "objectClass", 
170                              "uidNumber", "gidNumber", 
171                              "homeDirectory", NULL };
172
173 static const char *domain_info_attrs[] = {"domain", "nextUserRid", 
174                                           "nextGroupRid", "ntSid", NULL };
175
176 /*******************************************************************
177  open a connection to the ldap server.
178 ******************************************************************/
179 static int ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct)
180 {
181         int rc = LDAP_SUCCESS;
182         int version;
183         BOOL ldap_v3 = False;
184
185 #ifdef HAVE_LDAP_INITIALIZE
186         DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
187         
188         if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) {
189                 DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
190                 return rc;
191         }
192         
193 #else 
194
195         /* Parse the string manually */
196
197         {
198                 int port = 0;
199                 fstring protocol;
200                 fstring host;
201                 const char *p = ldap_state->uri; 
202                 SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
203                 
204                 /* skip leading "URL:" (if any) */
205                 if ( strncasecmp( p, "URL:", 4 ) == 0 ) {
206                         p += 4;
207                 }
208                 
209                 sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port);
210                 
211                 if (port == 0) {
212                         if (strequal(protocol, "ldap")) {
213                                 port = LDAP_PORT;
214                         } else if (strequal(protocol, "ldaps")) {
215                                 port = LDAPS_PORT;
216                         } else {
217                                 DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
218                         }
219                 }
220                 
221                 if ((*ldap_struct = ldap_init(host, port)) == NULL)     {
222                         DEBUG(0, ("ldap_init failed !\n"));
223                         return LDAP_OPERATIONS_ERROR;
224                 }
225                 
226                 if (strequal(protocol, "ldaps")) {
227 #ifdef LDAP_OPT_X_TLS
228                         int tls = LDAP_OPT_X_TLS_HARD;
229                         if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS)
230                         {
231                                 DEBUG(0, ("Failed to setup a TLS session\n"));
232                         }
233                         
234                         DEBUG(3,("LDAPS option set...!\n"));
235 #else
236                         DEBUG(0,("ldapsam_open_connection: Secure connection not supported by LDAP client libraries!\n"));
237                         return LDAP_OPERATIONS_ERROR;
238 #endif
239                 }
240         }
241 #endif
242
243         if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
244         {
245                 if (version != LDAP_VERSION3)
246                 {
247                         version = LDAP_VERSION3;
248                         if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
249                                 ldap_v3 = True;
250                         }
251                 } else {
252                         ldap_v3 = True;
253                 }
254         }
255
256         if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
257 #ifdef LDAP_OPT_X_TLS
258                 if (ldap_v3) {
259                         if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
260                         {
261                                 DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
262                                          ldap_err2string(rc)));
263                                 return rc;
264                         }
265                         DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
266                 } else {
267                         
268                         DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
269                         return LDAP_OPERATIONS_ERROR;
270                 }
271 #else
272                 DEBUG(0,("ldapsam_open_connection: StartTLS not supported by LDAP client libraries!\n"));
273                 return LDAP_OPERATIONS_ERROR;
274 #endif
275         }
276
277         DEBUG(2, ("ldapsam_open_connection: connection opened\n"));
278         return rc;
279 }
280
281
282 /*******************************************************************
283  a rebind function for authenticated referrals
284  This version takes a void* that we can shove useful stuff in :-)
285 ******************************************************************/
286 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
287 #else
288 static int rebindproc_with_state  (LDAP * ld, char **whop, char **credp, 
289                                    int *methodp, int freeit, void *arg)
290 {
291         struct ldapsam_privates *ldap_state = arg;
292         
293         /** @TODO Should we be doing something to check what servers we rebind to?
294             Could we get a referral to a machine that we don't want to give our
295             username and password to? */
296         
297         if (freeit) {
298                 SAFE_FREE(*whop);
299                 memset(*credp, '\0', strlen(*credp));
300                 SAFE_FREE(*credp);
301         } else {
302                 DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n", 
303                           ldap_state->bind_dn));
304
305                 *whop = strdup(ldap_state->bind_dn);
306                 if (!*whop) {
307                         return LDAP_NO_MEMORY;
308                 }
309                 *credp = strdup(ldap_state->bind_secret);
310                 if (!*credp) {
311                         SAFE_FREE(*whop);
312                         return LDAP_NO_MEMORY;
313                 }
314                 *methodp = LDAP_AUTH_SIMPLE;
315         }
316         return 0;
317 }
318 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
319
320 /*******************************************************************
321  a rebind function for authenticated referrals
322  This version takes a void* that we can shove useful stuff in :-)
323  and actually does the connection.
324 ******************************************************************/
325 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
326 static int rebindproc_connect_with_state (LDAP *ldap_struct, 
327                                           LDAP_CONST char *url, 
328                                           ber_tag_t request,
329                                           ber_int_t msgid, void *arg)
330 {
331         struct ldapsam_privates *ldap_state = arg;
332         int rc;
333         DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n", 
334                  ldap_state->bind_dn));
335         
336         /** @TODO Should we be doing something to check what servers we rebind to?
337             Could we get a referral to a machine that we don't want to give our
338             username and password to? */
339
340         rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
341         
342         return rc;
343 }
344 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
345
346 /*******************************************************************
347  Add a rebind function for authenticated referrals
348 ******************************************************************/
349 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
350 #else
351 # if LDAP_SET_REBIND_PROC_ARGS == 2
352 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
353                        int *method, int freeit )
354 {
355         return rebindproc_with_state(ldap_struct, whop, credp,
356                                    method, freeit, static_ldap_state);
357         
358 }
359 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
360 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
361
362 /*******************************************************************
363  a rebind function for authenticated referrals
364  this also does the connection, but no void*.
365 ******************************************************************/
366 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
367 # if LDAP_SET_REBIND_PROC_ARGS == 2
368 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
369                                ber_int_t msgid)
370 {
371         return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid, 
372                                              static_ldap_state);
373 }
374 # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
375 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
376
377 /*******************************************************************
378  connect to the ldap server under system privilege.
379 ******************************************************************/
380 static int ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
381 {
382         int rc;
383         char *ldap_dn;
384         char *ldap_secret;
385
386         /* The rebind proc needs this *HACK*.  We are not multithreaded, so
387            this will work, but it's not nice. */
388         static_ldap_state = ldap_state;
389
390         /* get the password */
391         if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
392         {
393                 DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
394                 return LDAP_INVALID_CREDENTIALS;
395         }
396
397         ldap_state->bind_dn = ldap_dn;
398         ldap_state->bind_secret = ldap_secret;
399
400         /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite 
401            (OpenLDAP) doesnt' seem to support it */
402            
403         DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n",
404                   ldap_state->uri, ldap_dn));
405
406 #if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
407 # if LDAP_SET_REBIND_PROC_ARGS == 2     
408         ldap_set_rebind_proc(ldap_struct, &rebindproc_connect); 
409 # endif
410 # if LDAP_SET_REBIND_PROC_ARGS == 3     
411         ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);  
412 # endif
413 #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
414 # if LDAP_SET_REBIND_PROC_ARGS == 2     
415         ldap_set_rebind_proc(ldap_struct, &rebindproc); 
416 # endif
417 # if LDAP_SET_REBIND_PROC_ARGS == 3     
418         ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);  
419 # endif
420 #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
421
422         rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
423
424         if (rc != LDAP_SUCCESS) {
425                 char *ld_error = NULL;
426                 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
427                                 &ld_error);
428                 DEBUG(ldap_state->num_failures ? 2 : 0,
429                       ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
430                                ldap_dn ? ld_error : "(unknown)", ldap_err2string(rc),
431                                ld_error));
432                 SAFE_FREE(ld_error);
433                 ldap_state->num_failures++;
434                 return rc;
435         }
436
437         ldap_state->num_failures = 0;
438
439         DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n"));
440         return rc;
441 }
442
443 /**********************************************************************
444 Connect to LDAP server 
445 *********************************************************************/
446 static int ldapsam_open(struct ldapsam_privates *ldap_state)
447 {
448         int rc;
449         SMB_ASSERT(ldap_state);
450                 
451 #ifndef NO_LDAP_SECURITY
452         if (geteuid() != 0) {
453                 DEBUG(0, ("ldapsam_open: cannot access LDAP when not root..\n"));
454                 return  LDAP_INSUFFICIENT_ACCESS;
455         }
456 #endif
457
458         if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + LDAPSAM_DONT_PING_TIME) < time(NULL))) {
459                 struct sockaddr_un addr;
460                 socklen_t len = sizeof(addr);
461                 int sd;
462                 if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 &&
463                     getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
464                         /* the other end has died. reopen. */
465                         ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
466                         ldap_state->ldap_struct = NULL;
467                         ldap_state->last_ping = (time_t)0;
468                 } else {
469                         ldap_state->last_ping = time(NULL);
470                 } 
471         }
472
473         if (ldap_state->ldap_struct != NULL) {
474                 DEBUG(5,("ldapsam_open: allready connected to the LDAP server\n"));
475                 return LDAP_SUCCESS;
476         }
477
478         if ((rc = ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))) {
479                 return rc;
480         }
481
482         if ((rc = ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))) {
483                 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
484                 ldap_state->ldap_struct = NULL;
485                 return rc;
486         }
487
488
489         ldap_state->last_ping = time(NULL);
490         DEBUG(4,("The LDAP server is succesful connected\n"));
491
492         return LDAP_SUCCESS;
493 }
494
495 /**********************************************************************
496 Disconnect from LDAP server 
497 *********************************************************************/
498 static NTSTATUS ldapsam_close(struct ldapsam_privates *ldap_state)
499 {
500         if (!ldap_state)
501                 return NT_STATUS_INVALID_PARAMETER;
502                 
503         if (ldap_state->ldap_struct != NULL) {
504                 ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
505                 ldap_state->ldap_struct = NULL;
506         }
507         
508         DEBUG(5,("The connection to the LDAP server was closed\n"));
509         /* maybe free the results here --metze */
510         
511         return NT_STATUS_OK;
512 }
513
514 static int ldapsam_retry_open(struct ldapsam_privates *ldap_state, int *attempts)
515 {
516         int rc;
517
518         SMB_ASSERT(ldap_state && attempts);
519                 
520         if (*attempts != 0) {
521                 unsigned int sleep_time;
522                 uint8 rand_byte = 128; /* a reasonable place to start */
523
524                 generate_random_buffer(&rand_byte, 1, False);
525
526                 sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2; 
527                 /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds
528                    on average.  
529                  */
530                 DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n", 
531                           sleep_time));
532                 msleep(sleep_time);
533         }
534         (*attempts)++;
535
536         if ((rc = ldapsam_open(ldap_state))) {
537                 DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts));
538                 return rc;
539         } 
540         
541         return LDAP_SUCCESS;            
542 }
543
544
545 static int ldapsam_search(struct ldapsam_privates *ldap_state, 
546                           const char *base, int scope, const char *filter, 
547                           const char *attrs[], int attrsonly, 
548                           LDAPMessage **res)
549 {
550         int             rc = LDAP_SERVER_DOWN;
551         int             attempts = 0;
552         char           *utf8_filter;
553
554         SMB_ASSERT(ldap_state);
555
556         if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) {
557                 return LDAP_NO_MEMORY;
558         }
559
560         while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
561                 
562                 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
563                         continue;
564                 
565                 rc = ldap_search_s(ldap_state->ldap_struct, base, scope, 
566                                    utf8_filter, (char **)attrs, attrsonly, res);
567         }
568         
569         if (rc == LDAP_SERVER_DOWN) {
570                 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
571                 ldapsam_close(ldap_state);      
572         }
573
574         SAFE_FREE(utf8_filter);
575         return rc;
576 }
577
578 static int ldapsam_modify(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[])
579 {
580         int             rc = LDAP_SERVER_DOWN;
581         int             attempts = 0;
582         char           *utf8_dn;
583
584         SMB_ASSERT(ldap_state);
585
586         if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
587                 return LDAP_NO_MEMORY;
588         }
589
590         while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
591                 
592                 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
593                         continue;
594                 
595                 rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs);
596         }
597         
598         if (rc == LDAP_SERVER_DOWN) {
599                 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
600                 ldapsam_close(ldap_state);      
601         }
602         
603         SAFE_FREE(utf8_dn);
604         return rc;
605 }
606
607 static int ldapsam_add(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[])
608 {
609         int             rc = LDAP_SERVER_DOWN;
610         int             attempts = 0;
611         char           *utf8_dn;
612         
613         SMB_ASSERT(ldap_state);
614
615         if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
616                 return LDAP_NO_MEMORY;
617         }
618
619         while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
620                 
621                 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
622                         continue;
623                 
624                 rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs);
625         }
626         
627         if (rc == LDAP_SERVER_DOWN) {
628                 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
629                 ldapsam_close(ldap_state);      
630         }
631                 
632         SAFE_FREE(utf8_dn);
633         return rc;
634 }
635
636 static int ldapsam_delete(struct ldapsam_privates *ldap_state, char *dn)
637 {
638         int             rc = LDAP_SERVER_DOWN;
639         int             attempts = 0;
640         char           *utf8_dn;
641         
642         SMB_ASSERT(ldap_state);
643
644         if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
645                 return LDAP_NO_MEMORY;
646         }
647
648         while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
649                 
650                 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
651                         continue;
652                 
653                 rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn);
654         }
655         
656         if (rc == LDAP_SERVER_DOWN) {
657                 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
658                 ldapsam_close(ldap_state);      
659         }
660                 
661         SAFE_FREE(utf8_dn);
662         return rc;
663 }
664
665 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
666 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)
667 {
668         int             rc = LDAP_SERVER_DOWN;
669         int             attempts = 0;
670         
671         if (!ldap_state)
672                 return (-1);
673
674         while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
675                 
676                 if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
677                         continue;
678                 
679                 rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap);
680         }
681         
682         if (rc == LDAP_SERVER_DOWN) {
683                 DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
684                 ldapsam_close(ldap_state);      
685         }
686                 
687         return rc;
688 }
689 #endif
690
691 /*******************************************************************
692  run the search by name.
693 ******************************************************************/
694 static int ldapsam_search_suffix (struct ldapsam_privates *ldap_state, const char *filter, const char **search_attr, LDAPMessage ** result)
695 {
696         int scope = LDAP_SCOPE_SUBTREE;
697         int rc;
698
699         DEBUG(2, ("ldapsam_search_suffix: searching for:[%s]\n", filter));
700
701         rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope, filter, search_attr, 0, result);
702
703         if (rc != LDAP_SUCCESS) {
704                 char *ld_error = NULL;
705                 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
706                                 &ld_error);
707                 DEBUG(0,("ldapsam_search_suffix: Problem during the LDAP search: %s (%s)\n", 
708                         ld_error?ld_error:"(unknown)", ldap_err2string (rc)));
709                 DEBUG(3,("ldapsam_search_suffix: Query was: %s, %s\n", lp_ldap_suffix(), 
710                         filter));
711                 SAFE_FREE(ld_error);
712         }
713         
714         return rc;
715 }
716
717 /*******************************************************************
718  run the search by name.
719 ******************************************************************/
720 static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state, const char *user,
721                              LDAPMessage ** result)
722 {
723         pstring filter;
724         char *escape_user = escape_ldap_string_alloc(user);
725
726         if (!escape_user) {
727                 return LDAP_NO_MEMORY;
728         }
729
730         /*
731          * in the filter expression, replace %u with the real name
732          * so in ldap filter, %u MUST exist :-)
733          */
734         pstrcpy(filter, lp_ldap_filter());
735
736         /* 
737          * have to use this here because $ is filtered out
738            * in pstring_sub
739          */
740         
741
742         all_string_sub(filter, "%u", escape_user, sizeof(pstring));
743         SAFE_FREE(escape_user);
744
745         return ldapsam_search_suffix(ldap_state, filter, attr, result);
746 }
747
748 /*******************************************************************
749  run the search by rid.
750 ******************************************************************/
751 static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state, 
752                                            uint32 rid,
753                                            LDAPMessage ** result)
754 {
755         pstring filter;
756         int rc;
757
758         /* check if the user rid exsists, if not, try searching on the uid */
759         
760         snprintf(filter, sizeof(filter) - 1, "rid=%i", rid);
761         rc = ldapsam_search_suffix(ldap_state, filter, attr, result);
762         
763         return rc;
764 }
765
766 /*******************************************************************
767  run the search by SID.
768 ******************************************************************/
769 static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state, 
770                                            const DOM_SID *sid,
771                                            LDAPMessage ** result)
772 {
773         pstring filter;
774         int rc;
775         fstring sid_string;
776
777         /* check if the user rid exsists, if not, try searching on the uid */
778
779         snprintf(filter, sizeof(filter) - 1, "ntSid=%s", sid_to_string(sid_string, sid));
780         rc = ldapsam_search_suffix(ldap_state, filter, attr, result);
781         
782         return rc;
783 }
784
785 /*******************************************************************
786 search an attribute and return the first value found.
787 ******************************************************************/
788 static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry,
789                                   const char *attribute, pstring value)
790 {
791         char **values;
792         value[0] = '\0';
793
794         if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
795                 DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute));
796                 
797                 return False;
798         }
799         
800         if (convert_string(CH_UTF8, CH_UNIX,
801                 values[0], -1,
802                 value, sizeof(pstring)) == (size_t)-1)
803         {
804                 DEBUG(1, ("get_single_attribute: string conversion of [%s] = [%s] failed!\n", 
805                           attribute, values[0]));
806                 ldap_value_free(values);
807                 return False;
808         }
809         
810         ldap_value_free(values);
811 #ifdef DEBUG_PASSWORDS
812         DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value));
813 #endif  
814         return True;
815 }
816
817 /************************************************************************
818 Routine to manage the LDAPMod structure array
819 manage memory used by the array, by each struct, and values
820
821 ************************************************************************/
822 static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
823 {
824         LDAPMod **mods;
825         int i;
826         int j;
827
828         mods = *modlist;
829
830         if (attribute == NULL || *attribute == '\0')
831                 return;
832
833 #if 0
834         /* Why do we need this??? -- vl */
835         if (value == NULL || *value == '\0')
836                 return;
837 #endif
838
839         if (mods == NULL) 
840         {
841                 mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
842                 if (mods == NULL)
843                 {
844                         DEBUG(0, ("make_a_mod: out of memory!\n"));
845                         return;
846                 }
847                 mods[0] = NULL;
848         }
849
850         for (i = 0; mods[i] != NULL; ++i) {
851                 if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute))
852                         break;
853         }
854
855         if (mods[i] == NULL)
856         {
857                 mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
858                 if (mods == NULL)
859                 {
860                         DEBUG(0, ("make_a_mod: out of memory!\n"));
861                         return;
862                 }
863                 mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
864                 if (mods[i] == NULL)
865                 {
866                         DEBUG(0, ("make_a_mod: out of memory!\n"));
867                         return;
868                 }
869                 mods[i]->mod_op = modop;
870                 mods[i]->mod_values = NULL;
871                 mods[i]->mod_type = strdup(attribute);
872                 mods[i + 1] = NULL;
873         }
874
875         if (value != NULL)
876         {
877                 char *utf8_value = NULL;
878
879                 j = 0;
880                 if (mods[i]->mod_values != NULL) {
881                         for (; mods[i]->mod_values[j] != NULL; j++);
882                 }
883                 mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
884                                                (j + 2) * sizeof (char *));
885                                                
886                 if (mods[i]->mod_values == NULL) {
887                         DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
888                         return;
889                 }
890
891                 if (push_utf8_allocate(&utf8_value, value) == (size_t)-1) {
892                         DEBUG (0, ("make_a_mod: String conversion failure!\n"));
893                         return;
894                 }
895
896                 mods[i]->mod_values[j] = utf8_value;
897
898                 mods[i]->mod_values[j + 1] = NULL;
899         }
900         *modlist = mods;
901 }
902
903 /**********************************************************************
904   Set attribute to newval in LDAP, regardless of what value the
905   attribute had in LDAP before.
906 *********************************************************************/
907 static void make_ldap_mod(LDAP *ldap_struct, LDAPMessage *existing,
908                           LDAPMod ***mods,
909                           const char *attribute, const char *newval)
910 {
911         char **values = NULL;
912
913         if (existing != NULL) {
914                 values = ldap_get_values(ldap_struct, existing, attribute);
915         }
916
917         if ((values != NULL) && (values[0] != NULL) &&
918             strcmp(values[0], newval) == 0) {
919                 
920                 /* Believe it or not, but LDAP will deny a delete and
921                    an add at the same time if the values are the
922                    same... */
923
924                 ldap_value_free(values);
925                 return;
926         }
927
928         /* Regardless of the real operation (add or modify)
929            we add the new value here. We rely on deleting
930            the old value, should it exist. */
931
932         if ((newval != NULL) && (strlen(newval) > 0)) {
933                 make_a_mod(mods, LDAP_MOD_ADD, attribute, newval);
934         }
935
936         if (values == NULL) {
937                 /* There has been no value before, so don't delete it.
938                    Here's a possible race: We might end up with
939                    duplicate attributes */
940                 return;
941         }
942
943         /* By deleting exactly the value we found in the entry this
944            should be race-free in the sense that the LDAP-Server will
945            deny the complete operation if somebody changed the
946            attribute behind our back. */
947
948         make_a_mod(mods, LDAP_MOD_DELETE, attribute, values[0]);
949         ldap_value_free(values);
950 }
951
952 /*******************************************************************
953  Delete complete object or objectclass and attrs from
954  object found in search_result depending on lp_ldap_delete_dn
955 ******************************************************************/
956 static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
957                                      LDAPMessage *result,
958                                      const char *objectclass,
959                                      const char **attrs)
960 {
961         int rc;
962         LDAPMessage *entry;
963         LDAPMod **mods = NULL;
964         char *name, *dn;
965         BerElement *ptr = NULL;
966
967         rc = ldap_count_entries(ldap_state->ldap_struct, result);
968
969         if (rc != 1) {
970                 DEBUG(0, ("Entry must exist exactly once!\n"));
971                 return NT_STATUS_UNSUCCESSFUL;
972         }
973
974         entry = ldap_first_entry(ldap_state->ldap_struct, result);
975         dn    = ldap_get_dn(ldap_state->ldap_struct, entry);
976
977         if (lp_ldap_delete_dn()) {
978                 NTSTATUS ret = NT_STATUS_OK;
979                 rc = ldapsam_delete(ldap_state, dn);
980
981                 if (rc != LDAP_SUCCESS) {
982                         DEBUG(0, ("Could not delete object %s\n", dn));
983                         ret = NT_STATUS_UNSUCCESSFUL;
984                 }
985                 ldap_memfree(dn);
986                 return ret;
987         }
988
989         /* Ok, delete only the SAM attributes */
990
991         for (name = ldap_first_attribute(ldap_state->ldap_struct, entry, &ptr);
992              name != NULL;
993              name = ldap_next_attribute(ldap_state->ldap_struct, entry, ptr)) {
994
995                 const char **attrib;
996
997                 /* We are only allowed to delete the attributes that
998                    really exist. */
999
1000                 for (attrib = attrs; *attrib != NULL; attrib++) {
1001                         if (StrCaseCmp(*attrib, name) == 0) {
1002                                 DEBUG(10, ("deleting attribute %s\n", name));
1003                                 make_a_mod(&mods, LDAP_MOD_DELETE, name, NULL);
1004                         }
1005                 }
1006
1007                 ldap_memfree(name);
1008         }
1009
1010         if (ptr != NULL) {
1011                 ber_free(ptr, 0);
1012         }
1013         
1014         make_a_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
1015
1016         rc = ldapsam_modify(ldap_state, dn, mods);
1017         ldap_mods_free(mods, 1);
1018
1019         if (rc != LDAP_SUCCESS) {
1020                 char *ld_error = NULL;
1021                 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1022                                 &ld_error);
1023                 
1024                 DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n",
1025                           dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
1026                 SAFE_FREE(ld_error);
1027                 ldap_memfree(dn);
1028                 return NT_STATUS_UNSUCCESSFUL;
1029         }
1030
1031         ldap_memfree(dn);
1032         return NT_STATUS_OK;
1033 }
1034                                           
1035 /**********************************************************************
1036 Search for the domain info entry
1037 *********************************************************************/
1038 static int ldapsam_search_domain_info(struct ldapsam_privates *ldap_state,
1039                                       LDAPMessage ** result)
1040 {
1041         pstring filter;
1042         int rc;
1043
1044         slprintf(filter, sizeof(filter)-1,
1045                  "(&(objectClass=sambaDomain)(domain=%s))",
1046                  ldap_state->domain_name);
1047
1048         DEBUG(2, ("Searching for:[%s]\n", filter));
1049
1050         rc = ldapsam_search_suffix(ldap_state, filter,
1051                                    domain_info_attrs, result);
1052
1053         if (rc != LDAP_SUCCESS) {
1054                 DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
1055                 DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1056         }
1057         
1058         return rc;
1059 }
1060
1061 /**********************************************************************
1062  If this entry is is the 'allocated' range, extract the RID and return 
1063  it, so we can find the 'next' rid to allocate.
1064
1065  Do this, no matter what type of object holds the RID - be it a user,
1066  group or somthing else.
1067 *********************************************************************/
1068 static uint32 entry_to_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry, int rid_type) 
1069 {
1070         pstring sid_string;
1071         DOM_SID dom_sid;
1072         uint32 rid;
1073
1074         if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntSid",
1075                                   sid_string)) {
1076                 return 0;
1077         }
1078         
1079         if (!string_to_sid(&dom_sid, sid_string)) {
1080                 return 0;
1081         }
1082
1083         if (!sid_peek_check_rid(&dom_sid, get_global_sam_sid(), &rid)) {
1084                 /* not our domain, so we don't care */
1085                 return 0;
1086         }
1087
1088         switch (rid_type) {
1089         case USER_RID_TYPE:
1090                 if (rid >= ldap_state->low_allocated_user_rid && 
1091                     rid <= ldap_state->high_allocated_user_rid) {
1092                         return rid;
1093                 }
1094                 break;
1095         case GROUP_RID_TYPE:
1096                 if (rid >= ldap_state->low_allocated_group_rid && 
1097                     rid <= ldap_state->high_allocated_group_rid) {
1098                         return rid;
1099                 }
1100                 break;
1101         }
1102         return 0;
1103 }
1104
1105
1106 /**********************************************************************
1107 Connect to LDAP server and find the next available 'allocated' RID.
1108
1109 The search is done 'per type' as we allocate seperate pools for the
1110 EVEN and ODD (user and group) RIDs.  
1111
1112 This is only done once, so that we can fill out the sambaDomain.
1113 *********************************************************************/
1114 static uint32 search_next_allocated_rid(struct ldapsam_privates *ldap_state, int rid_type)
1115 {
1116         int rc;
1117         LDAPMessage *result;
1118         LDAPMessage *entry;
1119         uint32 top_rid = 0;
1120         uint32 next_rid;
1121         uint32 count;
1122         uint32 rid;
1123         const char *sid_attr[] = {"ntSid", NULL};
1124         const char *filter = "(ntSid=*)";
1125
1126         DEBUG(2, ("search_top_allocated_rid: searching for:[%s]\n", filter));
1127
1128         rc = ldapsam_search_suffix(ldap_state, filter, 
1129                                    sid_attr, &result);
1130
1131         if (rc != LDAP_SUCCESS) {
1132                 DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
1133                 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1134
1135                 result = NULL;
1136                 return 0;
1137         }
1138         
1139         count = ldap_count_entries(ldap_state->ldap_struct, result);
1140         DEBUG(2, ("search_top_allocated_rid: %d entries in the base!\n", count));
1141         
1142         if (count == 0) {
1143                 DEBUG(3, ("LDAP search returned no records, assuming no allocated RIDs present!: %s\n", ldap_err2string(rc)));
1144                 DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
1145         } else {
1146                 entry = ldap_first_entry(ldap_state->ldap_struct,result);
1147                 
1148                 top_rid = entry_to_rid(ldap_state, entry, rid_type);
1149                 
1150                 while ((entry = ldap_next_entry(ldap_state->ldap_struct, entry))) {
1151                         
1152                         rid = entry_to_rid(ldap_state, entry, rid_type);
1153                         if (((rid & ~RID_TYPE_MASK) == rid_type) && (rid > top_rid)) {
1154                                 top_rid = rid;
1155                         }
1156                 }
1157         }
1158
1159         switch (rid_type) {
1160         case USER_RID_TYPE:
1161                 if (top_rid < ldap_state->low_allocated_user_rid) {
1162                         return ldap_state->low_allocated_user_rid;
1163                 }
1164                 break;
1165         case GROUP_RID_TYPE:
1166                 if (top_rid < ldap_state->low_allocated_group_rid) 
1167                         return ldap_state->low_allocated_group_rid;
1168                 break;
1169         }
1170
1171         next_rid = (top_rid & ~RID_TYPE_MASK) + rid_type + RID_MULTIPLIER;
1172
1173         switch (rid_type) {
1174         case USER_RID_TYPE:
1175                 if (next_rid > ldap_state->high_allocated_user_rid) {
1176                         return 0;
1177                 }
1178                 break;
1179         case GROUP_RID_TYPE:
1180                 if (next_rid > ldap_state->high_allocated_group_rid) {
1181                         return 0;
1182                 }
1183                 break;
1184         }
1185         return next_rid;
1186 }
1187
1188 /**********************************************************************
1189  Add the sambaDomain to LDAP, so we don't have to search for this stuff
1190  again.  This is a once-add operation for now.
1191
1192  TODO:  Add other attributes, and allow modification.
1193 *********************************************************************/
1194 static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state) 
1195 {
1196         pstring tmp;
1197         pstring filter;
1198         LDAPMod **mods = NULL;
1199         int rc;
1200         int ldap_op;
1201         LDAPMessage *result = NULL;
1202         LDAPMessage *entry  = NULL;
1203         char *dn = NULL;
1204         int num_result;
1205
1206         uint32 next_allocated_user_rid;
1207         uint32 next_allocated_group_rid;
1208
1209         next_allocated_user_rid = search_next_allocated_rid(ldap_state, USER_RID_TYPE);
1210         if (!next_allocated_user_rid) {
1211                 return NT_STATUS_UNSUCCESSFUL;
1212         }
1213
1214         next_allocated_group_rid = search_next_allocated_rid(ldap_state, GROUP_RID_TYPE);
1215         if (!next_allocated_group_rid) {
1216                 return NT_STATUS_UNSUCCESSFUL;
1217         }
1218
1219         slprintf (filter, sizeof (filter) - 1, "domain=%s", ldap_state->domain_name);
1220         rc = ldapsam_search_suffix(ldap_state, filter, domain_info_attrs, &result);
1221         if (rc != LDAP_SUCCESS) {
1222                 return NT_STATUS_UNSUCCESSFUL;
1223         }
1224
1225         num_result = ldap_count_entries(ldap_state->ldap_struct, result);
1226         
1227         if (num_result > 1) {
1228                 DEBUG (0, ("More than domain with that name exists: bailing out!\n"));
1229                 ldap_msgfree(result);
1230                 return NT_STATUS_UNSUCCESSFUL;
1231         }
1232         
1233         /* Check if we need to update an existing entry */
1234         if (num_result == 1) {
1235                 char *tmp_dn;
1236                 
1237                 DEBUG(3,("Domain exists without samba properties: adding them\n"));
1238                 ldap_op = LDAP_MOD_REPLACE;
1239                 entry = ldap_first_entry (ldap_state->ldap_struct, result);
1240                 tmp_dn = ldap_get_dn (ldap_state->ldap_struct, entry);
1241                 asprintf (&dn, "%s", tmp_dn);
1242                 ldap_memfree (tmp_dn);
1243         } else {
1244                 /* Check if we need to add an entry */
1245                 DEBUG(3,("Adding new domain\n"));
1246                 ldap_op = LDAP_MOD_ADD;
1247                 asprintf (&dn, "domain=%s,%s", ldap_state->domain_name, lp_ldap_suffix ());
1248         }
1249
1250         /* Free original search */
1251         ldap_msgfree(result);
1252
1253         if (!dn) {
1254                 return NT_STATUS_NO_MEMORY;
1255         }
1256
1257         /* make the changes - the entry *must* not already have samba attributes */
1258         make_a_mod(&mods, LDAP_MOD_ADD, "domain", ldap_state->domain_name);
1259
1260         sid_to_string(tmp, &ldap_state->domain_sid);
1261         make_a_mod(&mods, LDAP_MOD_ADD, "ntSid", tmp);
1262
1263         snprintf(tmp, sizeof(tmp)-1, "%i", next_allocated_user_rid);
1264         make_a_mod(&mods, LDAP_MOD_ADD, "nextUserRid", tmp);
1265
1266         snprintf(tmp, sizeof(tmp)-1, "%i", next_allocated_group_rid);
1267         make_a_mod(&mods, LDAP_MOD_ADD, "nextGroupRid", tmp);
1268
1269         make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaDomain");
1270
1271         switch(ldap_op)
1272         {
1273         case LDAP_MOD_ADD: 
1274                 rc = ldapsam_add(ldap_state, dn, mods);
1275                 break;
1276         case LDAP_MOD_REPLACE: 
1277                 rc = ldapsam_modify(ldap_state, dn, mods);
1278                 break;
1279         default:        
1280                 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
1281                 return NT_STATUS_INVALID_PARAMETER;
1282         }
1283         
1284         if (rc!=LDAP_SUCCESS) {
1285                 char *ld_error = NULL;
1286                 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
1287                                 &ld_error);
1288                 DEBUG(1,
1289                       ("failed to %s domain dn= %s with: %s\n\t%s\n",
1290                        ldap_op == LDAP_MOD_ADD ? "add" : "modify",
1291                        dn, ldap_err2string(rc),
1292                        ld_error?ld_error:"unknown"));
1293                 SAFE_FREE(ld_error);
1294
1295                 ldap_mods_free(mods,1);
1296                 return NT_STATUS_UNSUCCESSFUL;
1297         }
1298
1299         DEBUG(2,("added: domain = %s in the LDAP database\n", ldap_state->domain_name));
1300         ldap_mods_free(mods, 1);
1301         return NT_STATUS_OK;
1302 }
1303
1304 /**********************************************************************
1305  Even if the sambaAccount attribute in LDAP tells us that this RID is 
1306  safe to use, always check before use.  
1307 *********************************************************************/
1308 static BOOL sid_in_use(struct ldapsam_privates *ldap_state, 
1309                        const DOM_SID *sid, int *error) 
1310 {
1311         pstring filter;
1312         fstring sid_string;
1313         LDAPMessage *result = NULL;
1314         int count;
1315         int rc;
1316         const char *sid_attr[] = {"ntSid", NULL};
1317
1318         slprintf(filter, sizeof(filter)-1, "(ntSid=%s)", sid_to_string(sid_string, sid));
1319
1320         rc = ldapsam_search_suffix(ldap_state, filter, sid_attr, &result);
1321
1322         if (rc != LDAP_SUCCESS) {
1323                 char *ld_error = NULL;
1324                 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1325                 DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n", 
1326                           sid_string, ld_error));
1327                 SAFE_FREE(ld_error);
1328
1329                 *error = rc;
1330                 return True;
1331         }
1332         
1333         if ((count = ldap_count_entries(ldap_state->ldap_struct, result)) > 0) {
1334                 DEBUG(3, ("Sid %s already in use - trying next RID\n",
1335                           sid_string));
1336                 ldap_msgfree(result);
1337                 return True;
1338         }
1339
1340         ldap_msgfree(result);
1341
1342         /* good, sid is not in use */
1343         return False;
1344 }
1345
1346 /**********************************************************************
1347  Set the new nextRid attribute, and return one we can use.
1348
1349  This also checks that this RID is actually free - in case the admin
1350  manually stole it :-).
1351 *********************************************************************/
1352 static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *rid, int rid_type)
1353 {
1354         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
1355         int rc;
1356         LDAPMessage *result = NULL;
1357         LDAPMessage *entry  = NULL;
1358         char *dn;
1359         LDAPMod **mods = NULL;
1360         int count;
1361         fstring old_rid_string;
1362         fstring next_rid_string;
1363         uint32 next_rid;
1364         int attempts = 0;
1365
1366         if (!ldap_state->use_ntsid) {
1367                 DEBUG(0, ("Allocated RIDs require 'ldap use ntSid' to be set in smb.conf\n"));
1368                 return NT_STATUS_UNSUCCESSFUL;
1369         }
1370         
1371         while (attempts < 10) {
1372                 char *ld_error;
1373                 if (ldapsam_search_domain_info(ldap_state, &result)) {
1374                         return ret;
1375                 }
1376
1377                 if (ldap_count_entries(ldap_state->ldap_struct, result) < 1) {
1378                         DEBUG(3, ("Got no domain info entries for domain %s\n",
1379                                   ldap_state->domain_name));
1380                         ldap_msgfree(result);
1381                         if (NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state))) {
1382                                 continue;
1383                         } else {
1384                                 DEBUG(0, ("Adding domain info failed with %s\n", nt_errstr(ret)));
1385                                 return ret;
1386                         }
1387                 }
1388                 
1389                 if ((count = ldap_count_entries(ldap_state->ldap_struct, result)) > 1) {
1390                         DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n",
1391                                   count, ldap_state->domain_name));
1392                         ldap_msgfree(result);
1393                         return ret;
1394                 }
1395
1396                 entry = ldap_first_entry(ldap_state->ldap_struct, result);
1397                 if (!entry) {
1398                         ldap_msgfree(result);
1399                         return ret;
1400                 }
1401
1402                 if ((dn = ldap_get_dn(ldap_state->ldap_struct, entry)) == NULL) {
1403                         DEBUG(0, ("Could not get domain info DN\n"));
1404                         ldap_msgfree(result);
1405                         return ret;
1406                 }
1407
1408                 /* yes, we keep 2 seperate counters, to avoid stomping on the two
1409                    different sets of algorithmic RIDs */
1410
1411                 switch (rid_type) {
1412                 case USER_RID_TYPE:
1413                         if (!get_single_attribute(ldap_state->ldap_struct, 
1414                                                   entry, "nextUserRid",
1415                                                   old_rid_string)) {
1416                                 ldap_memfree(dn);
1417                                 ldap_msgfree(result);
1418                                 return ret;
1419                         }
1420                         break;
1421                 case GROUP_RID_TYPE:
1422                         if (!get_single_attribute(ldap_state->ldap_struct, 
1423                                                   entry, "nextGroupRid",
1424                                                   old_rid_string)) {
1425                                 ldap_memfree(dn);
1426                                 ldap_msgfree(result);
1427                                 return ret;
1428                         }
1429                         break;
1430                 }
1431
1432                 /* This is the core of the whole routine. If we had
1433                    scheme-style closures, there would be a *lot* less code
1434                    duplication... */
1435                 *rid = (uint32)atol(old_rid_string);
1436                 next_rid = *rid+RID_MULTIPLIER;
1437
1438                 slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid);
1439
1440                 switch (rid_type) {
1441                 case USER_RID_TYPE:
1442                         if (next_rid > ldap_state->high_allocated_user_rid) {
1443                                 return NT_STATUS_UNSUCCESSFUL;
1444                         }
1445
1446                         /* Try to make the modification atomically by enforcing the
1447                            old value in the delete mod. */
1448                         make_ldap_mod(ldap_state->ldap_struct, entry, &mods, "nextUserRid", next_rid_string);
1449                         break;
1450
1451                 case GROUP_RID_TYPE:
1452                         if (next_rid > ldap_state->high_allocated_group_rid) {
1453                                 return NT_STATUS_UNSUCCESSFUL;
1454                         }
1455
1456                         /* Try to make the modification atomically by enforcing the
1457                            old value in the delete mod. */
1458                         make_ldap_mod(ldap_state->ldap_struct, entry, &mods, "nextGroupRid", next_rid_string);
1459                         break;
1460                 }
1461
1462                 if ((rc = ldap_modify_s(ldap_state->ldap_struct, dn, mods)) == LDAP_SUCCESS) {
1463                         DOM_SID dom_sid;
1464                         DOM_SID sid;
1465                         pstring domain_sid_string;
1466                         int error = 0;
1467
1468                         if (!get_single_attribute(ldap_state->ldap_struct, result, "ntSid",
1469                                                   domain_sid_string)) {
1470                                 ldap_mods_free(mods, 1);
1471                                 ldap_memfree(dn);
1472                                 ldap_msgfree(result);
1473                                 return ret;
1474                         }
1475
1476                         if (!string_to_sid(&dom_sid, domain_sid_string)) { 
1477                                 ldap_mods_free(mods, 1);
1478                                 ldap_memfree(dn);
1479                                 ldap_msgfree(result);
1480                                 return ret;
1481                         }
1482
1483                         ldap_mods_free(mods, 1);
1484                         mods = NULL;
1485                         ldap_memfree(dn);
1486                         ldap_msgfree(result);
1487
1488                         sid_copy(&sid, &dom_sid);
1489                         sid_append_rid(&sid, *rid);
1490
1491                         /* check RID is not in use */
1492                         if (sid_in_use(ldap_state, &sid, &error)) {
1493                                 if (error) {
1494                                         return ret;
1495                                 }
1496                                 continue;
1497                         }
1498
1499                         return NT_STATUS_OK;
1500                 }
1501
1502                 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
1503                 DEBUG(2, ("Failed to modify rid: %s\n", ld_error));
1504                 SAFE_FREE(ld_error);
1505
1506                 ldap_mods_free(mods, 1);
1507                 mods = NULL;
1508
1509                 ldap_memfree(dn);
1510                 dn = NULL;
1511
1512                 ldap_msgfree(result);
1513                 result = NULL;
1514
1515                 {
1516                         /* Sleep for a random timeout */
1517                         unsigned sleeptime = (sys_random()*sys_getpid()*attempts);
1518                         attempts += 1;
1519                         
1520                         sleeptime %= 100;
1521                         msleep(sleeptime);
1522                 }
1523         }
1524
1525         DEBUG(0, ("Failed to set new RID\n"));
1526         return ret;
1527 }
1528
1529 /* New Interface is being implemented here */
1530
1531 /**********************************************************************
1532 Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
1533 *********************************************************************/
1534 static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state, 
1535                                 SAM_ACCOUNT * sampass,
1536                                 LDAPMessage * entry)
1537 {
1538         pstring  homedir;
1539         pstring  temp;
1540         uid_t uid;
1541         gid_t gid;
1542         char **ldap_values;
1543         char **values;
1544
1545         if ((ldap_values = ldap_get_values (ldap_state->ldap_struct, entry, "objectClass")) == NULL) {
1546                 DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
1547                 return False;
1548         }
1549
1550         for (values=ldap_values;*values;values++) {
1551                 if (strcasecmp(*values, "posixAccount") == 0) {
1552                         break;
1553                 }
1554         }
1555         
1556         if (!*values) { /*end of array, no posixAccount */
1557                 DEBUG(10, ("user does not have posixAcccount attributes\n"));
1558                 ldap_value_free(ldap_values);
1559                 return False;
1560         }
1561         ldap_value_free(ldap_values);
1562
1563         if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDirectory", homedir)) 
1564                 return False;
1565         
1566         if (!get_single_attribute(ldap_state->ldap_struct, entry, "uidNumber", temp))
1567                 return False;
1568         
1569         uid = (uid_t)atol(temp);
1570         
1571         if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber", temp))
1572                 return False;
1573         
1574         gid = (gid_t)atol(temp);
1575
1576         pdb_set_unix_homedir(sampass, homedir, PDB_SET);
1577         pdb_set_uid(sampass, uid, PDB_SET);
1578         pdb_set_gid(sampass, gid, PDB_SET);
1579         
1580         DEBUG(10, ("user has posixAcccount attributes\n"));
1581         return True;
1582 }
1583
1584
1585 /**********************************************************************
1586 Initialize SAM_ACCOUNT from an LDAP query
1587 (Based on init_sam_from_buffer in pdb_tdb.c)
1588 *********************************************************************/
1589 static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, 
1590                                 SAM_ACCOUNT * sampass,
1591                                 LDAPMessage * entry)
1592 {
1593         time_t  logon_time,
1594                         logoff_time,
1595                         kickoff_time,
1596                         pass_last_set_time, 
1597                         pass_can_change_time, 
1598                         pass_must_change_time;
1599         pstring         username, 
1600                         domain,
1601                         nt_username,
1602                         fullname,
1603                         homedir,
1604                         dir_drive,
1605                         logon_script,
1606                         profile_path,
1607                         acct_desc,
1608                         munged_dial,
1609                         workstations;
1610         struct passwd   *pw;
1611         uint32          user_rid; 
1612         uint8           smblmpwd[LM_HASH_LEN],
1613                         smbntpwd[NT_HASH_LEN];
1614         uint16          acct_ctrl = 0, 
1615                         logon_divs;
1616         uint32 hours_len;
1617         uint8           hours[MAX_HOURS_LEN];
1618         pstring temp;
1619         uid_t           uid = -1;
1620         gid_t           gid = getegid();
1621
1622
1623         /*
1624          * do a little initialization
1625          */
1626         username[0]     = '\0';
1627         domain[0]       = '\0';
1628         nt_username[0]  = '\0';
1629         fullname[0]     = '\0';
1630         homedir[0]      = '\0';
1631         dir_drive[0]    = '\0';
1632         logon_script[0] = '\0';
1633         profile_path[0] = '\0';
1634         acct_desc[0]    = '\0';
1635         munged_dial[0]  = '\0';
1636         workstations[0] = '\0';
1637          
1638
1639         if (sampass == NULL || ldap_state == NULL || entry == NULL) {
1640                 DEBUG(0, ("init_sam_from_ldap: NULL parameters found!\n"));
1641                 return False;
1642         }
1643
1644         if (ldap_state->ldap_struct == NULL) {
1645                 DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n"));
1646                 return False;
1647         }
1648         
1649         if (!get_single_attribute(ldap_state->ldap_struct, entry, "uid", username)) {
1650                 DEBUG(1, ("No uid attribute found for this user!\n"));
1651                 return False;
1652         }
1653
1654         DEBUG(2, ("Entry found for user: %s\n", username));
1655
1656         pstrcpy(nt_username, username);
1657
1658         pstrcpy(domain, ldap_state->domain_name);
1659         
1660         pdb_set_username(sampass, username, PDB_SET);
1661
1662         pdb_set_domain(sampass, domain, PDB_DEFAULT);
1663         pdb_set_nt_username(sampass, nt_username, PDB_SET);
1664         
1665         if (ldap_state->use_ntsid) {
1666                 if (get_single_attribute(ldap_state->ldap_struct, entry, "ntSid", temp)) {
1667                         pdb_set_user_sid_from_string(sampass, temp, PDB_SET);
1668                 }
1669         } else {
1670                 if (get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp)) {
1671                         user_rid = (uint32)atol(temp);
1672                         pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1673                 }
1674         }
1675
1676         if (pdb_get_init_flags(sampass,PDB_USERSID) == PDB_DEFAULT) {
1677                 DEBUG(1, ("no rid or ntSid attribute found for this user %s\n", username));
1678                 return False;
1679         }
1680
1681         if (!get_single_attribute(ldap_state->ldap_struct, entry, "primaryGroupID", temp)) {
1682                 pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
1683         } else {
1684                 uint32 group_rid;
1685                 group_rid = (uint32)atol(temp);
1686                 pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1687         }
1688
1689         /* 
1690          * If so configured, try and get the values from LDAP 
1691          */
1692
1693         if (!lp_ldap_trust_ids() || (!get_unix_attributes(ldap_state, sampass, entry))) {
1694                 
1695                 /* 
1696                  * Otherwise just ask the system getpw() calls.
1697                  */
1698         
1699                 pw = getpwnam_alloc(username);
1700                 if (pw == NULL) {
1701                         if (! ldap_state->permit_non_unix_accounts) {
1702                                 DEBUG (2,("init_sam_from_ldap: User [%s] does not exist via system getpwnam!\n", username));
1703                                 return False;
1704                         }
1705                 } else {
1706                         uid = pw->pw_uid;
1707                         pdb_set_uid(sampass, uid, PDB_SET);
1708                         gid = pw->pw_gid;
1709                         pdb_set_gid(sampass, gid, PDB_SET);
1710                         
1711                         pdb_set_unix_homedir(sampass, pw->pw_dir, PDB_SET);
1712
1713                         passwd_free(&pw);
1714                 }
1715         }
1716
1717         if ((pdb_get_init_flags(sampass,PDB_GROUPSID) == PDB_DEFAULT) 
1718                 && (pdb_get_init_flags(sampass,PDB_GID) != PDB_DEFAULT)) {
1719                 GROUP_MAP map;
1720                 gid = pdb_get_gid(sampass);
1721                 /* call the mapping code here */
1722                 if(pdb_getgrgid(&map, gid, MAPPING_WITHOUT_PRIV)) {
1723                         pdb_set_group_sid(sampass, &map.sid, PDB_SET);
1724                 } 
1725                 else {
1726                         pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
1727                 }
1728         }
1729
1730         if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdLastSet", temp)) {
1731                 /* leave as default */
1732         } else {
1733                 pass_last_set_time = (time_t) atol(temp);
1734                 pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1735         }
1736
1737         if (!get_single_attribute(ldap_state->ldap_struct, entry, "logonTime", temp)) {
1738                 /* leave as default */
1739         } else {
1740                 logon_time = (time_t) atol(temp);
1741                 pdb_set_logon_time(sampass, logon_time, PDB_SET);
1742         }
1743
1744         if (!get_single_attribute(ldap_state->ldap_struct, entry, "logoffTime", temp)) {
1745                 /* leave as default */
1746         } else {
1747                 logoff_time = (time_t) atol(temp);
1748                 pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1749         }
1750
1751         if (!get_single_attribute(ldap_state->ldap_struct, entry, "kickoffTime", temp)) {
1752                 /* leave as default */
1753         } else {
1754                 kickoff_time = (time_t) atol(temp);
1755                 pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1756         }
1757
1758         if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdCanChange", temp)) {
1759                 /* leave as default */
1760         } else {
1761                 pass_can_change_time = (time_t) atol(temp);
1762                 pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1763         }
1764
1765         if (!get_single_attribute(ldap_state->ldap_struct, entry, "pwdMustChange", temp)) {
1766                 /* leave as default */
1767         } else {
1768                 pass_must_change_time = (time_t) atol(temp);
1769                 pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1770         }
1771
1772         /* recommend that 'gecos' and 'displayName' should refer to the same
1773          * attribute OID.  userFullName depreciated, only used by Samba
1774          * primary rules of LDAP: don't make a new attribute when one is already defined
1775          * that fits your needs; using cn then displayName rather than 'userFullName'
1776          */
1777
1778         if (!get_single_attribute(ldap_state->ldap_struct, entry,
1779                                   "displayName", fullname)) {
1780                 if (!get_single_attribute(ldap_state->ldap_struct, entry,
1781                                           "cn", fullname)) {
1782                         /* leave as default */
1783                 } else {
1784                         pdb_set_fullname(sampass, fullname, PDB_SET);
1785                 }
1786         } else {
1787                 pdb_set_fullname(sampass, fullname, PDB_SET);
1788         }
1789
1790         if (!get_single_attribute(ldap_state->ldap_struct, entry, "homeDrive", dir_drive)) {
1791                 pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx, 
1792                                                                   lp_logon_drive(),
1793                                                                   username, domain, 
1794                                                                   uid, gid),
1795                                   PDB_DEFAULT);
1796         } else {
1797                 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1798         }
1799
1800         if (!get_single_attribute(ldap_state->ldap_struct, entry, "smbHome", homedir)) {
1801                 pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx, 
1802                                                                   lp_logon_home(),
1803                                                                   username, domain, 
1804                                                                   uid, gid), 
1805                                   PDB_DEFAULT);
1806         } else {
1807                 pdb_set_homedir(sampass, homedir, PDB_SET);
1808         }
1809
1810         if (!get_single_attribute(ldap_state->ldap_struct, entry, "scriptPath", logon_script)) {
1811                 pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx, 
1812                                                                      lp_logon_script(),
1813                                                                      username, domain, 
1814                                                                      uid, gid), 
1815                                      PDB_DEFAULT);
1816         } else {
1817                 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1818         }
1819
1820         if (!get_single_attribute(ldap_state->ldap_struct, entry, "profilePath", profile_path)) {
1821                 pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx, 
1822                                                                      lp_logon_path(),
1823                                                                      username, domain, 
1824                                                                      uid, gid), 
1825                                      PDB_DEFAULT);
1826         } else {
1827                 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1828         }
1829
1830         if (!get_single_attribute(ldap_state->ldap_struct, entry, "description", acct_desc)) {
1831                 /* leave as default */
1832         } else {
1833                 pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1834         }
1835
1836         if (!get_single_attribute(ldap_state->ldap_struct, entry, "userWorkstations", workstations)) {
1837                 /* leave as default */;
1838         } else {
1839                 pdb_set_workstations(sampass, workstations, PDB_SET);
1840         }
1841
1842         /* FIXME: hours stuff should be cleaner */
1843         
1844         logon_divs = 168;
1845         hours_len = 21;
1846         memset(hours, 0xff, hours_len);
1847
1848         if (!get_single_attribute (ldap_state->ldap_struct, entry, "lmPassword", temp)) {
1849                 /* leave as default */
1850         } else {
1851                 pdb_gethexpwd(temp, smblmpwd);
1852                 memset((char *)temp, '\0', strlen(temp)+1);
1853                 if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
1854                         return False;
1855                 ZERO_STRUCT(smblmpwd);
1856         }
1857
1858         if (!get_single_attribute (ldap_state->ldap_struct, entry, "ntPassword", temp)) {
1859                 /* leave as default */
1860         } else {
1861                 pdb_gethexpwd(temp, smbntpwd);
1862                 memset((char *)temp, '\0', strlen(temp)+1);
1863                 if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
1864                         return False;
1865                 ZERO_STRUCT(smbntpwd);
1866         }
1867
1868         if (!get_single_attribute (ldap_state->ldap_struct, entry, "acctFlags", temp)) {
1869                 acct_ctrl |= ACB_NORMAL;
1870         } else {
1871                 acct_ctrl = pdb_decode_acct_ctrl(temp);
1872
1873                 if (acct_ctrl == 0)
1874                         acct_ctrl |= ACB_NORMAL;
1875
1876                 pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1877         }
1878
1879         pdb_set_hours_len(sampass, hours_len, PDB_SET);
1880         pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1881
1882         pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1883         
1884         /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */
1885         /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */
1886         /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
1887
1888         pdb_set_hours(sampass, hours, PDB_SET);
1889
1890         return True;
1891 }
1892
1893 /**********************************************************************
1894 Initialize SAM_ACCOUNT from an LDAP query
1895 (Based on init_buffer_from_sam in pdb_tdb.c)
1896 *********************************************************************/
1897 static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, 
1898                                 LDAPMessage *existing,
1899                                 LDAPMod *** mods, SAM_ACCOUNT * sampass,
1900                                 BOOL (*need_update)(const SAM_ACCOUNT *,
1901                                                     enum pdb_elements))
1902 {
1903         pstring temp;
1904         uint32 rid;
1905
1906         if (mods == NULL || sampass == NULL) {
1907                 DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
1908                 return False;
1909         }
1910
1911         *mods = NULL;
1912
1913         /* 
1914          * took out adding "objectclass: sambaAccount"
1915          * do this on a per-mod basis
1916          */
1917         if (need_update(sampass, PDB_USERNAME))
1918                 make_ldap_mod(ldap_state->ldap_struct, existing, mods, 
1919                               "uid", pdb_get_username(sampass));
1920
1921         DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass)));
1922
1923         if (pdb_get_init_flags(sampass, PDB_USERSID) == PDB_DEFAULT) {
1924                 if (ldap_state->permit_non_unix_accounts) {
1925                         if (!NT_STATUS_IS_OK(ldapsam_next_rid(ldap_state, &rid, USER_RID_TYPE))) {
1926                                 DEBUG(0, ("NO user RID specified on account %s, and "
1927                                           "finding next available NUA RID failed, "
1928                                           "cannot store!\n",
1929                                           pdb_get_username(sampass)));
1930                                 ldap_mods_free(*mods, 1);
1931                                 return False;
1932                         }
1933                 } else {
1934                         DEBUG(0, ("NO user RID specified on account %s, "
1935                                   "cannot store!\n", pdb_get_username(sampass)));
1936                         ldap_mods_free(*mods, 1);
1937                         return False;
1938                 }
1939
1940                 /* now that we have figured out the RID, always store it, as
1941                    the schema requires it */
1942                 if (!pdb_set_user_sid_from_rid(sampass, rid, PDB_CHANGED)) {
1943                         DEBUG(0, ("Could not store RID back onto SAM_ACCOUNT for user %s!\n", 
1944                                   pdb_get_username(sampass)));
1945                         ldap_mods_free(*mods, 1);
1946                         return False;
1947                 }
1948         }
1949
1950         /* only update the RID if we actually need to */
1951         if (need_update(sampass, PDB_USERSID)) {
1952                 fstring sid_string;
1953                 fstring dom_sid_string;
1954                 const DOM_SID *user_sid;
1955                 user_sid = pdb_get_user_sid(sampass);
1956                 
1957                 if (ldap_state->use_ntsid) {
1958                         make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1959                                       "ntSid", sid_to_string(sid_string, user_sid));
1960                 } else {
1961                         if (!sid_peek_check_rid(get_global_sam_sid(), user_sid, &rid)) {
1962                                 DEBUG(1, ("User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n", sid_to_string(sid_string, user_sid), sid_to_string(dom_sid_string, get_global_sam_sid())));
1963                                 return False;
1964                         }
1965                         slprintf(temp, sizeof(temp) - 1, "%i", rid);
1966                         make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1967                                       "rid", temp);
1968                 }
1969                 
1970         }
1971
1972         /* we don't need to store the primary group RID - so leaving it
1973            'free' to hang off the unix primary group makes life easier */
1974
1975         if (need_update(sampass, PDB_GROUPSID)) {
1976                 rid = pdb_get_group_rid(sampass);
1977                 slprintf(temp, sizeof(temp) - 1, "%i", rid);
1978                 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1979                               "primaryGroupID", temp);
1980         }
1981
1982         /* displayName, cn, and gecos should all be the same
1983          *  most easily accomplished by giving them the same OID
1984          *  gecos isn't set here b/c it should be handled by the 
1985          *  add-user script
1986          *  We change displayName only and fall back to cn if
1987          *  it does not exist.
1988          */
1989
1990         if (need_update(sampass, PDB_FULLNAME))
1991                 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1992                               "displayName", pdb_get_fullname(sampass));
1993
1994         if (need_update(sampass, PDB_ACCTDESC))
1995                 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
1996                               "description", pdb_get_acct_desc(sampass));
1997
1998         if (need_update(sampass, PDB_WORKSTATIONS))
1999                 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2000                               "userWorkstations", pdb_get_workstations(sampass));
2001
2002         if (need_update(sampass, PDB_SMBHOME))
2003                 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2004                               "smbHome", pdb_get_homedir(sampass));
2005                         
2006         if (need_update(sampass, PDB_DRIVE))
2007                 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2008                               "homeDrive", pdb_get_dir_drive(sampass));
2009
2010         if (need_update(sampass, PDB_LOGONSCRIPT))
2011                 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2012                               "scriptPath", pdb_get_logon_script(sampass));
2013
2014         if (need_update(sampass, PDB_PROFILE))
2015                 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2016                               "profilePath", pdb_get_profile_path(sampass));
2017
2018         slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
2019
2020         if (need_update(sampass, PDB_LOGONTIME))
2021                 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2022                               "logonTime", temp);
2023
2024         slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
2025
2026         if (need_update(sampass, PDB_LOGOFFTIME))
2027                 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2028                               "logoffTime", temp);
2029
2030         slprintf (temp, sizeof (temp) - 1, "%li",
2031                   pdb_get_kickoff_time(sampass));
2032
2033         if (need_update(sampass, PDB_KICKOFFTIME))
2034                 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2035                               "kickoffTime", temp);
2036
2037         slprintf (temp, sizeof (temp) - 1, "%li",
2038                   pdb_get_pass_can_change_time(sampass));
2039
2040         if (need_update(sampass, PDB_CANCHANGETIME))
2041                 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2042                               "pwdCanChange", temp);
2043
2044         slprintf (temp, sizeof (temp) - 1, "%li",
2045                   pdb_get_pass_must_change_time(sampass));
2046
2047         if (need_update(sampass, PDB_MUSTCHANGETIME))
2048                 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2049                               "pwdMustChange", temp);
2050
2051         if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))||
2052             (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
2053
2054                 pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass),
2055                                pdb_get_acct_ctrl(sampass));
2056
2057                 if (need_update(sampass, PDB_LMPASSWD))
2058                         make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2059                                       "lmPassword", temp);
2060
2061                 pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass),
2062                                pdb_get_acct_ctrl(sampass));
2063
2064                 if (need_update(sampass, PDB_NTPASSWD))
2065                         make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2066                                       "ntPassword", temp);
2067
2068                 slprintf (temp, sizeof (temp) - 1, "%li",
2069                           pdb_get_pass_last_set_time(sampass));
2070
2071                 if (need_update(sampass, PDB_PASSLASTSET))
2072                         make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2073                                       "pwdLastSet", temp);
2074         }
2075
2076         /* FIXME: Hours stuff goes in LDAP  */
2077
2078         if (need_update(sampass, PDB_ACCTCTRL))
2079                 make_ldap_mod(ldap_state->ldap_struct, existing, mods,
2080                               "acctFlags",
2081                               pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
2082                                                     NEW_PW_FORMAT_SPACE_PADDED_LEN));
2083
2084         return True;
2085 }
2086
2087
2088
2089 /**********************************************************************
2090 Connect to LDAP server for password enumeration
2091 *********************************************************************/
2092 static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
2093 {
2094         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2095         int rc;
2096         pstring filter;
2097
2098         pstrcpy(filter, lp_ldap_filter());
2099         all_string_sub(filter, "%u", "*", sizeof(pstring));
2100
2101         rc = ldapsam_search_suffix(ldap_state, 
2102                                    filter, attr,
2103                                    &ldap_state->result);
2104
2105         if (rc != LDAP_SUCCESS) {
2106                 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
2107                 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
2108                 ldap_msgfree(ldap_state->result);
2109                 ldap_state->result = NULL;
2110                 return NT_STATUS_UNSUCCESSFUL;
2111         }
2112
2113         DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
2114                 ldap_count_entries(ldap_state->ldap_struct,
2115                 ldap_state->result)));
2116
2117         ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
2118                                  ldap_state->result);
2119         ldap_state->index = 0;
2120
2121         return NT_STATUS_OK;
2122 }
2123
2124 /**********************************************************************
2125 End enumeration of the LDAP password list 
2126 *********************************************************************/
2127 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
2128 {
2129         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2130         if (ldap_state->result) {
2131                 ldap_msgfree(ldap_state->result);
2132                 ldap_state->result = NULL;
2133         }
2134 }
2135
2136 /**********************************************************************
2137 Get the next entry in the LDAP password database 
2138 *********************************************************************/
2139 static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
2140 {
2141         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2142         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2143         BOOL bret = False;
2144
2145         /* The rebind proc needs this *HACK*.  We are not multithreaded, so
2146            this will work, but it's not nice. */
2147         static_ldap_state = ldap_state;
2148
2149         while (!bret) {
2150                 if (!ldap_state->entry)
2151                         return ret;
2152                 
2153                 ldap_state->index++;
2154                 bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
2155                 
2156                 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
2157                                             ldap_state->entry); 
2158         }
2159
2160         return NT_STATUS_OK;
2161 }
2162
2163 /**********************************************************************
2164 Get SAM_ACCOUNT entry from LDAP by username 
2165 *********************************************************************/
2166 static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
2167 {
2168         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2169         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2170         LDAPMessage *result;
2171         LDAPMessage *entry;
2172         int count;
2173         
2174         if (ldapsam_search_suffix_by_name(ldap_state, sname, &result) != LDAP_SUCCESS) {
2175                 return NT_STATUS_NO_SUCH_USER;
2176         }
2177         
2178         count = ldap_count_entries(ldap_state->ldap_struct, result);
2179         
2180         if (count < 1) {
2181                 DEBUG(4,
2182                       ("We don't find this user [%s] count=%d\n", sname,
2183                        count));
2184                 return NT_STATUS_NO_SUCH_USER;
2185         } else if (count > 1) {
2186                 DEBUG(1,
2187                       ("Duplicate entries for this user [%s] Failing. count=%d\n", sname,
2188                        count));
2189                 return NT_STATUS_NO_SUCH_USER;
2190         }
2191
2192         entry = ldap_first_entry(ldap_state->ldap_struct, result);
2193         if (entry) {
2194                 if (!init_sam_from_ldap(ldap_state, user, entry)) {
2195                         DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
2196                         ldap_msgfree(result);
2197                         return NT_STATUS_NO_SUCH_USER;
2198                 }
2199                 ldap_msgfree(result);
2200                 ret = NT_STATUS_OK;
2201         } else {
2202                 ldap_msgfree(result);
2203         }
2204         return ret;
2205 }
2206
2207 /**********************************************************************
2208 Get SAM_ACCOUNT entry from LDAP by SID
2209 *********************************************************************/
2210 static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
2211 {
2212         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2213         struct ldapsam_privates *ldap_state = 
2214                 (struct ldapsam_privates *)my_methods->private_data;
2215         LDAPMessage *result;
2216         LDAPMessage *entry;
2217         fstring sid_string;
2218         int count;
2219         
2220         if (ldap_state->use_ntsid) {
2221                 if (ldapsam_search_suffix_by_sid(ldap_state, sid, &result) != LDAP_SUCCESS) {
2222                         return NT_STATUS_NO_SUCH_USER;
2223                 }
2224         } else {
2225                 uint32 rid;
2226                 if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) {
2227                         return NT_STATUS_NO_SUCH_USER;
2228                 }
2229                 
2230                 if (ldapsam_search_suffix_by_rid(ldap_state, rid, &result) != LDAP_SUCCESS) {
2231                         return NT_STATUS_NO_SUCH_USER;
2232                 }
2233         }
2234         
2235         count = ldap_count_entries(ldap_state->ldap_struct, result);
2236         
2237         if (count < 1) {
2238                 DEBUG(4,
2239                       ("We don't find this SID [%s] count=%d\n", sid_to_string(sid_string, sid),
2240                        count));
2241                 return NT_STATUS_NO_SUCH_USER;
2242         } else if (count > 1) {
2243                 DEBUG(1,
2244                       ("More than one user with SID [%s]. Failing. count=%d\n", sid_to_string(sid_string, sid),
2245                        count));
2246                 return NT_STATUS_NO_SUCH_USER;
2247         }
2248
2249         entry = ldap_first_entry(ldap_state->ldap_struct, result);
2250         if (entry) {
2251                 if (!init_sam_from_ldap(ldap_state, user, entry)) {
2252                         DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
2253                         ldap_msgfree(result);
2254                         return NT_STATUS_NO_SUCH_USER;
2255                 }
2256                 ldap_msgfree(result);
2257                 ret = NT_STATUS_OK;
2258         } else {
2259                 ldap_msgfree(result);
2260         }
2261         return ret;
2262 }       
2263
2264 /********************************************************************
2265 Do the actual modification - also change a plaittext passord if 
2266 it it set.
2267 **********************************************************************/
2268
2269 static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, 
2270                                      SAM_ACCOUNT *newpwd, char *dn,
2271                                      LDAPMod **mods, int ldap_op, 
2272                                      BOOL (*need_update)(const SAM_ACCOUNT *,
2273                                                          enum pdb_elements))
2274 {
2275         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2276         int rc;
2277         
2278         if (!my_methods || !newpwd || !dn) {
2279                 return NT_STATUS_INVALID_PARAMETER;
2280         }
2281         
2282         if (!mods) {
2283                 DEBUG(5,("mods is empty: nothing to modify\n"));
2284                 /* may be password change below however */
2285         } else {
2286                 switch(ldap_op)
2287                 {
2288                         case LDAP_MOD_ADD: 
2289                                 make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
2290                                 rc = ldapsam_add(ldap_state, dn, mods);
2291                                 break;
2292                         case LDAP_MOD_REPLACE: 
2293                                 rc = ldapsam_modify(ldap_state, dn ,mods);
2294                                 break;
2295                         default:        
2296                                 DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
2297                                 return NT_STATUS_INVALID_PARAMETER;
2298                 }
2299                 
2300                 if (rc!=LDAP_SUCCESS) {
2301                         char *ld_error = NULL;
2302                         ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2303                                         &ld_error);
2304                         DEBUG(1,
2305                               ("failed to %s user dn= %s with: %s\n\t%s\n",
2306                                ldap_op == LDAP_MOD_ADD ? "add" : "modify",
2307                                dn, ldap_err2string(rc),
2308                                ld_error?ld_error:"unknown"));
2309                         SAFE_FREE(ld_error);
2310                         return NT_STATUS_UNSUCCESSFUL;
2311                 }  
2312         }
2313         
2314 #ifdef LDAP_EXOP_X_MODIFY_PASSWD
2315         if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) &&
2316                 (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) &&
2317                 need_update(newpwd, PDB_PLAINTEXT_PW) &&
2318                 (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
2319                 BerElement *ber;
2320                 struct berval *bv;
2321                 char *retoid;
2322                 struct berval *retdata;
2323                 char *utf8_password;
2324                 char *utf8_dn;
2325
2326                 if (push_utf8_allocate(&utf8_password, pdb_get_plaintext_passwd(newpwd)) == (size_t)-1) {
2327                         return NT_STATUS_NO_MEMORY;
2328                 }
2329
2330                 if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
2331                         return NT_STATUS_NO_MEMORY;
2332                 }
2333
2334                 if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
2335                         DEBUG(0,("ber_alloc_t returns NULL\n"));
2336                         SAFE_FREE(utf8_password);
2337                         return NT_STATUS_UNSUCCESSFUL;
2338                 }
2339
2340                 ber_printf (ber, "{");
2341                 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, utf8_dn);
2342                 ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, utf8_password);
2343                 ber_printf (ber, "N}");
2344
2345                 if ((rc = ber_flatten (ber, &bv))<0) {
2346                         DEBUG(0,("ber_flatten returns a value <0\n"));
2347                         ber_free(ber,1);
2348                         SAFE_FREE(utf8_dn);
2349                         SAFE_FREE(utf8_password);
2350                         return NT_STATUS_UNSUCCESSFUL;
2351                 }
2352                 
2353                 SAFE_FREE(utf8_dn);
2354                 SAFE_FREE(utf8_password);
2355                 ber_free(ber, 1);
2356
2357                 if ((rc = ldapsam_extended_operation(ldap_state, LDAP_EXOP_X_MODIFY_PASSWD,
2358                                                     bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) {
2359                         DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
2360                                 pdb_get_username(newpwd),ldap_err2string(rc)));
2361                 } else {
2362                         DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
2363 #ifdef DEBUG_PASSWORD
2364                         DEBUG(100,("LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd)));
2365 #endif    
2366                         ber_bvfree(retdata);
2367                         ber_memfree(retoid);
2368                 }
2369                 ber_bvfree(bv);
2370         }
2371 #else
2372         DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
2373 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */
2374         return NT_STATUS_OK;
2375 }
2376
2377 /**********************************************************************
2378 Delete entry from LDAP for username 
2379 *********************************************************************/
2380 static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
2381 {
2382         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2383         const char *sname;
2384         int rc;
2385         LDAPMessage *result;
2386         NTSTATUS ret;
2387         const char *sam_user_attrs[] =
2388         { "lmPassword", "ntPassword", "pwdLastSet", "logonTime", "logoffTime",
2389           "kickoffTime", "pwdCanChange", "pwdMustChange", "acctFlags",
2390           "displayName", "smbHome", "homeDrive", "scriptPath", "profilePath",
2391           "userWorkstations", "primaryGroupID", "domain", "rid", "ntSid", NULL };
2392
2393         if (!sam_acct) {
2394                 DEBUG(0, ("sam_acct was NULL!\n"));
2395                 return NT_STATUS_INVALID_PARAMETER;
2396         }
2397
2398         sname = pdb_get_username(sam_acct);
2399
2400         DEBUG (3, ("Deleting user %s from LDAP.\n", sname));
2401
2402         rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result);
2403         if (rc != LDAP_SUCCESS) {
2404                 return NT_STATUS_NO_SUCH_USER;
2405         }
2406
2407         ret = ldapsam_delete_entry(ldap_state, result, "sambaAccount",
2408                                    sam_user_attrs);
2409         ldap_msgfree(result);
2410         return ret;
2411 }
2412
2413 /**********************************************************************
2414   Helper function to determine for update_sam_account whether
2415   we need LDAP modification.
2416 *********************************************************************/
2417 static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
2418                                enum pdb_elements element)
2419 {
2420         return IS_SAM_CHANGED(sampass, element);
2421 }
2422
2423 /**********************************************************************
2424 Update SAM_ACCOUNT 
2425 *********************************************************************/
2426 static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2427 {
2428         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2429         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2430         int rc;
2431         char *dn;
2432         LDAPMessage *result;
2433         LDAPMessage *entry;
2434         LDAPMod **mods;
2435
2436         rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result);
2437         if (rc != LDAP_SUCCESS) {
2438                 return NT_STATUS_UNSUCCESSFUL;
2439         }
2440
2441         if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2442                 DEBUG(0, ("No user to modify!\n"));
2443                 ldap_msgfree(result);
2444                 return NT_STATUS_UNSUCCESSFUL;
2445         }
2446
2447         entry = ldap_first_entry(ldap_state->ldap_struct, result);
2448         dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2449
2450         if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2451                                 element_is_changed)) {
2452                 DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n"));
2453                 ldap_msgfree(result);
2454                 return NT_STATUS_UNSUCCESSFUL;
2455         }
2456         
2457         ldap_msgfree(result);
2458         
2459         if (mods == NULL) {
2460                 DEBUG(4,("mods is empty: nothing to update for user: %s\n",
2461                          pdb_get_username(newpwd)));
2462                 ldap_mods_free(mods, 1);
2463                 return NT_STATUS_OK;
2464         }
2465         
2466         ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed);
2467         ldap_mods_free(mods,1);
2468
2469         if (!NT_STATUS_IS_OK(ret)) {
2470                 char *ld_error = NULL;
2471                 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2472                                 &ld_error);
2473                 DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n",
2474                          pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
2475                 SAFE_FREE(ld_error);
2476                 return ret;
2477         }
2478
2479         DEBUG(2, ("successfully modified uid = %s in the LDAP database\n",
2480                   pdb_get_username(newpwd)));
2481         return NT_STATUS_OK;
2482 }
2483
2484 /**********************************************************************
2485   Helper function to determine for update_sam_account whether
2486   we need LDAP modification.
2487 *********************************************************************/
2488 static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
2489                                       enum pdb_elements element)
2490 {
2491         return (IS_SAM_SET(sampass, element) ||
2492                 IS_SAM_CHANGED(sampass, element));
2493 }
2494
2495 /**********************************************************************
2496 Add SAM_ACCOUNT to LDAP 
2497 *********************************************************************/
2498 static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
2499 {
2500         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
2501         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
2502         int rc;
2503         pstring filter;
2504         LDAPMessage *result = NULL;
2505         LDAPMessage *entry  = NULL;
2506         pstring dn;
2507         LDAPMod **mods = NULL;
2508         int             ldap_op;
2509         uint32          num_result;
2510         
2511         const char *username = pdb_get_username(newpwd);
2512         if (!username || !*username) {
2513                 DEBUG(0, ("Cannot add user without a username!\n"));
2514                 return NT_STATUS_INVALID_PARAMETER;
2515         }
2516
2517         rc = ldapsam_search_suffix_by_name (ldap_state, username, &result);
2518         if (rc != LDAP_SUCCESS) {
2519                 return NT_STATUS_UNSUCCESSFUL;
2520         }
2521
2522         if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) {
2523                 DEBUG(0,("User '%s' already in the base, with samba properties\n", 
2524                          username));
2525                 ldap_msgfree(result);
2526                 return NT_STATUS_UNSUCCESSFUL;
2527         }
2528         ldap_msgfree(result);
2529
2530         slprintf (filter, sizeof (filter) - 1, "uid=%s", username);
2531         rc = ldapsam_search_suffix(ldap_state, filter, attr, &result);
2532         if (rc != LDAP_SUCCESS) {
2533                 return NT_STATUS_UNSUCCESSFUL;
2534         }
2535
2536         num_result = ldap_count_entries(ldap_state->ldap_struct, result);
2537         
2538         if (num_result > 1) {
2539                 DEBUG (0, ("More than one user with that uid exists: bailing out!\n"));
2540                 ldap_msgfree(result);
2541                 return NT_STATUS_UNSUCCESSFUL;
2542         }
2543         
2544         /* Check if we need to update an existing entry */
2545         if (num_result == 1) {
2546                 char *tmp;
2547                 
2548                 DEBUG(3,("User exists without samba properties: adding them\n"));
2549                 ldap_op = LDAP_MOD_REPLACE;
2550                 entry = ldap_first_entry (ldap_state->ldap_struct, result);
2551                 tmp = ldap_get_dn (ldap_state->ldap_struct, entry);
2552                 slprintf (dn, sizeof (dn) - 1, "%s", tmp);
2553                 ldap_memfree (tmp);
2554         } else {
2555                 /* Check if we need to add an entry */
2556                 DEBUG(3,("Adding new user\n"));
2557                 ldap_op = LDAP_MOD_ADD;
2558                 if (username[strlen(username)-1] == '$') {
2559                         slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
2560                 } else {
2561                         slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
2562                 }
2563         }
2564
2565         if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
2566                                 element_is_set_or_changed)) {
2567                 DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n"));
2568                 ldap_msgfree(result);
2569                 return NT_STATUS_UNSUCCESSFUL;          
2570         }
2571         
2572         ldap_msgfree(result);
2573
2574         if (mods == NULL) {
2575                 DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd)));
2576                 return NT_STATUS_UNSUCCESSFUL;
2577         }
2578         
2579         make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
2580
2581         ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed);
2582         if (NT_STATUS_IS_ERR(ret)) {
2583                 DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
2584                          pdb_get_username(newpwd),dn));
2585                 ldap_mods_free(mods,1);
2586                 return ret;
2587         }
2588
2589         DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
2590         ldap_mods_free(mods, 1);
2591         return NT_STATUS_OK;
2592 }
2593
2594 static void free_private_data(void **vp) 
2595 {
2596         struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
2597
2598         ldapsam_close(*ldap_state);
2599
2600         if ((*ldap_state)->bind_secret) {
2601                 memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
2602         }
2603
2604         ldapsam_close(*ldap_state);
2605                 
2606         SAFE_FREE((*ldap_state)->bind_dn);
2607         SAFE_FREE((*ldap_state)->bind_secret);
2608
2609         *ldap_state = NULL;
2610
2611         /* No need to free any further, as it is talloc()ed */
2612 }
2613
2614 static const char *group_attr[] = {"cn", "ntSid", "ntGroupType",
2615                                    "gidNumber",
2616                                    "displayName", "description",
2617                                    NULL };
2618                                    
2619 static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
2620                                      const char *filter,
2621                                      LDAPMessage ** result)
2622 {
2623         int scope = LDAP_SCOPE_SUBTREE;
2624         int rc;
2625
2626         DEBUG(2, ("ldapsam_search_one_group: searching for:[%s]\n", filter));
2627
2628         rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope,
2629                             filter, group_attr, 0, result);
2630
2631         if (rc != LDAP_SUCCESS) {
2632                 char *ld_error = NULL;
2633                 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2634                                 &ld_error);
2635                 DEBUG(0, ("ldapsam_search_one_group: "
2636                           "Problem during the LDAP search: LDAP error: %s (%s)",
2637                           ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
2638                 DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
2639                           lp_ldap_suffix(), filter));
2640                 SAFE_FREE(ld_error);
2641         }
2642
2643         return rc;
2644 }
2645
2646 static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state,
2647                                  GROUP_MAP *map, LDAPMessage *entry)
2648 {
2649         pstring temp;
2650
2651         if (ldap_state == NULL || map == NULL || entry == NULL ||
2652             ldap_state->ldap_struct == NULL) {
2653                 DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n"));
2654                 return False;
2655         }
2656
2657         if (!get_single_attribute(ldap_state->ldap_struct, entry, "gidNumber",
2658                                   temp)) {
2659                 DEBUG(0, ("Mandatory attribute gidNumber not found\n"));
2660                 return False;
2661         }
2662         DEBUG(2, ("Entry found for group: %s\n", temp));
2663
2664         map->gid = (gid_t)atol(temp);
2665
2666         if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntSid",
2667                                   temp)) {
2668                 DEBUG(0, ("Mandatory attribute ntSid not found\n"));
2669                 return False;
2670         }
2671         string_to_sid(&map->sid, temp);
2672
2673         if (!get_single_attribute(ldap_state->ldap_struct, entry, "ntGroupType",
2674                                   temp)) {
2675                 DEBUG(0, ("Mandatory attribute ntGroupType not found\n"));
2676                 return False;
2677         }
2678         map->sid_name_use = (uint32)atol(temp);
2679
2680         if ((map->sid_name_use < SID_NAME_USER) ||
2681             (map->sid_name_use > SID_NAME_UNKNOWN)) {
2682                 DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use));
2683                 return False;
2684         }
2685
2686         if (!get_single_attribute(ldap_state->ldap_struct, entry, "displayName",
2687                                   temp)) {
2688                 DEBUG(3, ("Attribute displayName not found\n"));
2689                 temp[0] = '\0';
2690                 if (!get_single_attribute(ldap_state->ldap_struct, entry, "cn",
2691                                           temp)) {
2692                         DEBUG(0, ("Attributes cn not found either "
2693                                   "for gidNumber(%i)\n",map->gid));
2694                         return False;
2695                 }
2696         }
2697         fstrcpy(map->nt_name, temp);
2698
2699         if (!get_single_attribute(ldap_state->ldap_struct, entry, "description",
2700                                   temp)) {
2701                 DEBUG(3, ("Attribute description not found\n"));
2702                 temp[0] = '\0';
2703         }
2704         fstrcpy(map->comment, temp);
2705
2706         map->systemaccount = 0;
2707         init_privilege(&map->priv_set);
2708
2709         return True;
2710 }
2711
2712 static BOOL init_ldap_from_group(LDAP *ldap_struct,
2713                                  LDAPMessage *existing,
2714                                  LDAPMod ***mods,
2715                                  const GROUP_MAP *map)
2716 {
2717         pstring tmp;
2718
2719         if (mods == NULL || map == NULL) {
2720                 DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
2721                 return False;
2722         }
2723
2724         *mods = NULL;
2725
2726         sid_to_string(tmp, &map->sid);
2727         make_ldap_mod(ldap_struct, existing, mods, "ntSid", tmp);
2728         snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use);
2729         make_ldap_mod(ldap_struct, existing, mods, "ntGroupType", tmp);
2730
2731         make_ldap_mod(ldap_struct, existing, mods, "displayName", map->nt_name);
2732         make_ldap_mod(ldap_struct, existing, mods, "description", map->comment);
2733
2734         return True;
2735 }
2736
2737 static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
2738                                  const char *filter,
2739                                  GROUP_MAP *map)
2740 {
2741         struct ldapsam_privates *ldap_state =
2742                 (struct ldapsam_privates *)methods->private_data;
2743         LDAPMessage *result;
2744         LDAPMessage *entry;
2745         int count;
2746
2747         if (ldapsam_search_one_group(ldap_state, filter, &result)
2748             != LDAP_SUCCESS) {
2749                 return NT_STATUS_NO_SUCH_GROUP;
2750         }
2751
2752         count = ldap_count_entries(ldap_state->ldap_struct, result);
2753
2754         if (count < 1) {
2755                 DEBUG(4, ("Did not find group for filter %s\n", filter));
2756                 return NT_STATUS_NO_SUCH_GROUP;
2757         }
2758
2759         if (count > 1) {
2760                 DEBUG(1, ("Duplicate entries for filter %s: count=%d\n",
2761                           filter, count));
2762                 return NT_STATUS_NO_SUCH_GROUP;
2763         }
2764
2765         entry = ldap_first_entry(ldap_state->ldap_struct, result);
2766
2767         if (!entry) {
2768                 ldap_msgfree(result);
2769                 return NT_STATUS_UNSUCCESSFUL;
2770         }
2771
2772         if (!init_group_from_ldap(ldap_state, map, entry)) {
2773                 DEBUG(1, ("init_group_from_ldap failed for group filter %s\n",
2774                           filter));
2775                 ldap_msgfree(result);
2776                 return NT_STATUS_NO_SUCH_GROUP;
2777         }
2778
2779         ldap_msgfree(result);
2780         return NT_STATUS_OK;
2781 }
2782
2783 static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
2784                                  DOM_SID sid, BOOL with_priv)
2785 {
2786         pstring filter;
2787
2788         snprintf(filter, sizeof(filter)-1,
2789                  "(&(objectClass=sambaGroupMapping)(ntSid=%s))",
2790                  sid_string_static(&sid));
2791
2792         return ldapsam_getgroup(methods, filter, map);
2793 }
2794
2795 static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
2796                                  gid_t gid, BOOL with_priv)
2797 {
2798         pstring filter;
2799
2800         snprintf(filter, sizeof(filter)-1,
2801                  "(&(objectClass=sambaGroupMapping)(gidNumber=%d))",
2802                  gid);
2803
2804         return ldapsam_getgroup(methods, filter, map);
2805 }
2806
2807 static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
2808                                  char *name, BOOL with_priv)
2809 {
2810         pstring filter;
2811
2812         /* TODO: Escaping of name? */
2813
2814         snprintf(filter, sizeof(filter)-1,
2815                  "(&(objectClass=sambaGroupMapping)(|(displayName=%s)(cn=%s)))",
2816                  name, name);
2817
2818         return ldapsam_getgroup(methods, filter, map);
2819 }
2820
2821 static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
2822                                            gid_t gid,
2823                                            LDAPMessage **result)
2824 {
2825         pstring filter;
2826
2827         snprintf(filter, sizeof(filter)-1,
2828                  "(&(objectClass=posixGroup)(gidNumber=%i))", gid);
2829
2830         return ldapsam_search_one_group(ldap_state, filter, result);
2831 }
2832
2833 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
2834                                                 GROUP_MAP *map)
2835 {
2836         struct ldapsam_privates *ldap_state =
2837                 (struct ldapsam_privates *)methods->private_data;
2838         LDAPMessage *result = NULL;
2839         LDAPMod **mods = NULL;
2840
2841         char *tmp;
2842         pstring dn;
2843         LDAPMessage *entry;
2844
2845         GROUP_MAP dummy;
2846
2847         int rc;
2848
2849         if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
2850                                              map->gid, False))) {
2851                 DEBUG(0, ("Group %i already exists in LDAP\n", map->gid));
2852                 return NT_STATUS_UNSUCCESSFUL;
2853         }
2854
2855         rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2856         if (rc != LDAP_SUCCESS) {
2857                 return NT_STATUS_UNSUCCESSFUL;
2858         }
2859
2860         if (ldap_count_entries(ldap_state->ldap_struct, result) != 1) {
2861                 DEBUG(2, ("Group %i must exist exactly once in LDAP\n",
2862                           map->gid));
2863                 ldap_msgfree(result);
2864                 return NT_STATUS_UNSUCCESSFUL;
2865         }
2866
2867         entry = ldap_first_entry(ldap_state->ldap_struct, result);
2868         tmp = ldap_get_dn(ldap_state->ldap_struct, entry);
2869         pstrcpy(dn, tmp);
2870         ldap_memfree(tmp);
2871
2872         if (!init_ldap_from_group(ldap_state->ldap_struct,
2873                                   result, &mods, map)) {
2874                 DEBUG(0, ("init_ldap_from_group failed!\n"));
2875                 ldap_mods_free(mods, 1);
2876                 ldap_msgfree(result);
2877                 return NT_STATUS_UNSUCCESSFUL;
2878         }
2879
2880         ldap_msgfree(result);
2881
2882         if (mods == NULL) {
2883                 DEBUG(0, ("mods is empty\n"));
2884                 return NT_STATUS_UNSUCCESSFUL;
2885         }
2886
2887         make_a_mod(&mods, LDAP_MOD_ADD, "objectClass",
2888                    "sambaGroupMapping");
2889
2890         rc = ldapsam_modify(ldap_state, dn, mods);
2891         ldap_mods_free(mods, 1);
2892
2893         if (rc != LDAP_SUCCESS) {
2894                 char *ld_error = NULL;
2895                 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2896                                 &ld_error);
2897                 DEBUG(0, ("failed to add group %i error: %s (%s)\n", map->gid, 
2898                           ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2899                 SAFE_FREE(ld_error);
2900                 return NT_STATUS_UNSUCCESSFUL;
2901         }
2902
2903         DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2904         return NT_STATUS_OK;
2905 }
2906
2907 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
2908                                                    GROUP_MAP *map)
2909 {
2910         struct ldapsam_privates *ldap_state =
2911                 (struct ldapsam_privates *)methods->private_data;
2912         int rc;
2913         char *dn;
2914         LDAPMessage *result;
2915         LDAPMessage *entry;
2916         LDAPMod **mods;
2917
2918         rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
2919
2920         if (rc != LDAP_SUCCESS) {
2921                 return NT_STATUS_UNSUCCESSFUL;
2922         }
2923
2924         if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) {
2925                 DEBUG(0, ("No group to modify!\n"));
2926                 ldap_msgfree(result);
2927                 return NT_STATUS_UNSUCCESSFUL;
2928         }
2929
2930         entry = ldap_first_entry(ldap_state->ldap_struct, result);
2931         dn = ldap_get_dn(ldap_state->ldap_struct, entry);
2932
2933         if (!init_ldap_from_group(ldap_state->ldap_struct,
2934                                   result, &mods, map)) {
2935                 DEBUG(0, ("init_ldap_from_group failed\n"));
2936                 ldap_msgfree(result);
2937                 return NT_STATUS_UNSUCCESSFUL;
2938         }
2939
2940         ldap_msgfree(result);
2941
2942         if (mods == NULL) {
2943                 DEBUG(4, ("mods is empty: nothing to do\n"));
2944                 return NT_STATUS_UNSUCCESSFUL;
2945         }
2946
2947         rc = ldapsam_modify(ldap_state, dn, mods);
2948
2949         ldap_mods_free(mods, 1);
2950
2951         if (rc != LDAP_SUCCESS) {
2952                 char *ld_error = NULL;
2953                 ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
2954                                 &ld_error);
2955                 DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map->gid, 
2956                           ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
2957                 SAFE_FREE(ld_error);
2958         }
2959
2960         DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid));
2961         return NT_STATUS_OK;
2962 }
2963
2964 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
2965                                                    DOM_SID sid)
2966 {
2967         struct ldapsam_privates *ldap_state =
2968                 (struct ldapsam_privates *)methods->private_data;
2969         pstring sidstring, filter;
2970         LDAPMessage *result;
2971         int rc;
2972         NTSTATUS ret;
2973
2974         const char *sam_group_attrs[] = { "ntSid", "ntGroupType",
2975                                           "description", "displayName",
2976                                           NULL };
2977         sid_to_string(sidstring, &sid);
2978         snprintf(filter, sizeof(filter)-1,
2979                  "(&(objectClass=sambaGroupMapping)(ntSid=%s))", sidstring);
2980
2981         rc = ldapsam_search_one_group(ldap_state, filter, &result);
2982
2983         if (rc != LDAP_SUCCESS) {
2984                 return NT_STATUS_NO_SUCH_GROUP;
2985         }
2986
2987         ret = ldapsam_delete_entry(ldap_state, result, "sambaGroupMapping",
2988                                    sam_group_attrs);
2989         ldap_msgfree(result);
2990         return ret;
2991 }
2992
2993 static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
2994                                     BOOL update)
2995 {
2996         struct ldapsam_privates *ldap_state =
2997                 (struct ldapsam_privates *)my_methods->private_data;
2998         const char *filter = "(objectClass=sambaGroupMapping)";
2999         int rc;
3000
3001         rc = ldapsam_search(ldap_state, lp_ldap_suffix(),
3002                             LDAP_SCOPE_SUBTREE, filter,
3003                             group_attr, 0, &ldap_state->result);
3004
3005         if (rc != LDAP_SUCCESS) {
3006                 DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
3007                 DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
3008                 ldap_msgfree(ldap_state->result);
3009                 ldap_state->result = NULL;
3010                 return NT_STATUS_UNSUCCESSFUL;
3011         }
3012
3013         DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n",
3014                   ldap_count_entries(ldap_state->ldap_struct,
3015                                      ldap_state->result)));
3016
3017         ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct,
3018                                  ldap_state->result);
3019         ldap_state->index = 0;
3020
3021         return NT_STATUS_OK;
3022 }
3023
3024 static void ldapsam_endsamgrent(struct pdb_methods *my_methods)
3025 {
3026         ldapsam_endsampwent(my_methods);
3027 }
3028
3029 static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
3030                                     GROUP_MAP *map)
3031 {
3032         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
3033         struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
3034         BOOL bret = False;
3035
3036         /* The rebind proc needs this *HACK*.  We are not multithreaded, so
3037            this will work, but it's not nice. */
3038         static_ldap_state = ldap_state;
3039
3040         while (!bret) {
3041                 if (!ldap_state->entry)
3042                         return ret;
3043                 
3044                 ldap_state->index++;
3045                 bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
3046                 
3047                 ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
3048                                             ldap_state->entry); 
3049         }
3050
3051         return NT_STATUS_OK;
3052 }
3053
3054 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
3055                                            enum SID_NAME_USE sid_name_use,
3056                                            GROUP_MAP **rmap, int *num_entries,
3057                                            BOOL unix_only, BOOL with_priv)
3058 {
3059         GROUP_MAP map;
3060         GROUP_MAP *mapt;
3061         int entries = 0;
3062         NTSTATUS nt_status;
3063
3064         *num_entries = 0;
3065         *rmap = NULL;
3066
3067         if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
3068                 DEBUG(0, ("Unable to open passdb\n"));
3069                 return NT_STATUS_ACCESS_DENIED;
3070         }
3071
3072         while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) {
3073                 if (sid_name_use != SID_NAME_UNKNOWN &&
3074                     sid_name_use != map.sid_name_use) {
3075                         DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
3076                         continue;
3077                 }
3078                 if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
3079                         DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name));
3080                         continue;
3081                 }
3082
3083                 mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP));
3084                 if (!mapt) {
3085                         DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n"));
3086                         SAFE_FREE(*rmap);
3087                         return NT_STATUS_UNSUCCESSFUL;
3088                 }
3089                 else
3090                         (*rmap) = mapt;
3091
3092                 mapt[entries] = map;
3093
3094                 entries += 1;
3095
3096         }
3097         ldapsam_endsamgrent(methods);
3098
3099         *num_entries = entries;
3100
3101         return NT_STATUS_OK;
3102 }
3103
3104 static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3105 {
3106         NTSTATUS nt_status;
3107         struct ldapsam_privates *ldap_state;
3108
3109         if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
3110                 return nt_status;
3111         }
3112
3113         (*pdb_method)->name = "ldapsam";
3114
3115         (*pdb_method)->setsampwent = ldapsam_setsampwent;
3116         (*pdb_method)->endsampwent = ldapsam_endsampwent;
3117         (*pdb_method)->getsampwent = ldapsam_getsampwent;
3118         (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
3119         (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
3120         (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
3121         (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
3122         (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
3123
3124         (*pdb_method)->getgrsid = ldapsam_getgrsid;
3125         (*pdb_method)->getgrgid = ldapsam_getgrgid;
3126         (*pdb_method)->getgrnam = ldapsam_getgrnam;
3127         (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
3128         (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
3129         (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
3130         (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
3131
3132         /* TODO: Setup private data and free */
3133
3134         ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates));
3135
3136         if (!ldap_state) {
3137                 DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
3138                 return NT_STATUS_NO_MEMORY;
3139         }
3140
3141         if (location) {
3142                 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
3143         } else {
3144                 ldap_state->uri = "ldap://localhost";
3145         }
3146
3147         ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, lp_workgroup());
3148         if (!ldap_state->domain_name) {
3149                 return NT_STATUS_NO_MEMORY;
3150         }
3151
3152         sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
3153
3154         ldap_state->use_ntsid = True;
3155
3156         (*pdb_method)->private_data = ldap_state;
3157
3158         (*pdb_method)->free_private_data = free_private_data;
3159
3160         return NT_STATUS_OK;
3161 }
3162
3163 static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3164 {
3165         NTSTATUS nt_status;
3166         struct ldapsam_privates *ldap_state;
3167
3168         if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
3169                 return nt_status;
3170         }
3171
3172         (*pdb_method)->name = "ldapsam_compat";
3173
3174         ldap_state = (*pdb_method)->private_data;
3175         ldap_state->use_ntsid = False;
3176
3177         if (location) {
3178                 ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location);
3179         } else {
3180 #ifndef WITH_LDAP_SAMCONFIG
3181                 ldap_state->uri = "ldap://localhost";
3182 #else
3183                 int ldap_port = lp_ldap_port();
3184                         
3185                 /* remap default port if not using SSL (ie clear or TLS) */
3186                 if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
3187                         ldap_port = 389;
3188                 }
3189
3190                 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);
3191                 if (!ldap_state->uri) {
3192                         return NT_STATUS_NO_MEMORY;
3193                 }
3194 #endif
3195         }
3196
3197         return NT_STATUS_OK;
3198 }
3199
3200 static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
3201 {
3202         NTSTATUS nt_status;
3203         struct ldapsam_privates *ldap_state;
3204         uint32 low_idmap_uid, high_idmap_uid;
3205         uint32 low_idmap_gid, high_idmap_gid;
3206
3207         if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
3208                 return nt_status;
3209         }
3210
3211         (*pdb_method)->name = "ldapsam";
3212
3213         ldap_state = (*pdb_method)->private_data;
3214         
3215         ldap_state->permit_non_unix_accounts = True;
3216
3217         /* We know these uids can't turn up as allogorithmic RIDs */
3218         if (!lp_idmap_uid(&low_idmap_uid, &high_idmap_uid)) {
3219                 DEBUG(0, ("cannot use ldapsam_nua without 'idmap uid' range in smb.conf!\n"));
3220                 return NT_STATUS_UNSUCCESSFUL;
3221         }
3222
3223         /* We know these gids can't turn up as allogorithmic RIDs */
3224         if (!lp_idmap_gid(&low_idmap_gid, &high_idmap_gid)) {
3225                 DEBUG(0, ("cannot use ldapsam_nua without 'wibnind gid' range in smb.conf!\n"));
3226                 return NT_STATUS_UNSUCCESSFUL;
3227         }
3228
3229         ldap_state->low_allocated_user_rid=fallback_pdb_uid_to_user_rid(low_idmap_uid);
3230
3231         ldap_state->high_allocated_user_rid=fallback_pdb_uid_to_user_rid(high_idmap_uid);
3232
3233         ldap_state->low_allocated_group_rid=pdb_gid_to_group_rid(low_idmap_gid);
3234
3235         ldap_state->high_allocated_group_rid=pdb_gid_to_group_rid(high_idmap_gid);
3236
3237         return NT_STATUS_OK;
3238 }
3239
3240 NTSTATUS pdb_ldap_init(void)
3241 {
3242         NTSTATUS nt_status;
3243         if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam", pdb_init_ldapsam)))
3244                 return nt_status;
3245
3246         if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat)))
3247                 return nt_status;
3248
3249         return NT_STATUS_OK;
3250 }