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