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