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