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