merge of get_dc_name()-like code from APP_HEAD; better support password server =...
[ira/wip.git] / source3 / sam / sam_ads.c
1 /*
2   Unix SMB/CIFS implementation.
3   Active Directory SAM backend, for simulate a W2K DC in mixed mode.
4
5   Copyright (C) Stefan (metze) Metzmacher       2002
6   Copyright (C) Andrew Bartlett         2002
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24
25
26 #ifdef HAVE_LDAP
27
28 static int sam_ads_debug_level = DBGC_SAM;
29
30 #undef DBGC_CLASS
31 #define DBGC_CLASS sam_ads_debug_level
32
33 #ifndef FIXME
34 #define FIXME( body ) { DEBUG(0,("FIXME: "));\
35                         DEBUGADD(0,(body));}
36 #endif
37
38 #define ADS_STATUS_OK ADS_ERROR(0)
39 #define ADS_STATUS_UNSUCCESSFUL ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL)
40 #define ADS_STATUS_NOT_IMPLEMENTED ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED)
41
42
43 #define ADS_SUBTREE_BUILTIN     "CN=Builtin,"
44 #define ADS_SUBTREE_COMPUTERS   "CN=Computers,"
45 #define ADS_SUBTREE_DC          "CN=Domain Controllers,"
46 #define ADS_SUBTREE_USERS       "CN=Users,"
47 #define ADS_ROOT_TREE           ""
48 /* Here are private module structs and functions */
49
50 typedef struct sam_ads_privates {
51         ADS_STRUCT      *ads_struct;
52         TALLOC_CTX      *mem_ctx;
53         BOOL            bind_plaintext;
54         char            *ads_bind_dn;
55         char            *ads_bind_pw;
56         char            *ldap_uri;
57         /* did we need something more? */
58 }SAM_ADS_PRIVATES;
59
60
61 /* get only these LDAP attributes, witch we really need for an account */
62 const char *account_attrs[] = { "objectSid",
63                                 "objectGUID", 
64                                 "sAMAccountType",
65                                 "sAMAcountName",
66                                 "userPrincipalName",
67                                 "accountExpires",
68                                 "badPasswordTime",
69                                 "badPwdCount",
70                                 "lastLogoff",
71                                 "lastLogon",
72                                 "userWorkstations",
73                                 "dBCSPwd",
74                                 "unicodePwd",
75                                 "pwdLastSet",
76                                 "userAccountControl",
77                                 "profilePath",
78                                 "homeDrive",
79                                 "scriptPath",
80                                 "homeDirectory",
81                                 "cn",
82                                 "primaryGroupID",/* 513 */
83                                 "nsNPAllowDialIn",/* TRUE */
84                                 "userParameters",/* Dial Back number ...*/
85                                 "codePage",/* 0 */
86                                 "countryCode",/* 0 */
87                                 "adminCount",/* 1 or 0 */
88                                 "logonCount",/* 0 */
89                                 "managedObjects",
90                                 "memberOf",/* dn */
91                                 "instanceType",/* 4 */
92                                 "name", /* sync with cn */
93                                 "description",
94                                 /* "nTSecurityDescriptor", */
95                                 NULL};
96                         
97 /* get only these LDAP attributes, witch we really need for a group */                  
98 const char *group_attrs[] = {"objectSid",
99                              /* "objectGUID", */ 
100                              "sAMAccountType",
101                              "sAMAcountName",
102                              "groupType",
103                              /* "member", */
104                              "description",
105                              "name", /* sync with cn */
106                              /* "nTSecurityDescriptor", */
107                              NULL};
108                         
109
110 /***************************************************
111   return our ads connection. We keep the connection
112   open to make things faster
113 ****************************************************/
114 static ADS_STATUS sam_ads_cached_connection(SAM_ADS_PRIVATES *privates)
115 {
116         ADS_STRUCT      *ads_struct;
117         ADS_STATUS      ads_status;
118         
119         if (!privates->ads_struct) {
120                 privates->ads_struct = ads_init_simple();
121                 ads_struct = privates->ads_struct;
122                 ads_struct->server.ldap_uri = smb_xstrdup(privates->ldap_uri);
123                 if ((!privates->ads_bind_dn) || (!*privates->ads_bind_dn)) {
124                         ads_struct->auth.flags |= ADS_AUTH_ANON_BIND;
125                 } else {
126                         ads_struct->auth.user_name 
127                                 = smb_xstrdup(privates->ads_bind_dn);
128                         if (privates->ads_bind_pw) {
129                                 ads_struct->auth.password 
130                                         = smb_xstrdup(privates->ads_bind_pw);
131                         }
132                 }
133                 if (privates->bind_plaintext) {
134                         ads_struct->auth.flags |= ADS_AUTH_SIMPLE_BIND;
135                 }
136         } else {
137                 ads_struct = privates->ads_struct;
138         }
139
140         if (ads_struct->ld != NULL) {           
141                 /* connection has been opened. ping server. */
142                 struct sockaddr_un addr;
143                 socklen_t len;
144                 int sd;
145                 if (ldap_get_option(ads_struct->ld, LDAP_OPT_DESC, &sd) == 0 &&
146                     getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
147                         /* the other end has died. reopen. */
148                         ldap_unbind_ext(ads_struct->ld, NULL, NULL);
149                         ads_struct->ld = NULL;
150                 }
151         }
152
153         if (ads_struct->ld != NULL) {
154                 DEBUG(5,("sam_ads_cached_connection: allready connected to the LDAP server\n"));
155                 return ADS_SUCCESS;
156         }
157
158         ads_status = ads_connect(ads_struct);
159
160         ads_status = ads_server_info(ads_struct);
161         if (!ADS_ERR_OK(ads_status)) {
162                 DEBUG(0,("Can't set server info: %s\n",ads_errstr(ads_status)));
163                 /* return ads_status; */ FIXME("for now we only warn!\n");
164         }
165
166         DEBUG(2, ("sam_ads_cached_connection: succesful connection to the LDAP server\n"));
167         return ADS_SUCCESS;
168 }
169
170 static ADS_STATUS sam_ads_do_search(SAM_ADS_PRIVATES *privates, const char *bind_path, int scope, const char *exp, const char **attrs, void **res)
171 {
172         ADS_STATUS      ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
173         
174         ads_status = sam_ads_cached_connection(privates);
175         if (!ADS_ERR_OK(ads_status))
176                 return ads_status;
177                 
178         return ads_do_search_retry(privates->ads_struct, bind_path, scope, exp, attrs, res);            
179 }
180
181
182 /*********************************************
183 here we have to check the update serial number
184  - this is the core of the ldap cache
185 *********************************************/
186 static ADS_STATUS sam_ads_usn_is_valid(SAM_ADS_PRIVATES *privates, uint32 usn_in, uint32 *usn_out)
187 {
188         ADS_STATUS      ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
189
190         SAM_ASSERT(privates && privates->ads_struct && usn_out);
191
192         ads_status = ads_USN(privates->ads_struct, usn_out);
193         if (!ADS_ERR_OK(ads_status))
194                 return ads_status;      
195         
196         if (*usn_out == usn_in)
197                 return ADS_SUCCESS;
198                 
199         return ads_status;      
200 }
201
202 /***********************************************
203 Initialize SAM_ACCOUNT_HANDLE from an ADS query
204 ************************************************/
205 /* not ready :-( */
206 static ADS_STATUS ads_entry2sam_account_handle(SAM_ADS_PRIVATES *privates, SAM_ACCOUNT_HANDLE *account ,void *msg)
207 {
208         ADS_STATUS      ads_status = ADS_ERROR_NT(NT_STATUS_NO_SUCH_USER);
209         NTSTATUS        nt_status = NT_STATUS_NO_SUCH_USER;
210         ADS_STRUCT      *ads_struct = privates->ads_struct;
211         TALLOC_CTX      *mem_ctx = account->mem_ctx;
212         char            *tmp_str = NULL;
213         
214         SAM_ASSERT(privates && ads_struct && account && mem_ctx && msg);
215
216         FIXME("should we really use ads_pull_username()(or ads_pull_string())?\n");
217         if ((account->private.account_name = ads_pull_username(ads_struct, mem_ctx, msg))==NULL) {
218                 DEBUG(0,("ads_pull_username failed\n"));
219                 return ADS_ERROR_NT(NT_STATUS_NO_SUCH_USER);
220         }
221         
222         if ((account->private.full_name = ads_pull_string(ads_struct, mem_ctx, msg,"name"))==NULL) {
223                 DEBUG(3,("ads_pull_string for 'name' failed - skip\n"));
224         }
225         
226         if ((account->private.acct_desc = ads_pull_string(ads_struct, mem_ctx, msg,"description"))!=NULL) {
227                 DEBUG(3,("ads_pull_string for 'acct_desc' failed - skip\n"));
228         }
229         
230         if ((account->private.home_dir = ads_pull_string(ads_struct, mem_ctx, msg,"homeDirectory"))!=NULL) {
231                 DEBUG(3,("ads_pull_string for 'homeDirectory' failed - skip\n"));
232         }
233         
234         if ((account->private.dir_drive = ads_pull_string(ads_struct, mem_ctx, msg,"homeDrive"))!=NULL) {
235                 DEBUG(3,("ads_pull_string for 'homeDrive' failed - skip\n"));
236         }
237         
238         if ((account->private.profile_path = ads_pull_string(ads_struct, mem_ctx, msg,"profilePath"))!=NULL) {
239                 DEBUG(3,("ads_pull_string for 'profilePath' failed - skip\n"));
240         }
241         
242         if ((account->private.logon_script = ads_pull_string(ads_struct, mem_ctx, msg,"scriptPath"))!=NULL) {
243                 DEBUG(3,("ads_pull_string for 'scriptPath' failed - skip\n"));
244         }
245         
246         FIXME("check 'nsNPAllowDialIn' for munged_dial!\n");
247         if ((account->private.munged_dial = ads_pull_string(ads_struct, mem_ctx, msg,"userParameters"))!=NULL) {
248                 DEBUG(3,("ads_pull_string for 'userParameters' failed - skip\n"));
249         }
250         
251         if ((account->private.unix_home_dir = ads_pull_string(ads_struct, mem_ctx, msg,"msSFUHomeDrirectory"))!=NULL) {
252                 DEBUG(3,("ads_pull_string for 'msSFUHomeDrirectory' failed - skip\n"));
253         }
254
255 #if 0
256         FIXME("use function intern mem_ctx for pwdLastSet\n");
257         if ((tmp_str = ads_pull_string(ads_struct, mem_ctx, msg,"pwdLastSet"))!=NULL) {
258                 DEBUG(3,("ads_pull_string for 'pwdLastSet' failed - skip\n"));
259         } else {
260                 account->private.pass_last_set_time = ads_parse_nttime(tmp_str);
261                 tmp_str = NULL;
262                 
263         }       
264 #endif
265
266 #if 0
267 typedef struct sam_account_handle {
268         TALLOC_CTX *mem_ctx;
269         uint32 access_granted;
270         const struct sam_methods *current_sam_methods; /* sam_methods creating this handle */
271         void (*free_fn)(struct sam_account_handle **);
272         struct sam_account_data {
273                 uint32 init_flag;
274                 NTTIME logon_time; /* logon time */
275                 NTTIME logoff_time; /* logoff time */
276                 NTTIME kickoff_time; /* kickoff time */
277                 NTTIME pass_last_set_time; /* password last set time */
278                 NTTIME pass_can_change_time; /* password can change time */
279                 NTTIME pass_must_change_time; /* password must change time */
280                 char * account_name; /* account_name string */
281                 SAM_DOMAIN_HANDLE * domain; /* domain of account */
282                 char *full_name; /* account's full name string */
283                 char *unix_home_dir; /* UNIX home directory string */
284                 char *home_dir; /* home directory string */
285                 char *dir_drive; /* home directory drive string */
286                 char *logon_script; /* logon script string */
287                 char *profile_path; /* profile path string */
288                 char *acct_desc; /* account description string */
289                 char *workstations; /* login from workstations string */
290                 char *unknown_str; /* don't know what this is, yet. */
291                 char *munged_dial; /* munged path name and dial-back tel number */
292                 DOM_SID account_sid; /* Primary Account SID */
293                 DOM_SID group_sid; /* Primary Group SID */
294                 DATA_BLOB lm_pw; /* .data is Null if no password */
295                 DATA_BLOB nt_pw; /* .data is Null if no password */
296                 char *plaintext_pw; /* if Null not available */
297                 uint16 acct_ctrl; /* account info (ACB_xxxx bit-mask) */
298                 uint32 unknown_1; /* 0x00ff ffff */
299                 uint16 logon_divs; /* 168 - number of hours in a week */
300                 uint32 hours_len; /* normally 21 bytes */
301                 uint8 hours[MAX_HOURS_LEN];
302                 uint32 unknown_2; /* 0x0002 0000 */
303                 uint32 unknown_3; /* 0x0000 04ec */
304         } private;
305 } SAM_ACCOUNT_HANDLE;
306 #endif
307
308         return ads_status;
309 }
310
311
312 /***********************************************
313 Initialize SAM_GROUP_ENUM from an ads entry
314 ************************************************/
315 /* not ready :-( */
316 static ADS_STATUS ads_entry2sam_group_enum(SAM_ADS_PRIVATES *privates, TALLOC_CTX *mem_ctx, SAM_GROUP_ENUM **group_enum,const void *entry)
317 {
318         ADS_STATUS      ads_status = ADS_STATUS_UNSUCCESSFUL;
319         ADS_STRUCT      *ads_struct = privates->ads_struct;
320         SAM_GROUP_ENUM  __group_enum;
321         SAM_GROUP_ENUM  *_group_enum = &__group_enum;
322         
323         SAM_ASSERT(privates && ads_struct && mem_ctx && group_enum && entry);
324         
325         *group_enum = _group_enum;
326         
327         DEBUG(3,("sam_ads: ads_entry2sam_account_handle\n"));
328
329         if (!ads_pull_sid(ads_struct, &entry, "objectSid", &(_group_enum->sid))) {
330                 DEBUG(0,("No sid for!?\n"));
331                 return ADS_STATUS_UNSUCCESSFUL;
332         }
333         
334         if (!(_group_enum->group_name = ads_pull_string(ads_struct, mem_ctx, &entry, "sAMAccountName"))) {
335                 DEBUG(0,("No groupname found"));
336                 return ADS_STATUS_UNSUCCESSFUL;
337         }
338
339         if (!(_group_enum->group_desc = ads_pull_string(ads_struct, mem_ctx, &entry, "desciption"))) {
340                 DEBUG(0,("No description found"));
341                 return ADS_STATUS_UNSUCCESSFUL;
342         }       
343
344         DEBUG(0,("sAMAccountName: %s\ndescription: %s\nobjectSid: %s\n",
345                  _group_enum->group_name,
346                  _group_enum->group_desc,
347                  sid_string_static(&(_group_enum->sid))
348                       ));
349         
350         return ads_status;
351 }
352
353 static ADS_STATUS sam_ads_access_check(SAM_ADS_PRIVATES *privates, const SEC_DESC *sd, const NT_USER_TOKEN *access_token, uint32 access_desired, uint32 *acc_granted)
354 {
355         ADS_STATUS      ads_status = ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
356         NTSTATUS        nt_status;
357         uint32          my_acc_granted;
358
359         SAM_ASSERT(privates && sd && access_token);
360         /* acc_granted can be set to NULL */
361         
362         /* the steps you need are: 
363            1. get_sec_desc for sid 
364            2. se_map_generic(accessdesired, generic_mapping) 
365            3. se_access_check() */
366
367         if (!se_access_check(sd, access_token, access_desired, (acc_granted)?acc_granted:&my_acc_granted, &nt_status)) {
368                 DEBUG(3,("sam_ads_access_check: ACCESS DENIED\n"));
369                 ads_status = ADS_ERROR_NT(nt_status);
370                 return ads_status;
371         }
372         ads_status = ADS_ERROR_NT(nt_status);   
373         return ads_status;
374 }
375
376 static ADS_STATUS sam_ads_get_tree_sec_desc(SAM_ADS_PRIVATES *privates, const char *subtree, SEC_DESC **sd)
377 {
378         ADS_STATUS              ads_status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
379         ADS_STRUCT              *ads_struct = privates->ads_struct;
380         TALLOC_CTX              *mem_ctx = privates->mem_ctx;
381         char                    *search_path;
382         void                    *sec_desc_res;
383         void                    *sec_desc_msg;
384         const char              *sec_desc_attrs[] = {"nTSecurityDescriptor",NULL};
385                 
386         SAM_ASSERT(privates && ads_struct && mem_ctx && sd);
387         *sd = NULL;
388                 
389         if (subtree) {
390                 asprintf(&search_path, "%s%s",subtree,ads_struct->config.bind_path);
391         } else {
392                 asprintf(&search_path, "%s","");
393         }
394         ads_status = sam_ads_do_search(privates, search_path, LDAP_SCOPE_BASE, "(objectClass=*)", sec_desc_attrs, &sec_desc_res);
395         SAFE_FREE(search_path);
396         if (!ADS_ERR_OK(ads_status))
397                 return ads_status;
398                 
399         if ((sec_desc_msg = ads_first_entry(ads_struct, sec_desc_res))==NULL) {
400                 ads_status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
401                 return ads_status;              
402         }               
403                         
404         if (!ads_pull_sd(ads_struct, mem_ctx, sec_desc_msg, sec_desc_attrs[0], sd)) {
405                 *sd = NULL;
406                 ads_status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
407                 return ads_status;
408         }               
409         
410         return ads_status;      
411 }
412
413 static ADS_STATUS sam_ads_account_policy_get(SAM_ADS_PRIVATES *privates, int field, uint32 *value)
414 {
415         ADS_STATUS              ads_status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
416         ADS_STRUCT              *ads_struct = privates->ads_struct;
417         void                    *ap_res;
418         void                    *ap_msg;
419         const char              *ap_attrs[] = {"minPwdLength",/* AP_MIN_PASSWORD_LEN */
420                                                 "pwdHistoryLength",/* AP_PASSWORD_HISTORY */
421                                                 "AP_USER_MUST_LOGON_TO_CHG_PASS",/* AP_USER_MUST_LOGON_TO_CHG_PASS */
422                                                 "maxPwdAge",/* AP_MAX_PASSWORD_AGE */
423                                                 "minPwdAge",/* AP_MIN_PASSWORD_AGE */
424                                                 "lockoutDuration",/* AP_LOCK_ACCOUNT_DURATION */
425                                                 "AP_RESET_COUNT_TIME",/* AP_RESET_COUNT_TIME */
426                                                 "AP_BAD_ATTEMPT_LOCKOUT",/* AP_BAD_ATTEMPT_LOCKOUT */
427                                                 "AP_TIME_TO_LOGOUT",/* AP_TIME_TO_LOGOUT */
428                                                 NULL};
429                                                 /*lockOutObservationWindow 
430                                                 lockoutThreshold $ pwdProperties*/
431         static uint32           ap[9];
432         static uint32           ap_usn = 0;
433         uint32                  tmp_usn = 0;
434
435         SAM_ASSERT(privates && ads_struct && value);
436         
437         FIXME("We need to decode all account_policy attributes!\n");
438         
439         ads_status = sam_ads_usn_is_valid(privates,ap_usn,&tmp_usn);
440         if (!ADS_ERR_OK(ads_status)) {
441                 ads_status = sam_ads_do_search(privates, ads_struct->config.bind_path, LDAP_SCOPE_BASE, "(objectClass=*)", ap_attrs, &ap_res);
442                 if (!ADS_ERR_OK(ads_status))
443                         return ads_status; 
444                 
445                 if (ads_count_replies(ads_struct, ap_res) != 1) {
446                         ads_msgfree(ads_struct, ap_res);
447                         return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
448                 }
449
450                 if (!(ap_msg = ads_first_entry(ads_struct, ap_res))) {
451                         ads_msgfree(ads_struct, ap_res);
452                         return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
453                 }
454                 
455                 if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[0], &ap[0])) {
456                         /* AP_MIN_PASSWORD_LEN */
457                         ap[0] = MINPASSWDLENGTH;/* 5 chars minimum */
458                 }
459                 if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[1], &ap[1])) {
460                         /* AP_PASSWORD_HISTORY */
461                         ap[1] = 0;/* don't keep any old password */
462                 }
463                 if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[2], &ap[2])) {
464                         /* AP_USER_MUST_LOGON_TO_CHG_PASS */
465                         ap[2] = 0;/* don't force user to logon */
466                 }
467                 if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[3], &ap[3])) {
468                         /* AP_MAX_PASSWORD_AGE */
469                         ap[3] = MAX_PASSWORD_AGE;/* 21 days */
470                 }
471                 if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[4], &ap[4])) {
472                         /* AP_MIN_PASSWORD_AGE */
473                         ap[4] = 0;/* 0 days */
474                 }               
475                 if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[5], &ap[5])) {
476                         /* AP_LOCK_ACCOUNT_DURATION */
477                         ap[5] = 0;/* lockout for 0 minutes */
478                 }
479                 if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[6], &ap[6])) {
480                         /* AP_RESET_COUNT_TIME */
481                         ap[6] = 0;/* reset immediatly */
482                 }
483                 if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[7], &ap[7])) {
484                         /* AP_BAD_ATTEMPT_LOCKOUT */
485                         ap[7] = 0;/* don't lockout */
486                 }
487                 if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[8], &ap[8])) {
488                         /* AP_TIME_TO_LOGOUT */
489                         ap[8] = -1;/* don't force logout */
490                 }
491                 
492                 ads_msgfree(ads_struct, ap_res);
493                 ap_usn = tmp_usn;
494         }
495
496         switch(field) {
497                 case AP_MIN_PASSWORD_LEN:
498                         *value = ap[0];
499                         ads_status = ADS_ERROR_NT(NT_STATUS_OK);
500                         break;
501                 case AP_PASSWORD_HISTORY:
502                         *value = ap[1];
503                         ads_status = ADS_ERROR_NT(NT_STATUS_OK);
504                         break;
505                 case AP_USER_MUST_LOGON_TO_CHG_PASS:
506                         *value = ap[2];
507                         ads_status = ADS_ERROR_NT(NT_STATUS_OK);
508                         break;
509                 case AP_MAX_PASSWORD_AGE:
510                         *value = ap[3];
511                         ads_status = ADS_ERROR_NT(NT_STATUS_OK);
512                         break;
513                 case AP_MIN_PASSWORD_AGE:
514                         *value = ap[4];
515                         ads_status = ADS_ERROR_NT(NT_STATUS_OK);
516                         break;
517                 case AP_LOCK_ACCOUNT_DURATION:
518                         *value = ap[5];
519                         ads_status = ADS_ERROR_NT(NT_STATUS_OK);
520                         break;
521                 case AP_RESET_COUNT_TIME:
522                         *value = ap[6];
523                         ads_status = ADS_ERROR_NT(NT_STATUS_OK);
524                         break;
525                 case AP_BAD_ATTEMPT_LOCKOUT:
526                         *value = ap[7];
527                         ads_status = ADS_ERROR_NT(NT_STATUS_OK);
528                         break;
529                 case AP_TIME_TO_LOGOUT:
530                         *value = ap[8];
531                         ads_status = ADS_ERROR_NT(NT_STATUS_OK);
532                         break;
533                 default: *value = 0; break;
534         }
535         
536         return ads_status;      
537 }
538
539
540 /**********************************
541 Now the functions off the SAM API 
542 ***********************************/
543
544 /* General API */
545 static NTSTATUS sam_ads_get_sec_desc(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, 
546                               const DOM_SID *sid, SEC_DESC **sd)
547 {
548         ADS_STATUS              ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
549         SAM_ADS_PRIVATES        *privates = (struct sam_ads_privates *)sam_method->private_data;
550         ADS_STRUCT              *ads_struct = privates->ads_struct;
551         TALLOC_CTX              *mem_ctx;
552         char                    *sidstr,*filter;
553         void                    *sec_desc_res;
554         void                    *sec_desc_msg;
555         const char              *sec_desc_attrs[] = {"nTSecurityDescriptor",NULL};
556         fstring                 sid_str;
557         SEC_DESC                *my_sd;
558
559         SAM_ASSERT(sam_method && access_token && sid && sd);    
560         
561         ads_status = sam_ads_get_tree_sec_desc(privates, ADS_ROOT_TREE, &my_sd);
562         if (!ADS_ERR_OK(ads_status))
563                 return ads_ntstatus(ads_status);
564
565         ads_status = sam_ads_access_check(privates, my_sd, access_token, GENERIC_RIGHTS_DOMAIN_READ, NULL);
566
567         if (!ADS_ERR_OK(ads_status))
568                 return ads_ntstatus(ads_status);
569
570         sidstr = sid_binstring(sid);
571         if (asprintf(&filter, "(objectSid=%s)", sidstr) == -1) {
572                 SAFE_FREE(sidstr);
573                 return NT_STATUS_NO_MEMORY;
574         }
575
576         SAFE_FREE(sidstr);
577
578         ads_status = sam_ads_do_search(privates,ads_struct->config.bind_path, 
579                                        LDAP_SCOPE_SUBTREE, filter, sec_desc_attrs,
580                                        &sec_desc_res);
581         SAFE_FREE(filter);
582
583         if (!ADS_ERR_OK(ads_status)) {
584                 return ads_ntstatus(ads_status);
585         }
586
587         if (!(mem_ctx = talloc_init_named("sec_desc parse in sam_ads"))) {
588                 DEBUG(1, ("talloc_init_named() failed for sec_desc parse context in sam_ads"));
589                 ads_msgfree(ads_struct, sec_desc_res);
590                 return NT_STATUS_NO_MEMORY;
591         }
592
593         if (ads_count_replies(ads_struct, sec_desc_res) != 1) {
594                 DEBUG(1,("sam_ads_get_sec_desc: duplicate or 0 results for sid %s\n", 
595                          sid_to_string(sid_str, sid)));
596                 talloc_destroy(mem_ctx);
597                 ads_msgfree(ads_struct, sec_desc_res);
598                 return NT_STATUS_UNSUCCESSFUL;
599         }
600
601         if (!(sec_desc_msg = ads_first_entry(ads_struct, sec_desc_res))) {
602                 talloc_destroy(mem_ctx);
603                 ads_msgfree(ads_struct, sec_desc_res);
604                 return NT_STATUS_INVALID_PARAMETER;
605         }               
606                         
607         if (!ads_pull_sd(ads_struct, mem_ctx, sec_desc_msg, sec_desc_attrs[0], sd)) {
608                 ads_status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
609                 talloc_destroy(mem_ctx);
610                 ads_msgfree(ads_struct, sec_desc_res);
611                 return ads_ntstatus(ads_status);
612         }        
613         
614         /* now, were we allowed to see the SD we just got? */
615
616         ads_msgfree(ads_struct, sec_desc_res);
617         talloc_destroy(mem_ctx);
618         return ads_ntstatus(ads_status);
619 }
620
621 static NTSTATUS sam_ads_set_sec_desc(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, 
622                               const DOM_SID *sid, const SEC_DESC *sd)
623 {
624         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
625         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
626         SAM_ASSERT(sam_method);
627         return ads_ntstatus(ads_status);
628 }
629
630         
631 static NTSTATUS sam_ads_lookup_sid(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, 
632                             TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **name, 
633                             enum SID_NAME_USE *type)
634 {
635         ADS_STATUS              ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
636         SAM_ADS_PRIVATES        *privates = (struct sam_ads_privates *)sam_method->private_data;
637         ADS_STRUCT              *ads_struct = privates->ads_struct;
638         SEC_DESC                *my_sd;
639
640         SAM_ASSERT(sam_method && access_token && mem_ctx && sid && name && type);
641
642         ads_status = sam_ads_get_tree_sec_desc(privates, ADS_ROOT_TREE, &my_sd);        
643         if (!ADS_ERR_OK(ads_status))
644                 return ads_ntstatus(ads_status);
645
646         ads_status = sam_ads_access_check(privates, my_sd, access_token, GENERIC_RIGHTS_DOMAIN_READ, NULL);
647         if (!ADS_ERR_OK(ads_status))
648                 return ads_ntstatus(ads_status);
649
650         return ads_sid_to_name(ads_struct, mem_ctx, sid, name, type);
651 }
652
653 static NTSTATUS sam_ads_lookup_name(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, 
654                              const char *name, DOM_SID *sid, enum SID_NAME_USE *type)
655 {
656         ADS_STATUS              ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
657         SAM_ADS_PRIVATES        *privates = (struct sam_ads_privates *)sam_method->private_data;
658         ADS_STRUCT              *ads_struct = privates->ads_struct;
659         SEC_DESC                *my_sd;
660
661         SAM_ASSERT(sam_method && access_token && name && sid && type);
662
663         ads_status = sam_ads_get_tree_sec_desc(privates, ADS_ROOT_TREE, &my_sd);
664         if (!ADS_ERR_OK(ads_status))
665                 return ads_ntstatus(ads_status);
666
667         ads_status = sam_ads_access_check(privates, my_sd, access_token, GENERIC_RIGHTS_DOMAIN_READ, NULL);
668         if (!ADS_ERR_OK(ads_status))
669                 return ads_ntstatus(ads_status);
670
671         return ads_name_to_sid(ads_struct, name, sid, type);
672 }
673
674         
675 /* Domain API */
676
677 static NTSTATUS sam_ads_update_domain(const SAM_METHODS *sam_method, const SAM_DOMAIN_HANDLE *domain)
678 {
679         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
680         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
681         SAM_ASSERT(sam_method);
682         return ads_ntstatus(ads_status);
683 }
684
685 static NTSTATUS sam_ads_get_domain_handle(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, 
686                                    const uint32 access_desired, SAM_DOMAIN_HANDLE **domain)
687 {
688         ADS_STATUS              ads_status = ADS_STATUS_NOT_IMPLEMENTED;
689         SAM_ADS_PRIVATES        *privates = (struct sam_ads_privates *)sam_method->private_data;
690         TALLOC_CTX              *mem_ctx = privates->mem_ctx;   /*Fix me is this right??? */
691         SAM_DOMAIN_HANDLE       *dom_handle = NULL;
692         SEC_DESC                *sd;
693         uint32                  acc_granted;
694         uint32                  tmp_value;
695
696         DEBUG(5,("sam_ads_get_domain_handle: %d\n",__LINE__));
697         
698         SAM_ASSERT(sam_method && access_token && domain);
699         
700         (*domain) = NULL;
701
702         if ((dom_handle = talloc(mem_ctx, sizeof(SAM_DOMAIN_HANDLE))) == NULL) {
703                 DEBUG(0,("failed to talloc dom_handle\n"));
704                         ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
705                         return ads_ntstatus(ads_status);
706         }
707
708         ZERO_STRUCTP(dom_handle);
709
710         dom_handle->mem_ctx = mem_ctx; /*Fix me is this right??? */
711         dom_handle->free_fn = NULL;
712         dom_handle->current_sam_methods = sam_method;
713
714         /* check if access can be granted as requested */
715
716         ads_status = sam_ads_get_tree_sec_desc(privates, ADS_ROOT_TREE, &sd);
717         if (!ADS_ERR_OK(ads_status))
718                 return ads_ntstatus(ads_status);
719
720         ads_status = sam_ads_access_check(privates, sd, access_token, access_desired, &acc_granted);
721         if (!ADS_ERR_OK(ads_status))
722                 return ads_ntstatus(ads_status);
723
724         dom_handle->access_granted = acc_granted;
725
726         /* fill all the values of dom_handle */
727         sid_copy(&dom_handle->private.sid, &sam_method->domain_sid);
728         dom_handle->private.name       = smb_xstrdup(sam_method->domain_name);
729         dom_handle->private.servername = "WHOKNOWS"; /* what is the servername */
730
731         /*Fix me: sam_ads_account_policy_get() return ADS_STATUS! */ 
732         ads_status = sam_ads_account_policy_get(privates, AP_MAX_PASSWORD_AGE, &tmp_value);
733         if (!ADS_ERR_OK(ads_status)) {
734                 DEBUG(4,("sam_ads_account_policy_get failed for max password age. Useing default\n"));
735                 tmp_value = MAX_PASSWORD_AGE;
736         }
737         unix_to_nt_time_abs(&dom_handle->private.max_passwordage,tmp_value);
738
739         ads_status = sam_ads_account_policy_get(privates, AP_MIN_PASSWORD_AGE, &tmp_value);
740         if (!ADS_ERR_OK(ads_status)) {
741                 DEBUG(4,("sam_ads_account_policy_get failed for min password age. Useing default\n"));
742                 tmp_value = 0;
743         }
744         unix_to_nt_time_abs(&dom_handle->private.min_passwordage, tmp_value);
745
746         ads_status = sam_ads_account_policy_get(privates, AP_LOCK_ACCOUNT_DURATION, &tmp_value);
747         if (!ADS_ERR_OK(ads_status)) {
748                 DEBUG(4,("sam_ads_account_policy_get failed for lockout duration. Useing default\n"));
749                 tmp_value = 0;
750         }
751         unix_to_nt_time_abs(&dom_handle->private.lockout_duration, tmp_value);
752
753         ads_status = sam_ads_account_policy_get(privates, AP_RESET_COUNT_TIME, &tmp_value);
754         if (!ADS_ERR_OK(ads_status)) {
755                 DEBUG(4,("sam_ads_account_policy_get failed for time till locout count is reset. Useing default\n"));
756                 tmp_value = 0;
757         }
758         unix_to_nt_time_abs(&dom_handle->private.reset_count, tmp_value);
759
760         ads_status = sam_ads_account_policy_get(privates, AP_MIN_PASSWORD_LEN, &tmp_value);
761         if (!ADS_ERR_OK(ads_status)) {
762                 DEBUG(4,("sam_ads_account_policy_get failed for min password length. Useing default\n"));
763                 tmp_value = 0;
764         }
765         dom_handle->private.min_passwordlength = (uint16)tmp_value;
766
767         ads_status = sam_ads_account_policy_get(privates, AP_PASSWORD_HISTORY, &tmp_value);
768         if (!ADS_ERR_OK(ads_status)) {
769                 DEBUG(4,("sam_ads_account_policy_get failed password history. Useing default\n"));
770                 tmp_value = 0;
771         }
772         dom_handle->private.password_history = (uint16)tmp_value;
773
774         ads_status = sam_ads_account_policy_get(privates, AP_BAD_ATTEMPT_LOCKOUT, &tmp_value);
775         if (!ADS_ERR_OK(ads_status)) {
776                 DEBUG(4,("sam_ads_account_policy_get failed for bad attempts till lockout. Useing default\n"));
777                 tmp_value = 0;
778         }
779         dom_handle->private.lockout_count = (uint16)tmp_value;
780
781         ads_status = sam_ads_account_policy_get(privates, AP_TIME_TO_LOGOUT, &tmp_value);
782         if (!ADS_ERR_OK(ads_status)) {
783                 DEBUG(4,("sam_ads_account_policy_get failed for force logout. Useing default\n"));
784                 tmp_value = -1;
785         }
786
787         ads_status = sam_ads_account_policy_get(privates, AP_USER_MUST_LOGON_TO_CHG_PASS, &tmp_value);
788         if (!ADS_ERR_OK(ads_status)) {
789                 DEBUG(4,("sam_ads_account_policy_get failed for user must login to change password. Useing default\n"));
790                 tmp_value = 0;
791         }
792
793         /* should the real values of num_accounts, num_groups and num_aliases be retreved?
794          * I think it is to expensive to bother
795          */
796         dom_handle->private.num_accounts = 3;
797         dom_handle->private.num_groups   = 4;
798         dom_handle->private.num_aliases  = 5;
799
800         *domain = dom_handle;
801         
802         ads_status = ADS_ERROR_NT(NT_STATUS_OK);
803         return ads_ntstatus(ads_status);
804 }
805
806 /* Account API */
807 static NTSTATUS sam_ads_create_account(const SAM_METHODS *sam_method, 
808                                 const NT_USER_TOKEN *access_token, uint32 access_desired, 
809                                 const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account)
810 {
811         ADS_STATUS              ads_status = ADS_STATUS_NOT_IMPLEMENTED;
812         SAM_ADS_PRIVATES        *privates = (struct sam_ads_privates *)sam_method->private_data;
813         SEC_DESC                *sd = NULL;
814         uint32                  acc_granted;
815
816         SAM_ASSERT(sam_method && privates && access_token && account_name && account);
817
818         ads_status = sam_ads_get_tree_sec_desc(privates, ADS_SUBTREE_USERS, &sd);
819         if (!ADS_ERR_OK(ads_status))
820                 return ads_ntstatus(ads_status);
821
822         ads_status = sam_ads_access_check(privates, sd, access_token, access_desired, &acc_granted);
823         if (!ADS_ERR_OK(ads_status))
824                 return ads_ntstatus(ads_status);
825
826         ads_status = ADS_ERROR_NT(sam_init_account(account));
827         if (!ADS_ERR_OK(ads_status))
828                 return ads_ntstatus(ads_status);        
829
830         (*account)->access_granted = acc_granted;
831
832         return ads_ntstatus(ads_status);
833 }
834
835 static NTSTATUS sam_ads_add_account(const SAM_METHODS *sam_method, const SAM_ACCOUNT_HANDLE *account)
836 {
837         ADS_STATUS              ads_status = ADS_ERROR(LDAP_NO_MEMORY);
838         SAM_ADS_PRIVATES        *privates = (struct sam_ads_privates *)sam_method->private_data;
839         ADS_STRUCT              *ads_struct = privates->ads_struct;
840         TALLOC_CTX              *mem_ctx = privates->mem_ctx;
841         ADS_MODLIST             mods;
842         uint16                  acct_ctrl;
843         char                    *new_dn;
844         SEC_DESC                *sd;
845         uint32                  acc_granted;
846
847         SAM_ASSERT(sam_method && account);
848         
849         ads_status = ADS_ERROR_NT(sam_get_account_acct_ctrl(account,&acct_ctrl));
850         if (!ADS_ERR_OK(ads_status))
851                 goto done;
852                         
853         if ((acct_ctrl & ACB_WSTRUST)||(acct_ctrl & ACB_SVRTRUST)) {
854                 /* Computer account */
855                 char            *name,*controlstr;
856                 char            *hostname,*host_upn,*host_spn;
857                 const char      *objectClass[] = {"top", "person", "organizationalPerson",
858                                                   "user", "computer", NULL};
859
860                 ads_status = ADS_ERROR_NT(sam_get_account_name(account,&name));
861                 if (!ADS_ERR_OK(ads_status))
862                         goto done;
863
864                 if (!(host_upn = talloc_asprintf(mem_ctx, "%s@%s", name, ads_struct->config.realm))) {
865                         ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
866                         goto done;
867                 }
868
869                 if (!(new_dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Computers,%s", hostname, 
870                                                ads_struct->config.bind_path))) {
871                         ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
872                         goto done;
873                 }
874                                         
875                 if (!(controlstr = talloc_asprintf(mem_ctx, "%u", ads_acb2uf(acct_ctrl)))) {
876                         ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
877                         goto done;
878                 }
879                 
880                 if (!(mods = ads_init_mods(mem_ctx))) {
881                         ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
882                         goto done;
883                 }
884                 
885                 ads_status = ads_mod_str(mem_ctx, &mods, "cn", hostname);
886                 if (!ADS_ERR_OK(ads_status))
887                         goto done;
888                 ads_status = ads_mod_strlist(mem_ctx, &mods, "objectClass", objectClass);
889                 if (!ADS_ERR_OK(ads_status))
890                         goto done;
891                 ads_status = ads_mod_str(mem_ctx, &mods, "userPrincipalName", host_upn);
892                 if (!ADS_ERR_OK(ads_status))
893                         goto done;
894                 ads_status = ads_mod_str(mem_ctx, &mods, "displayName", hostname);
895                 if (!ADS_ERR_OK(ads_status))
896                         goto done;
897                 ads_status = ads_mod_str(mem_ctx, &mods, "sAMAccountName", name);
898                 if (!ADS_ERR_OK(ads_status))
899                         goto done;
900                 ads_status = ads_mod_str(mem_ctx, &mods, "userAccountControl", controlstr);
901                 if (!ADS_ERR_OK(ads_status))
902                         goto done;      
903
904                 ads_status = ads_mod_str(mem_ctx, &mods, "servicePrincipalName", host_spn);
905                 if (!ADS_ERR_OK(ads_status))
906                         goto done;
907                 ads_status = ads_mod_str(mem_ctx, &mods, "dNSHostName", hostname);
908                 if (!ADS_ERR_OK(ads_status))
909                         goto done;
910                 ads_status = ads_mod_str(mem_ctx, &mods, "userAccountControl", controlstr);
911                 if (!ADS_ERR_OK(ads_status))
912                         goto done;
913                 /*      ads_status = ads_mod_str(mem_ctx, &mods, "operatingSystem", "Samba");
914                         if (!ADS_ERR_OK(ads_status))
915                         goto done;
916                 *//*    ads_status = ads_mod_str(mem_ctx, &mods, "operatingSystemVersion", VERSION);
917                         if (!ADS_ERR_OK(ads_status))
918                         goto done;
919                   */            
920                 /* End Computer account */
921         } else {
922                 /* User account*/
923                 char            *upn, *controlstr;
924                 char            *name, *fullname;
925                 const char      *objectClass[] = {"top", "person", "organizationalPerson",
926                                                   "user", NULL};
927
928                 ads_status = ADS_ERROR_NT(sam_get_account_name(account,&name));
929                 if (!ADS_ERR_OK(ads_status))
930                         goto done;
931
932                 ads_status = ADS_ERROR_NT(sam_get_account_fullname(account,&fullname));
933                 if (!ADS_ERR_OK(ads_status))
934                         goto done;
935
936                 if (!(upn = talloc_asprintf(mem_ctx, "%s@%s", name, ads_struct->config.realm))) {
937                         ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
938                         goto done;
939                 }
940
941                 if (!(new_dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Users,%s", fullname, 
942                                                ads_struct->config.bind_path))) {
943                         ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
944                         goto done;
945                 }
946                                         
947                 if (!(controlstr = talloc_asprintf(mem_ctx, "%u", ads_acb2uf(acct_ctrl)))) {
948                         ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
949                         goto done;
950                 }
951                 
952                 if (!(mods = ads_init_mods(mem_ctx))) {
953                         ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
954                         goto done;
955                 }
956                 
957                 ads_status = ads_mod_str(mem_ctx, &mods, "cn", fullname);
958                 if (!ADS_ERR_OK(ads_status))
959                         goto done;
960                 ads_status = ads_mod_strlist(mem_ctx, &mods, "objectClass", objectClass);
961                 if (!ADS_ERR_OK(ads_status))
962                         goto done;
963                 ads_status = ads_mod_str(mem_ctx, &mods, "userPrincipalName", upn);
964                 if (!ADS_ERR_OK(ads_status))
965                         goto done;
966                 ads_status = ads_mod_str(mem_ctx, &mods, "displayName", fullname);
967                 if (!ADS_ERR_OK(ads_status))
968                         goto done;
969                 ads_status = ads_mod_str(mem_ctx, &mods, "sAMAccountName", name);
970                 if (!ADS_ERR_OK(ads_status))
971                         goto done;
972                 ads_status = ads_mod_str(mem_ctx, &mods, "userAccountControl", controlstr);
973                 if (!ADS_ERR_OK(ads_status))
974                         goto done;      
975         }/* End User account */ 
976
977         /* Finally at the account */
978         ads_status = ads_gen_add(ads_struct, new_dn, mods);
979
980 done:
981         return ads_ntstatus(ads_status);
982 }
983
984 static NTSTATUS sam_ads_update_account(const SAM_METHODS *sam_method, const SAM_ACCOUNT_HANDLE *account)
985 {
986         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
987         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
988         SAM_ASSERT(sam_method);
989         return ads_ntstatus(ads_status);
990 }
991
992 static NTSTATUS sam_ads_delete_account(const SAM_METHODS *sam_method, const SAM_ACCOUNT_HANDLE *account)
993 {
994         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
995         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
996         SAM_ASSERT(sam_method);
997
998
999
1000         return ads_ntstatus(ads_status);
1001 }
1002
1003 static NTSTATUS sam_ads_enum_accounts(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, uint16 acct_ctrl, uint32 *account_count, SAM_ACCOUNT_ENUM **accounts)
1004 {
1005         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
1006         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
1007         SAM_ASSERT(sam_method);
1008         return ads_ntstatus(ads_status);
1009 }
1010
1011 #if 0
1012 static NTSTATUS sam_ads_get_account_by_sid(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint32 access_desired, const DOM_SID *account_sid, SAM_ACCOUNT_HANDLE **account)
1013 {
1014         ADS_STATUS              ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
1015         SAM_ADS_PRIVATES        *privates = (struct sam_ads_privates *)sam_method->private_data;
1016         ADS_STRUCT              *ads_struct = privates->ads_struct;
1017         TALLOC_CTX              *mem_ctx = privates->mem_ctx;
1018         SEC_DESC                *sd = NULL;
1019         uint32                  acc_granted;
1020                 
1021         SAM_ASSERT(sam_method && privates && ads_struct && access_token && account_sid && account);
1022
1023         ads_status = ADS_ERROR_NT(sam_ads_get_sec_desc(sam_method, access_token, account_sid, &my_sd));
1024         if (!ADS_ERR_OK(ads_status))
1025                 return ads_ntstatus(ads_status);
1026
1027         ads_status = sam_ads_access_check(privates, sd, access_token, access_desired, &acc_granted);
1028         if (!ADS_ERR_OK(ads_status))
1029                 return ads_ntstatus(ads_status);
1030
1031         ads_status = ADS_ERROR_NT(sam_init_account(account));
1032         if (!ADS_ERR_OK(ads_status))
1033                 return ads_ntstatus(ads_status);        
1034
1035         (*account)->access_granted = acc_granted;
1036
1037         return ads_ntstatus(ads_status);
1038 }
1039 #else
1040 static NTSTATUS sam_ads_get_account_by_sid(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint32 access_desired, const DOM_SID *account_sid, SAM_ACCOUNT_HANDLE **account)
1041 {
1042         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
1043         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
1044         SAM_ASSERT(sam_method);
1045         return ads_ntstatus(ads_status);
1046 }
1047 #endif
1048
1049 #if 0
1050 static NTSTATUS sam_ads_get_account_by_name(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint32 access_desired, const char *account_name, SAM_ACCOUNT_HANDLE **account)
1051 {
1052         ADS_STATUS      ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
1053         SAM_ADS_PRIVATES        *privates = (struct sam_ads_privates *)sam_method->private_data;
1054         ADS_STRUCT              *ads_struct = privates->ads_struct;
1055         TALLOC_CTX              *mem_ctx = privates->mem_ctx;
1056         SEC_DESC                *sd = NULL;
1057         uint32                  acc_granted;
1058         
1059         SAM_ASSERT(sam_method && privates && ads_struct && access_token && account_name && account);
1060
1061         ads_status = sam_ads_get_tree_sec_desc(privates, ADS_ROOT_TREE, &sd);
1062         if (!ADS_ERR_OK(ads_status))
1063                 return ads_ntstatus(ads_status);
1064
1065         ads_status = sam_ads_access_check(privates, sd, access_token, access_desired, &acc_granted);
1066         if (!ADS_ERR_OK(ads_status))
1067                 return ads_ntstatus(ads_status);
1068
1069         ads_status = ADS_ERROR_NT(sam_init_account(account));
1070         if (!ADS_ERR_OK(ads_status))
1071                 return ads_ntstatus(ads_status);        
1072
1073         (*account)->access_granted = acc_granted;
1074
1075         return ads_ntstatus(ads_status);
1076 }
1077 #else
1078 static NTSTATUS sam_ads_get_account_by_name(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint32 access_desired, const char *account_name, SAM_ACCOUNT_HANDLE **account)
1079 {
1080         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
1081         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
1082         SAM_ASSERT(sam_method);
1083         return ads_ntstatus(ads_status);
1084 }
1085 #endif
1086
1087 /* Group API */
1088 static NTSTATUS sam_ads_create_group(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *group_name, uint16 group_ctrl, SAM_GROUP_HANDLE **group)
1089 {
1090         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
1091         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
1092         SAM_ASSERT(sam_method);
1093         return ads_ntstatus(ads_status);
1094 }
1095
1096 static NTSTATUS sam_ads_add_group(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group)
1097 {
1098         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
1099         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
1100         SAM_ASSERT(sam_method);
1101         return ads_ntstatus(ads_status);
1102 }
1103
1104 static NTSTATUS sam_ads_update_group(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group)
1105 {
1106         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
1107         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
1108         SAM_ASSERT(sam_method);
1109         return ads_ntstatus(ads_status);
1110 }
1111
1112 static NTSTATUS sam_ads_delete_group(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group)
1113 {
1114         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
1115         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
1116         SAM_ASSERT(sam_method);
1117         return ads_ntstatus(ads_status);
1118 }
1119
1120 static NTSTATUS sam_ads_enum_groups(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint16 group_ctrl, uint32 *groups_count, SAM_GROUP_ENUM **groups)
1121 {
1122         ADS_STATUS              ads_status = ADS_STATUS_NOT_IMPLEMENTED;
1123         SAM_ADS_PRIVATES        *privates = (struct sam_ads_privates *)sam_method->private_data;
1124         ADS_STRUCT              *ads_struct = privates->ads_struct;
1125         TALLOC_CTX              *mem_ctx = privates->mem_ctx;
1126         void                    *res = NULL;
1127         void                    *msg = NULL;
1128         char                    *filter = NULL;
1129         int                     i = 0;
1130         
1131         /* get only these LDAP attributes, witch we really need for a group */                  
1132         const char *group_enum_attrs[] = {"objectSid",
1133                                           "description",
1134                                           "sAMAcountName",
1135                                           NULL};
1136         
1137         SAM_ASSERT(sam_method && access_token && groups_count && groups);
1138         
1139         *groups_count = 0;
1140
1141         DEBUG(3,("ads: enum_dom_groups\n"));
1142
1143         FIXME("get only group from the wanted Type!\n");
1144         asprintf(&filter, "(&(objectClass=group)(groupType=%s))", "*");
1145         ads_status = sam_ads_do_search(privates, ads_struct->config.bind_path, LDAP_SCOPE_SUBTREE, filter, group_enum_attrs, &res);
1146         if (!ADS_ERR_OK(ads_status)) {
1147                 DEBUG(1,("enum_groups ads_search: %s\n", ads_errstr(ads_status)));
1148         }
1149
1150         *groups_count = ads_count_replies(ads_struct, res);
1151         if (*groups_count == 0) {
1152                 DEBUG(1,("enum_groups: No groups found\n"));
1153         }
1154
1155         (*groups) = talloc_zero(mem_ctx, (*groups_count) * sizeof(**groups));
1156         if (!*groups) {
1157                 ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1158         }
1159
1160         for (msg = ads_first_entry(ads_struct, res); msg; msg = ads_next_entry(ads_struct, msg)) {
1161                 uint32          grouptype;
1162
1163                 if (!ads_pull_uint32(ads_struct, msg, "groupType", &grouptype)) {
1164                         ;
1165                 } else {
1166                         (*groups)->group_ctrl = ads_gtype2gcb(grouptype);
1167                 }
1168         
1169                 if (!((*groups)->group_name = ads_pull_string(ads_struct, mem_ctx, msg, "sAMAccountName"))) {
1170                         ;
1171                 }
1172                 
1173                 if (!((*groups)->group_desc = ads_pull_string(ads_struct, mem_ctx, msg, "description"))) {
1174                         ;
1175                 }
1176                 
1177                 if (!ads_pull_sid(ads_struct, msg, "objectSid", &((*groups)->sid))) {
1178                         DEBUG(1,("No sid for group %s !?\n", (*groups)->group_name));
1179                         continue;
1180                 }
1181
1182                 i++;
1183         }
1184
1185         (*groups_count) = i;
1186
1187         ads_status = ADS_ERROR_NT(NT_STATUS_OK);
1188
1189         DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*groups_count)));
1190
1191         if (res) ads_msgfree(ads_struct, res);
1192
1193         return ads_ntstatus(ads_status);
1194 }
1195
1196 static NTSTATUS sam_ads_get_group_by_sid(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint32 access_desired, const DOM_SID *groupsid, SAM_GROUP_HANDLE **group)
1197 {
1198         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
1199         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
1200         SAM_ASSERT(sam_method);
1201         return ads_ntstatus(ads_status);
1202 }
1203
1204 static NTSTATUS sam_ads_get_group_by_name(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint32 access_desired, const char *name, SAM_GROUP_HANDLE **group)
1205 {
1206         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
1207         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
1208         SAM_ASSERT(sam_method);
1209         return ads_ntstatus(ads_status);
1210 }
1211
1212 static NTSTATUS sam_ads_add_member_to_group(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member)
1213 {
1214         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
1215         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
1216         SAM_ASSERT(sam_method);
1217         return ads_ntstatus(ads_status);
1218 }
1219
1220 static NTSTATUS sam_ads_delete_member_from_group(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member)
1221 {
1222         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
1223         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
1224         SAM_ASSERT(sam_method);
1225         return ads_ntstatus(ads_status);
1226 }
1227
1228 static NTSTATUS sam_ads_enum_groupmembers(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group, uint32 *members_count, SAM_GROUP_MEMBER **members)
1229 {
1230         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
1231         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
1232         SAM_ASSERT(sam_method);
1233         return ads_ntstatus(ads_status);
1234 }
1235
1236 static NTSTATUS sam_ads_get_groups_of_sid(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const DOM_SID **sids, const uint16 group_ctrl, uint32 *group_count, SAM_GROUP_ENUM **groups)
1237 {
1238         ADS_STATUS      ads_status = ADS_STATUS_NOT_IMPLEMENTED;
1239         DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO));
1240         SAM_ASSERT(sam_method);
1241         return ads_ntstatus(ads_status);
1242 }
1243
1244 /**********************************
1245 Free our private data
1246 ***********************************/
1247 static void sam_ads_free_private_data(void **vp) 
1248 {
1249         SAM_ADS_PRIVATES **sam_ads_state = (SAM_ADS_PRIVATES **)vp;
1250
1251         if ((*sam_ads_state)->ads_struct->ld) {
1252                 ldap_unbind((*sam_ads_state)->ads_struct->ld);
1253         }
1254
1255         ads_destroy(&((*sam_ads_state)->ads_struct));
1256         
1257         talloc_destroy((*sam_ads_state)->mem_ctx);
1258         FIXME("maybe we must free some other stuff here\n");
1259
1260         *sam_ads_state = NULL;
1261 }
1262
1263
1264
1265 /*****************************************************
1266 Init the ADS SAM backend  
1267 ******************************************************/
1268 NTSTATUS sam_init_ads(SAM_METHODS *sam_method, const char *module_params)
1269 {
1270         ADS_STATUS              ads_status;
1271         SAM_ADS_PRIVATES        *sam_ads_state;
1272         TALLOC_CTX              *mem_ctx;
1273         
1274         SAM_ASSERT(sam_method && sam_method->parent);
1275         
1276         mem_ctx = sam_method->parent->mem_ctx;
1277
1278         /* Here the SAM API functions of the sam_ads module */
1279
1280         /* General API */
1281
1282         sam_method->sam_get_sec_desc = sam_ads_get_sec_desc;
1283         sam_method->sam_set_sec_desc = sam_ads_set_sec_desc;
1284         
1285         sam_method->sam_lookup_sid = sam_ads_lookup_sid;
1286         sam_method->sam_lookup_name = sam_ads_lookup_name;
1287         
1288         /* Domain API */
1289
1290         sam_method->sam_update_domain = sam_ads_update_domain;
1291         sam_method->sam_get_domain_handle = sam_ads_get_domain_handle;
1292
1293         /* Account API */
1294
1295         sam_method->sam_create_account = sam_ads_create_account;
1296         sam_method->sam_add_account = sam_ads_add_account;
1297         sam_method->sam_update_account = sam_ads_update_account;
1298         sam_method->sam_delete_account = sam_ads_delete_account;
1299         sam_method->sam_enum_accounts = sam_ads_enum_accounts;
1300
1301         sam_method->sam_get_account_by_sid = sam_ads_get_account_by_sid;
1302         sam_method->sam_get_account_by_name = sam_ads_get_account_by_name;
1303
1304         /* Group API */
1305
1306         sam_method->sam_create_group = sam_ads_create_group;
1307         sam_method->sam_add_group = sam_ads_add_group;
1308         sam_method->sam_update_group = sam_ads_update_group;
1309         sam_method->sam_delete_group = sam_ads_delete_group;
1310         sam_method->sam_enum_groups = sam_ads_enum_groups;
1311         sam_method->sam_get_group_by_sid = sam_ads_get_group_by_sid;
1312         sam_method->sam_get_group_by_name = sam_ads_get_group_by_name;
1313
1314         sam_method->sam_add_member_to_group = sam_ads_add_member_to_group;
1315         sam_method->sam_delete_member_from_group = sam_ads_delete_member_from_group;
1316         sam_method->sam_enum_groupmembers = sam_ads_enum_groupmembers;
1317
1318         sam_method->sam_get_groups_of_sid = sam_ads_get_groups_of_sid;
1319
1320         sam_ads_state = talloc_zero(mem_ctx, sizeof(SAM_ADS_PRIVATES));
1321         if (!sam_ads_state) {
1322                 DEBUG(0, ("talloc() failed for sam_ads private_data!\n"));
1323                 return NT_STATUS_NO_MEMORY;
1324         }
1325         
1326         if (!(sam_ads_state->mem_ctx = talloc_init_named("sam_ads_method"))) {
1327                 DEBUG(0, ("talloc_init_named() failed for sam_ads_state->mem_ctx\n"));
1328                 return NT_STATUS_NO_MEMORY;
1329         }
1330
1331         sam_ads_state->ads_bind_dn = talloc_strdup(sam_ads_state->mem_ctx, lp_parm_string(NULL,"sam_ads","bind as"));
1332         sam_ads_state->ads_bind_pw = talloc_strdup(sam_ads_state->mem_ctx, lp_parm_string(NULL,"sam_ads","bind pw"));
1333
1334         sam_ads_state->bind_plaintext = strequal(lp_parm_string(NULL, "sam_ads", "plaintext bind"), "yes");
1335
1336         if (!sam_ads_state->ads_bind_dn || !sam_ads_state->ads_bind_pw) {
1337                 DEBUG(0, ("talloc_strdup() failed for bind dn or password\n"));
1338                 return NT_STATUS_NO_MEMORY;
1339         }
1340
1341         /* Maybe we should not check the result here? Server down on startup? */
1342
1343         if (module_params && *module_params) {
1344                 sam_ads_state->ldap_uri = talloc_strdup(sam_ads_state->mem_ctx, module_params);
1345                 if (!sam_ads_state->ldap_uri) {
1346                         DEBUG(0, ("talloc_strdup() failed for bind dn or password\n"));
1347                         return NT_STATUS_NO_MEMORY;
1348                 }
1349         } else {
1350                 sam_ads_state->ldap_uri = "ldapi://";
1351         }
1352
1353         ads_status = sam_ads_cached_connection(sam_ads_state);
1354         if (!ADS_ERR_OK(ads_status)) {
1355                 return ads_ntstatus(ads_status);
1356         }
1357
1358         sam_method->private_data = sam_ads_state;
1359         sam_method->free_private_data = sam_ads_free_private_data;
1360         
1361         sam_ads_debug_level = debug_add_class("sam_ads");
1362         if (sam_ads_debug_level == -1) {
1363                 sam_ads_debug_level = DBGC_ALL;
1364                 DEBUG(0, ("sam_ads: Couldn't register custom debugging class!\n"));
1365         } else DEBUG(2, ("sam_ads: Debug class number of 'sam_ads': %d\n", sam_ads_debug_level));
1366     
1367         DEBUG(5, ("Initializing sam_ads\n"));
1368         if (module_params)
1369                 DEBUG(10, ("Module Parameters for Domain %s[%s]: %s\n", sam_method->domain_name, sam_method->domain_name, module_params));
1370         return NT_STATUS_OK;
1371 }
1372
1373 #else /* HAVE_LDAP */
1374 void sam_ads_dummy(void)
1375 {
1376         DEBUG(0,("sam_ads: not supported!\n"));
1377 }
1378 #endif /* HAVE_LDAP */