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