s3-samr: cosmetic fixes for _samr_QueryDisplayInfo.
[ira/wip.git] / source3 / rpc_server / srv_samr_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell                   1992-1997,
5  *  Copyright (C) Luke Kenneth Casson Leighton      1996-1997,
6  *  Copyright (C) Paul Ashton                       1997,
7  *  Copyright (C) Marc Jacobsen                     1999,
8  *  Copyright (C) Jeremy Allison                    2001-2008,
9  *  Copyright (C) Jean François Micouleau           1998-2001,
10  *  Copyright (C) Jim McDonough <jmcd@us.ibm.com>   2002,
11  *  Copyright (C) Gerald (Jerry) Carter             2003-2004,
12  *  Copyright (C) Simo Sorce                        2003.
13  *  Copyright (C) Volker Lendecke                   2005.
14  *  Copyright (C) Guenther Deschner                 2008.
15  *
16  *  This program is free software; you can redistribute it and/or modify
17  *  it under the terms of the GNU General Public License as published by
18  *  the Free Software Foundation; either version 3 of the License, or
19  *  (at your option) any later version.
20  *
21  *  This program is distributed in the hope that it will be useful,
22  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
23  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  *  GNU General Public License for more details.
25  *
26  *  You should have received a copy of the GNU General Public License
27  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
28  */
29
30 /*
31  * This is the implementation of the SAMR code.
32  */
33
34 #include "includes.h"
35 #include "smbd/globals.h"
36 #include "../libcli/auth/libcli_auth.h"
37
38 #undef DBGC_CLASS
39 #define DBGC_CLASS DBGC_RPC_SRV
40
41 #define SAMR_USR_RIGHTS_WRITE_PW \
42                 ( READ_CONTROL_ACCESS           | \
43                   SAMR_USER_ACCESS_CHANGE_PASSWORD      | \
44                   SAMR_USER_ACCESS_SET_LOC_COM)
45 #define SAMR_USR_RIGHTS_CANT_WRITE_PW \
46                 ( READ_CONTROL_ACCESS | SAMR_USER_ACCESS_SET_LOC_COM )
47
48 #define DISP_INFO_CACHE_TIMEOUT 10
49
50 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
51 #define MAX_SAM_ENTRIES_W95 50
52
53 struct samr_connect_info {
54         uint8_t dummy;
55 };
56
57 struct samr_domain_info {
58         struct dom_sid sid;
59         struct disp_info *disp_info;
60 };
61
62 struct samr_user_info {
63         struct dom_sid sid;
64 };
65
66 struct samr_group_info {
67         struct dom_sid sid;
68 };
69
70 struct samr_alias_info {
71         struct dom_sid sid;
72 };
73
74 typedef struct disp_info {
75         DOM_SID sid; /* identify which domain this is. */
76         struct pdb_search *users; /* querydispinfo 1 and 4 */
77         struct pdb_search *machines; /* querydispinfo 2 */
78         struct pdb_search *groups; /* querydispinfo 3 and 5, enumgroups */
79         struct pdb_search *aliases; /* enumaliases */
80
81         uint16 enum_acb_mask;
82         struct pdb_search *enum_users; /* enumusers with a mask */
83
84         struct timed_event *cache_timeout_event; /* cache idle timeout
85                                                   * handler. */
86 } DISP_INFO;
87
88 static const struct generic_mapping sam_generic_mapping = {
89         GENERIC_RIGHTS_SAM_READ,
90         GENERIC_RIGHTS_SAM_WRITE,
91         GENERIC_RIGHTS_SAM_EXECUTE,
92         GENERIC_RIGHTS_SAM_ALL_ACCESS};
93 static const struct generic_mapping dom_generic_mapping = {
94         GENERIC_RIGHTS_DOMAIN_READ,
95         GENERIC_RIGHTS_DOMAIN_WRITE,
96         GENERIC_RIGHTS_DOMAIN_EXECUTE,
97         GENERIC_RIGHTS_DOMAIN_ALL_ACCESS};
98 static const struct generic_mapping usr_generic_mapping = {
99         GENERIC_RIGHTS_USER_READ,
100         GENERIC_RIGHTS_USER_WRITE,
101         GENERIC_RIGHTS_USER_EXECUTE,
102         GENERIC_RIGHTS_USER_ALL_ACCESS};
103 static const struct generic_mapping usr_nopwchange_generic_mapping = {
104         GENERIC_RIGHTS_USER_READ,
105         GENERIC_RIGHTS_USER_WRITE,
106         GENERIC_RIGHTS_USER_EXECUTE & ~SAMR_USER_ACCESS_CHANGE_PASSWORD,
107         GENERIC_RIGHTS_USER_ALL_ACCESS};
108 static const struct generic_mapping grp_generic_mapping = {
109         GENERIC_RIGHTS_GROUP_READ,
110         GENERIC_RIGHTS_GROUP_WRITE,
111         GENERIC_RIGHTS_GROUP_EXECUTE,
112         GENERIC_RIGHTS_GROUP_ALL_ACCESS};
113 static const struct generic_mapping ali_generic_mapping = {
114         GENERIC_RIGHTS_ALIAS_READ,
115         GENERIC_RIGHTS_ALIAS_WRITE,
116         GENERIC_RIGHTS_ALIAS_EXECUTE,
117         GENERIC_RIGHTS_ALIAS_ALL_ACCESS};
118
119 /*******************************************************************
120 *******************************************************************/
121
122 static NTSTATUS make_samr_object_sd( TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size,
123                                      const struct generic_mapping *map,
124                                      DOM_SID *sid, uint32 sid_access )
125 {
126         DOM_SID domadmin_sid;
127         SEC_ACE ace[5];         /* at most 5 entries */
128         size_t i = 0;
129
130         SEC_ACL *psa = NULL;
131
132         /* basic access for Everyone */
133
134         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
135                         map->generic_execute | map->generic_read, 0);
136
137         /* add Full Access 'BUILTIN\Administrators' and 'BUILTIN\Account Operators */
138
139         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
140                         SEC_ACE_TYPE_ACCESS_ALLOWED, map->generic_all, 0);
141         init_sec_ace(&ace[i++], &global_sid_Builtin_Account_Operators,
142                         SEC_ACE_TYPE_ACCESS_ALLOWED, map->generic_all, 0);
143
144         /* Add Full Access for Domain Admins if we are a DC */
145
146         if ( IS_DC ) {
147                 sid_copy( &domadmin_sid, get_global_sam_sid() );
148                 sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS );
149                 init_sec_ace(&ace[i++], &domadmin_sid,
150                         SEC_ACE_TYPE_ACCESS_ALLOWED, map->generic_all, 0);
151         }
152
153         /* if we have a sid, give it some special access */
154
155         if ( sid ) {
156                 init_sec_ace(&ace[i++], sid, SEC_ACE_TYPE_ACCESS_ALLOWED, sid_access, 0);
157         }
158
159         /* create the security descriptor */
160
161         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) == NULL)
162                 return NT_STATUS_NO_MEMORY;
163
164         if ((*psd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
165                                   SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL,
166                                   psa, sd_size)) == NULL)
167                 return NT_STATUS_NO_MEMORY;
168
169         return NT_STATUS_OK;
170 }
171
172 /*******************************************************************
173  Checks if access to an object should be granted, and returns that
174  level of access for further checks.
175 ********************************************************************/
176
177 NTSTATUS access_check_object( SEC_DESC *psd, NT_USER_TOKEN *token,
178                                           SE_PRIV *rights, uint32 rights_mask,
179                                           uint32 des_access, uint32 *acc_granted,
180                                           const char *debug )
181 {
182         NTSTATUS status = NT_STATUS_ACCESS_DENIED;
183         uint32 saved_mask = 0;
184
185         /* check privileges; certain SAM access bits should be overridden
186            by privileges (mostly having to do with creating/modifying/deleting
187            users and groups) */
188
189         if (rights && !se_priv_equal(rights, &se_priv_none) &&
190                         user_has_any_privilege(token, rights)) {
191
192                 saved_mask = (des_access & rights_mask);
193                 des_access &= ~saved_mask;
194
195                 DEBUG(4,("access_check_object: user rights access mask [0x%x]\n",
196                         rights_mask));
197         }
198
199
200         /* check the security descriptor first */
201
202         status = se_access_check(psd, token, des_access, acc_granted);
203         if (NT_STATUS_IS_OK(status)) {
204                 goto done;
205         }
206
207         /* give root a free pass */
208
209         if ( geteuid() == sec_initial_uid() ) {
210
211                 DEBUG(4,("%s: ACCESS should be DENIED  (requested: %#010x)\n", debug, des_access));
212                 DEBUGADD(4,("but overritten by euid == sec_initial_uid()\n"));
213
214                 *acc_granted = des_access;
215
216                 status = NT_STATUS_OK;
217                 goto done;
218         }
219
220
221 done:
222         /* add in any bits saved during the privilege check (only
223            matters is status is ok) */
224
225         *acc_granted |= rights_mask;
226
227         DEBUG(4,("%s: access %s (requested: 0x%08x, granted: 0x%08x)\n",
228                 debug, NT_STATUS_IS_OK(status) ? "GRANTED" : "DENIED",
229                 des_access, *acc_granted));
230
231         return status;
232 }
233
234
235 /*******************************************************************
236  Map any MAXIMUM_ALLOWED_ACCESS request to a valid access set.
237 ********************************************************************/
238
239 void map_max_allowed_access(const NT_USER_TOKEN *token,
240                                         uint32_t *pacc_requested)
241 {
242         if (!((*pacc_requested) & MAXIMUM_ALLOWED_ACCESS)) {
243                 return;
244         }
245         *pacc_requested &= ~MAXIMUM_ALLOWED_ACCESS;
246
247         /* At least try for generic read|execute - Everyone gets that. */
248         *pacc_requested = GENERIC_READ_ACCESS|GENERIC_EXECUTE_ACCESS;
249
250         /* root gets anything. */
251         if (geteuid() == sec_initial_uid()) {
252                 *pacc_requested |= GENERIC_ALL_ACCESS;
253                 return;
254         }
255
256         /* Full Access for 'BUILTIN\Administrators' and 'BUILTIN\Account Operators */
257
258         if (is_sid_in_token(token, &global_sid_Builtin_Administrators) ||
259                         is_sid_in_token(token, &global_sid_Builtin_Account_Operators)) {
260                 *pacc_requested |= GENERIC_ALL_ACCESS;
261                 return;
262         }
263
264         /* Full access for DOMAIN\Domain Admins. */
265         if ( IS_DC ) {
266                 DOM_SID domadmin_sid;
267                 sid_copy( &domadmin_sid, get_global_sam_sid() );
268                 sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS );
269                 if (is_sid_in_token(token, &domadmin_sid)) {
270                         *pacc_requested |= GENERIC_ALL_ACCESS;
271                         return;
272                 }
273         }
274         /* TODO ! Check privileges. */
275 }
276
277 /*******************************************************************
278  Fetch or create a dispinfo struct.
279 ********************************************************************/
280
281 static DISP_INFO *get_samr_dispinfo_by_sid(const struct dom_sid *psid)
282 {
283         /*
284          * We do a static cache for DISP_INFO's here. Explanation can be found
285          * in Jeremy's checkin message to r11793:
286          *
287          * Fix the SAMR cache so it works across completely insane
288          * client behaviour (ie.:
289          * open pipe/open SAMR handle/enumerate 0 - 1024
290          * close SAMR handle, close pipe.
291          * open pipe/open SAMR handle/enumerate 1024 - 2048...
292          * close SAMR handle, close pipe.
293          * And on ad-nausium. Amazing.... probably object-oriented
294          * client side programming in action yet again.
295          * This change should *massively* improve performance when
296          * enumerating users from an LDAP database.
297          * Jeremy.
298          *
299          * "Our" and the builtin domain are the only ones where we ever
300          * enumerate stuff, so just cache 2 entries.
301          */
302
303         static struct disp_info *builtin_dispinfo;
304         static struct disp_info *domain_dispinfo;
305
306         /* There are two cases to consider here:
307            1) The SID is a domain SID and we look for an equality match, or
308            2) This is an account SID and so we return the DISP_INFO* for our
309               domain */
310
311         if (psid == NULL) {
312                 return NULL;
313         }
314
315         if (sid_check_is_builtin(psid) || sid_check_is_in_builtin(psid)) {
316                 /*
317                  * Necessary only once, but it does not really hurt.
318                  */
319                 if (builtin_dispinfo == NULL) {
320                         builtin_dispinfo = talloc_zero(
321                                 talloc_autofree_context(), struct disp_info);
322                         if (builtin_dispinfo == NULL) {
323                                 return NULL;
324                         }
325                 }
326                 sid_copy(&builtin_dispinfo->sid, &global_sid_Builtin);
327
328                 return builtin_dispinfo;
329         }
330
331         if (sid_check_is_domain(psid) || sid_check_is_in_our_domain(psid)) {
332                 /*
333                  * Necessary only once, but it does not really hurt.
334                  */
335                 if (domain_dispinfo == NULL) {
336                         domain_dispinfo = talloc_zero(
337                                 talloc_autofree_context(), struct disp_info);
338                         if (domain_dispinfo == NULL) {
339                                 return NULL;
340                         }
341                 }
342                 sid_copy(&domain_dispinfo->sid, get_global_sam_sid());
343
344                 return domain_dispinfo;
345         }
346
347         return NULL;
348 }
349
350 /*******************************************************************
351  Function to free the per SID data.
352  ********************************************************************/
353
354 static void free_samr_cache(DISP_INFO *disp_info)
355 {
356         DEBUG(10, ("free_samr_cache: deleting cache for SID %s\n",
357                    sid_string_dbg(&disp_info->sid)));
358
359         /* We need to become root here because the paged search might have to
360          * tell the LDAP server we're not interested in the rest anymore. */
361
362         become_root();
363
364         TALLOC_FREE(disp_info->users);
365         TALLOC_FREE(disp_info->machines);
366         TALLOC_FREE(disp_info->groups);
367         TALLOC_FREE(disp_info->aliases);
368         TALLOC_FREE(disp_info->enum_users);
369
370         unbecome_root();
371 }
372
373 /*******************************************************************
374  Idle event handler. Throw away the disp info cache.
375  ********************************************************************/
376
377 static void disp_info_cache_idle_timeout_handler(struct event_context *ev_ctx,
378                                                  struct timed_event *te,
379                                                  struct timeval now,
380                                                  void *private_data)
381 {
382         DISP_INFO *disp_info = (DISP_INFO *)private_data;
383
384         TALLOC_FREE(disp_info->cache_timeout_event);
385
386         DEBUG(10, ("disp_info_cache_idle_timeout_handler: caching timed "
387                    "out\n"));
388         free_samr_cache(disp_info);
389 }
390
391 /*******************************************************************
392  Setup cache removal idle event handler.
393  ********************************************************************/
394
395 static void set_disp_info_cache_timeout(DISP_INFO *disp_info, time_t secs_fromnow)
396 {
397         /* Remove any pending timeout and update. */
398
399         TALLOC_FREE(disp_info->cache_timeout_event);
400
401         DEBUG(10,("set_disp_info_cache_timeout: caching enumeration for "
402                   "SID %s for %u seconds\n", sid_string_dbg(&disp_info->sid),
403                   (unsigned int)secs_fromnow ));
404
405         disp_info->cache_timeout_event = event_add_timed(
406                 smbd_event_context(), NULL,
407                 timeval_current_ofs(secs_fromnow, 0),
408                 disp_info_cache_idle_timeout_handler, (void *)disp_info);
409 }
410
411 /*******************************************************************
412  Force flush any cache. We do this on any samr_set_xxx call.
413  We must also remove the timeout handler.
414  ********************************************************************/
415
416 static void force_flush_samr_cache(const struct dom_sid *sid)
417 {
418         struct disp_info *disp_info = get_samr_dispinfo_by_sid(sid);
419
420         if ((disp_info == NULL) || (disp_info->cache_timeout_event == NULL)) {
421                 return;
422         }
423
424         DEBUG(10,("force_flush_samr_cache: clearing idle event\n"));
425         TALLOC_FREE(disp_info->cache_timeout_event);
426         free_samr_cache(disp_info);
427 }
428
429 /*******************************************************************
430  Ensure password info is never given out. Paranioa... JRA.
431  ********************************************************************/
432
433 static void samr_clear_sam_passwd(struct samu *sam_pass)
434 {
435
436         if (!sam_pass)
437                 return;
438
439         /* These now zero out the old password */
440
441         pdb_set_lanman_passwd(sam_pass, NULL, PDB_DEFAULT);
442         pdb_set_nt_passwd(sam_pass, NULL, PDB_DEFAULT);
443 }
444
445 static uint32 count_sam_users(struct disp_info *info, uint32 acct_flags)
446 {
447         struct samr_displayentry *entry;
448
449         if (sid_check_is_builtin(&info->sid)) {
450                 /* No users in builtin. */
451                 return 0;
452         }
453
454         if (info->users == NULL) {
455                 info->users = pdb_search_users(info, acct_flags);
456                 if (info->users == NULL) {
457                         return 0;
458                 }
459         }
460         /* Fetch the last possible entry, thus trigger an enumeration */
461         pdb_search_entries(info->users, 0xffffffff, 1, &entry);
462
463         /* Ensure we cache this enumeration. */
464         set_disp_info_cache_timeout(info, DISP_INFO_CACHE_TIMEOUT);
465
466         return info->users->num_entries;
467 }
468
469 static uint32 count_sam_groups(struct disp_info *info)
470 {
471         struct samr_displayentry *entry;
472
473         if (sid_check_is_builtin(&info->sid)) {
474                 /* No groups in builtin. */
475                 return 0;
476         }
477
478         if (info->groups == NULL) {
479                 info->groups = pdb_search_groups(info);
480                 if (info->groups == NULL) {
481                         return 0;
482                 }
483         }
484         /* Fetch the last possible entry, thus trigger an enumeration */
485         pdb_search_entries(info->groups, 0xffffffff, 1, &entry);
486
487         /* Ensure we cache this enumeration. */
488         set_disp_info_cache_timeout(info, DISP_INFO_CACHE_TIMEOUT);
489
490         return info->groups->num_entries;
491 }
492
493 static uint32 count_sam_aliases(struct disp_info *info)
494 {
495         struct samr_displayentry *entry;
496
497         if (info->aliases == NULL) {
498                 info->aliases = pdb_search_aliases(info, &info->sid);
499                 if (info->aliases == NULL) {
500                         return 0;
501                 }
502         }
503         /* Fetch the last possible entry, thus trigger an enumeration */
504         pdb_search_entries(info->aliases, 0xffffffff, 1, &entry);
505
506         /* Ensure we cache this enumeration. */
507         set_disp_info_cache_timeout(info, DISP_INFO_CACHE_TIMEOUT);
508
509         return info->aliases->num_entries;
510 }
511
512 /*******************************************************************
513  _samr_Close
514  ********************************************************************/
515
516 NTSTATUS _samr_Close(pipes_struct *p, struct samr_Close *r)
517 {
518         if (!close_policy_hnd(p, r->in.handle)) {
519                 return NT_STATUS_INVALID_HANDLE;
520         }
521
522         ZERO_STRUCTP(r->out.handle);
523
524         return NT_STATUS_OK;
525 }
526
527 /*******************************************************************
528  _samr_OpenDomain
529  ********************************************************************/
530
531 NTSTATUS _samr_OpenDomain(pipes_struct *p,
532                           struct samr_OpenDomain *r)
533 {
534         struct samr_connect_info *cinfo;
535         struct samr_domain_info *dinfo;
536         SEC_DESC *psd = NULL;
537         uint32    acc_granted;
538         uint32    des_access = r->in.access_mask;
539         NTSTATUS  status;
540         size_t    sd_size;
541         uint32_t extra_access = SAMR_DOMAIN_ACCESS_CREATE_USER;
542         SE_PRIV se_rights;
543
544         /* find the connection policy handle. */
545
546         cinfo = policy_handle_find(p, r->in.connect_handle, 0, NULL,
547                                    struct samr_connect_info, &status);
548         if (!NT_STATUS_IS_OK(status)) {
549                 return status;
550         }
551
552         /*check if access can be granted as requested by client. */
553         map_max_allowed_access(p->server_info->ptok, &des_access);
554
555         make_samr_object_sd( p->mem_ctx, &psd, &sd_size, &dom_generic_mapping, NULL, 0 );
556         se_map_generic( &des_access, &dom_generic_mapping );
557
558         /*
559          * Users with SeMachineAccount or SeAddUser get additional
560          * SAMR_DOMAIN_ACCESS_CREATE_USER access.
561          */
562         se_priv_copy( &se_rights, &se_machine_account );
563         se_priv_add( &se_rights, &se_add_users );
564
565         /*
566          * Users with SeAddUser get the ability to manipulate groups
567          * and aliases.
568          */
569         if (user_has_any_privilege(p->server_info->ptok, &se_add_users)) {
570                 extra_access |= (SAMR_DOMAIN_ACCESS_CREATE_GROUP |
571                                 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
572                                 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT |
573                                 SAMR_DOMAIN_ACCESS_LOOKUP_ALIAS |
574                                 SAMR_DOMAIN_ACCESS_CREATE_ALIAS);
575         }
576
577         status = access_check_object( psd, p->server_info->ptok,
578                 &se_rights, extra_access, des_access,
579                 &acc_granted, "_samr_OpenDomain" );
580
581         if ( !NT_STATUS_IS_OK(status) )
582                 return status;
583
584         if (!sid_check_is_domain(r->in.sid) &&
585             !sid_check_is_builtin(r->in.sid)) {
586                 return NT_STATUS_NO_SUCH_DOMAIN;
587         }
588
589         dinfo = policy_handle_create(p, r->out.domain_handle, acc_granted,
590                                      struct samr_domain_info, &status);
591         if (!NT_STATUS_IS_OK(status)) {
592                 return status;
593         }
594         dinfo->sid = *r->in.sid;
595         dinfo->disp_info = get_samr_dispinfo_by_sid(r->in.sid);
596
597         DEBUG(5,("_samr_OpenDomain: %d\n", __LINE__));
598
599         return NT_STATUS_OK;
600 }
601
602 /*******************************************************************
603  _samr_GetUserPwInfo
604  ********************************************************************/
605
606 NTSTATUS _samr_GetUserPwInfo(pipes_struct *p,
607                              struct samr_GetUserPwInfo *r)
608 {
609         struct samr_user_info *uinfo;
610         enum lsa_SidType sid_type;
611         uint32_t min_password_length = 0;
612         uint32_t password_properties = 0;
613         bool ret = false;
614         NTSTATUS status;
615
616         DEBUG(5,("_samr_GetUserPwInfo: %d\n", __LINE__));
617
618         uinfo = policy_handle_find(p, r->in.user_handle,
619                                    SAMR_USER_ACCESS_GET_ATTRIBUTES, NULL,
620                                    struct samr_user_info, &status);
621         if (!NT_STATUS_IS_OK(status)) {
622                 return status;
623         }
624
625         if (!sid_check_is_in_our_domain(&uinfo->sid)) {
626                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
627         }
628
629         become_root();
630         ret = lookup_sid(p->mem_ctx, &uinfo->sid, NULL, NULL, &sid_type);
631         unbecome_root();
632         if (ret == false) {
633                 return NT_STATUS_NO_SUCH_USER;
634         }
635
636         switch (sid_type) {
637                 case SID_NAME_USER:
638                         become_root();
639                         pdb_get_account_policy(AP_MIN_PASSWORD_LEN,
640                                                &min_password_length);
641                         pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS,
642                                                &password_properties);
643                         unbecome_root();
644
645                         if (lp_check_password_script() && *lp_check_password_script()) {
646                                 password_properties |= DOMAIN_PASSWORD_COMPLEX;
647                         }
648
649                         break;
650                 default:
651                         break;
652         }
653
654         r->out.info->min_password_length = min_password_length;
655         r->out.info->password_properties = password_properties;
656
657         DEBUG(5,("_samr_GetUserPwInfo: %d\n", __LINE__));
658
659         return NT_STATUS_OK;
660 }
661
662 /*******************************************************************
663  _samr_SetSecurity
664  ********************************************************************/
665
666 NTSTATUS _samr_SetSecurity(pipes_struct *p,
667                            struct samr_SetSecurity *r)
668 {
669         struct samr_user_info *uinfo;
670         uint32 i;
671         SEC_ACL *dacl;
672         bool ret;
673         struct samu *sampass=NULL;
674         NTSTATUS status;
675
676         uinfo = policy_handle_find(p, r->in.handle,
677                                    SAMR_USER_ACCESS_SET_ATTRIBUTES, NULL,
678                                    struct samr_user_info, &status);
679         if (!NT_STATUS_IS_OK(status)) {
680                 return status;
681         }
682
683         if (!(sampass = samu_new( p->mem_ctx))) {
684                 DEBUG(0,("No memory!\n"));
685                 return NT_STATUS_NO_MEMORY;
686         }
687
688         /* get the user record */
689         become_root();
690         ret = pdb_getsampwsid(sampass, &uinfo->sid);
691         unbecome_root();
692
693         if (!ret) {
694                 DEBUG(4, ("User %s not found\n",
695                           sid_string_dbg(&uinfo->sid)));
696                 TALLOC_FREE(sampass);
697                 return NT_STATUS_INVALID_HANDLE;
698         }
699
700         dacl = r->in.sdbuf->sd->dacl;
701         for (i=0; i < dacl->num_aces; i++) {
702                 if (sid_equal(&uinfo->sid, &dacl->aces[i].trustee)) {
703                         ret = pdb_set_pass_can_change(sampass,
704                                 (dacl->aces[i].access_mask &
705                                  SAMR_USER_ACCESS_CHANGE_PASSWORD) ?
706                                                       True: False);
707                         break;
708                 }
709         }
710
711         if (!ret) {
712                 TALLOC_FREE(sampass);
713                 return NT_STATUS_ACCESS_DENIED;
714         }
715
716         become_root();
717         status = pdb_update_sam_account(sampass);
718         unbecome_root();
719
720         TALLOC_FREE(sampass);
721
722         return status;
723 }
724
725 /*******************************************************************
726   build correct perms based on policies and password times for _samr_query_sec_obj
727 *******************************************************************/
728 static bool check_change_pw_access(TALLOC_CTX *mem_ctx, DOM_SID *user_sid)
729 {
730         struct samu *sampass=NULL;
731         bool ret;
732
733         if ( !(sampass = samu_new( mem_ctx )) ) {
734                 DEBUG(0,("No memory!\n"));
735                 return False;
736         }
737
738         become_root();
739         ret = pdb_getsampwsid(sampass, user_sid);
740         unbecome_root();
741
742         if (ret == False) {
743                 DEBUG(4,("User %s not found\n", sid_string_dbg(user_sid)));
744                 TALLOC_FREE(sampass);
745                 return False;
746         }
747
748         DEBUG(3,("User:[%s]\n",  pdb_get_username(sampass) ));
749
750         if (pdb_get_pass_can_change(sampass)) {
751                 TALLOC_FREE(sampass);
752                 return True;
753         }
754         TALLOC_FREE(sampass);
755         return False;
756 }
757
758
759 /*******************************************************************
760  _samr_QuerySecurity
761  ********************************************************************/
762
763 NTSTATUS _samr_QuerySecurity(pipes_struct *p,
764                              struct samr_QuerySecurity *r)
765 {
766         struct samr_connect_info *cinfo;
767         struct samr_domain_info *dinfo;
768         struct samr_user_info *uinfo;
769         struct samr_group_info *ginfo;
770         struct samr_alias_info *ainfo;
771         NTSTATUS status;
772         SEC_DESC * psd = NULL;
773         size_t sd_size;
774
775         cinfo = policy_handle_find(p, r->in.handle,
776                                    STD_RIGHT_READ_CONTROL_ACCESS, NULL,
777                                    struct samr_connect_info, &status);
778         if (NT_STATUS_IS_OK(status)) {
779                 DEBUG(5,("_samr_QuerySecurity: querying security on SAM\n"));
780                 status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size,
781                                              &sam_generic_mapping, NULL, 0);
782                 goto done;
783         }
784
785         dinfo = policy_handle_find(p, r->in.handle,
786                                    STD_RIGHT_READ_CONTROL_ACCESS, NULL,
787                                    struct samr_domain_info, &status);
788         if (NT_STATUS_IS_OK(status)) {
789                 DEBUG(5,("_samr_QuerySecurity: querying security on Domain "
790                          "with SID: %s\n", sid_string_dbg(&dinfo->sid)));
791                 /*
792                  * TODO: Builtin probably needs a different SD with restricted
793                  * write access
794                  */
795                 status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size,
796                                              &dom_generic_mapping, NULL, 0);
797                 goto done;
798         }
799
800         uinfo = policy_handle_find(p, r->in.handle,
801                                    STD_RIGHT_READ_CONTROL_ACCESS, NULL,
802                                    struct samr_user_info, &status);
803         if (NT_STATUS_IS_OK(status)) {
804                 DEBUG(10,("_samr_QuerySecurity: querying security on user "
805                           "Object with SID: %s\n",
806                           sid_string_dbg(&uinfo->sid)));
807                 if (check_change_pw_access(p->mem_ctx, &uinfo->sid)) {
808                         status = make_samr_object_sd(
809                                 p->mem_ctx, &psd, &sd_size,
810                                 &usr_generic_mapping,
811                                 &uinfo->sid, SAMR_USR_RIGHTS_WRITE_PW);
812                 } else {
813                         status = make_samr_object_sd(
814                                 p->mem_ctx, &psd, &sd_size,
815                                 &usr_nopwchange_generic_mapping,
816                                 &uinfo->sid, SAMR_USR_RIGHTS_CANT_WRITE_PW);
817                 }
818                 goto done;
819         }
820
821         ginfo = policy_handle_find(p, r->in.handle,
822                                    STD_RIGHT_READ_CONTROL_ACCESS, NULL,
823                                    struct samr_group_info, &status);
824         if (NT_STATUS_IS_OK(status)) {
825                 /*
826                  * TODO: different SDs have to be generated for aliases groups
827                  * and users.  Currently all three get a default user SD
828                  */
829                 DEBUG(10,("_samr_QuerySecurity: querying security on group "
830                           "Object with SID: %s\n",
831                           sid_string_dbg(&ginfo->sid)));
832                 status = make_samr_object_sd(
833                         p->mem_ctx, &psd, &sd_size,
834                         &usr_nopwchange_generic_mapping,
835                         &ginfo->sid, SAMR_USR_RIGHTS_CANT_WRITE_PW);
836                 goto done;
837         }
838
839         ainfo = policy_handle_find(p, r->in.handle,
840                                    STD_RIGHT_READ_CONTROL_ACCESS, NULL,
841                                    struct samr_alias_info, &status);
842         if (NT_STATUS_IS_OK(status)) {
843                 /*
844                  * TODO: different SDs have to be generated for aliases groups
845                  * and users.  Currently all three get a default user SD
846                  */
847                 DEBUG(10,("_samr_QuerySecurity: querying security on alias "
848                           "Object with SID: %s\n",
849                           sid_string_dbg(&ainfo->sid)));
850                 status = make_samr_object_sd(
851                         p->mem_ctx, &psd, &sd_size,
852                         &usr_nopwchange_generic_mapping,
853                         &ainfo->sid, SAMR_USR_RIGHTS_CANT_WRITE_PW);
854                 goto done;
855         }
856
857         return NT_STATUS_OBJECT_TYPE_MISMATCH;
858 done:
859         if ((*r->out.sdbuf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL)
860                 return NT_STATUS_NO_MEMORY;
861
862         return status;
863 }
864
865 /*******************************************************************
866 makes a SAM_ENTRY / UNISTR2* structure from a user list.
867 ********************************************************************/
868
869 static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx,
870                                          struct samr_SamEntry **sam_pp,
871                                          uint32_t num_entries,
872                                          uint32_t start_idx,
873                                          struct samr_displayentry *entries)
874 {
875         uint32_t i;
876         struct samr_SamEntry *sam;
877
878         *sam_pp = NULL;
879
880         if (num_entries == 0) {
881                 return NT_STATUS_OK;
882         }
883
884         sam = TALLOC_ZERO_ARRAY(ctx, struct samr_SamEntry, num_entries);
885         if (sam == NULL) {
886                 DEBUG(0, ("make_user_sam_entry_list: TALLOC_ZERO failed!\n"));
887                 return NT_STATUS_NO_MEMORY;
888         }
889
890         for (i = 0; i < num_entries; i++) {
891 #if 0
892                 /*
893                  * usrmgr expects a non-NULL terminated string with
894                  * trust relationships
895                  */
896                 if (entries[i].acct_flags & ACB_DOMTRUST) {
897                         init_unistr2(&uni_temp_name, entries[i].account_name,
898                                      UNI_FLAGS_NONE);
899                 } else {
900                         init_unistr2(&uni_temp_name, entries[i].account_name,
901                                      UNI_STR_TERMINATE);
902                 }
903 #endif
904                 init_lsa_String(&sam[i].name, entries[i].account_name);
905                 sam[i].idx = entries[i].rid;
906         }
907
908         *sam_pp = sam;
909
910         return NT_STATUS_OK;
911 }
912
913 #define MAX_SAM_ENTRIES MAX_SAM_ENTRIES_W2K
914
915 /*******************************************************************
916  _samr_EnumDomainUsers
917  ********************************************************************/
918
919 NTSTATUS _samr_EnumDomainUsers(pipes_struct *p,
920                                struct samr_EnumDomainUsers *r)
921 {
922         NTSTATUS status;
923         struct samr_domain_info *dinfo;
924         int num_account;
925         uint32 enum_context = *r->in.resume_handle;
926         enum remote_arch_types ra_type = get_remote_arch();
927         int max_sam_entries = (ra_type == RA_WIN95) ? MAX_SAM_ENTRIES_W95 : MAX_SAM_ENTRIES_W2K;
928         uint32 max_entries = max_sam_entries;
929         struct samr_displayentry *entries = NULL;
930         struct samr_SamArray *samr_array = NULL;
931         struct samr_SamEntry *samr_entries = NULL;
932
933         DEBUG(5,("_samr_EnumDomainUsers: %d\n", __LINE__));
934
935         dinfo = policy_handle_find(p, r->in.domain_handle,
936                                    SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL,
937                                    struct samr_domain_info, &status);
938         if (!NT_STATUS_IS_OK(status)) {
939                 return status;
940         }
941
942         if (sid_check_is_builtin(&dinfo->sid)) {
943                 /* No users in builtin. */
944                 *r->out.resume_handle = *r->in.resume_handle;
945                 DEBUG(5,("_samr_EnumDomainUsers: No users in BUILTIN\n"));
946                 return status;
947         }
948
949         samr_array = TALLOC_ZERO_P(p->mem_ctx, struct samr_SamArray);
950         if (!samr_array) {
951                 return NT_STATUS_NO_MEMORY;
952         }
953         *r->out.sam = samr_array;
954
955         become_root();
956
957         /* AS ROOT !!!! */
958
959         if ((dinfo->disp_info->enum_users != NULL) &&
960             (dinfo->disp_info->enum_acb_mask != r->in.acct_flags)) {
961                 TALLOC_FREE(dinfo->disp_info->enum_users);
962         }
963
964         if (dinfo->disp_info->enum_users == NULL) {
965                 dinfo->disp_info->enum_users = pdb_search_users(
966                         dinfo->disp_info, r->in.acct_flags);
967                 dinfo->disp_info->enum_acb_mask = r->in.acct_flags;
968         }
969
970         if (dinfo->disp_info->enum_users == NULL) {
971                 /* END AS ROOT !!!! */
972                 unbecome_root();
973                 return NT_STATUS_ACCESS_DENIED;
974         }
975
976         num_account = pdb_search_entries(dinfo->disp_info->enum_users,
977                                          enum_context, max_entries,
978                                          &entries);
979
980         /* END AS ROOT !!!! */
981
982         unbecome_root();
983
984         if (num_account == 0) {
985                 DEBUG(5, ("_samr_EnumDomainUsers: enumeration handle over "
986                           "total entries\n"));
987                 *r->out.resume_handle = *r->in.resume_handle;
988                 return NT_STATUS_OK;
989         }
990
991         status = make_user_sam_entry_list(p->mem_ctx, &samr_entries,
992                                           num_account, enum_context,
993                                           entries);
994         if (!NT_STATUS_IS_OK(status)) {
995                 return status;
996         }
997
998         if (max_entries <= num_account) {
999                 status = STATUS_MORE_ENTRIES;
1000         } else {
1001                 status = NT_STATUS_OK;
1002         }
1003
1004         /* Ensure we cache this enumeration. */
1005         set_disp_info_cache_timeout(dinfo->disp_info, DISP_INFO_CACHE_TIMEOUT);
1006
1007         DEBUG(5, ("_samr_EnumDomainUsers: %d\n", __LINE__));
1008
1009         samr_array->count = num_account;
1010         samr_array->entries = samr_entries;
1011
1012         *r->out.resume_handle = *r->in.resume_handle + num_account;
1013         *r->out.num_entries = num_account;
1014
1015         DEBUG(5,("_samr_EnumDomainUsers: %d\n", __LINE__));
1016
1017         return status;
1018 }
1019
1020 /*******************************************************************
1021 makes a SAM_ENTRY / UNISTR2* structure from a group list.
1022 ********************************************************************/
1023
1024 static void make_group_sam_entry_list(TALLOC_CTX *ctx,
1025                                       struct samr_SamEntry **sam_pp,
1026                                       uint32_t num_sam_entries,
1027                                       struct samr_displayentry *entries)
1028 {
1029         struct samr_SamEntry *sam;
1030         uint32_t i;
1031
1032         *sam_pp = NULL;
1033
1034         if (num_sam_entries == 0) {
1035                 return;
1036         }
1037
1038         sam = TALLOC_ZERO_ARRAY(ctx, struct samr_SamEntry, num_sam_entries);
1039         if (sam == NULL) {
1040                 return;
1041         }
1042
1043         for (i = 0; i < num_sam_entries; i++) {
1044                 /*
1045                  * JRA. I think this should include the null. TNG does not.
1046                  */
1047                 init_lsa_String(&sam[i].name, entries[i].account_name);
1048                 sam[i].idx = entries[i].rid;
1049         }
1050
1051         *sam_pp = sam;
1052 }
1053
1054 /*******************************************************************
1055  _samr_EnumDomainGroups
1056  ********************************************************************/
1057
1058 NTSTATUS _samr_EnumDomainGroups(pipes_struct *p,
1059                                 struct samr_EnumDomainGroups *r)
1060 {
1061         NTSTATUS status;
1062         struct samr_domain_info *dinfo;
1063         struct samr_displayentry *groups;
1064         uint32 num_groups;
1065         struct samr_SamArray *samr_array = NULL;
1066         struct samr_SamEntry *samr_entries = NULL;
1067
1068         dinfo = policy_handle_find(p, r->in.domain_handle,
1069                                    SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL,
1070                                    struct samr_domain_info, &status);
1071         if (!NT_STATUS_IS_OK(status)) {
1072                 return status;
1073         }
1074
1075         DEBUG(5,("_samr_EnumDomainGroups: %d\n", __LINE__));
1076
1077         if (sid_check_is_builtin(&dinfo->sid)) {
1078                 /* No groups in builtin. */
1079                 *r->out.resume_handle = *r->in.resume_handle;
1080                 DEBUG(5,("_samr_EnumDomainGroups: No groups in BUILTIN\n"));
1081                 return status;
1082         }
1083
1084         samr_array = TALLOC_ZERO_P(p->mem_ctx, struct samr_SamArray);
1085         if (!samr_array) {
1086                 return NT_STATUS_NO_MEMORY;
1087         }
1088
1089         /* the domain group array is being allocated in the function below */
1090
1091         become_root();
1092
1093         if (dinfo->disp_info->groups == NULL) {
1094                 dinfo->disp_info->groups = pdb_search_groups(dinfo->disp_info);
1095
1096                 if (dinfo->disp_info->groups == NULL) {
1097                         unbecome_root();
1098                         return NT_STATUS_ACCESS_DENIED;
1099                 }
1100         }
1101
1102         num_groups = pdb_search_entries(dinfo->disp_info->groups,
1103                                         *r->in.resume_handle,
1104                                         MAX_SAM_ENTRIES, &groups);
1105         unbecome_root();
1106
1107         /* Ensure we cache this enumeration. */
1108         set_disp_info_cache_timeout(dinfo->disp_info, DISP_INFO_CACHE_TIMEOUT);
1109
1110         make_group_sam_entry_list(p->mem_ctx, &samr_entries,
1111                                   num_groups, groups);
1112
1113         if (MAX_SAM_ENTRIES <= num_groups) {
1114                 status = STATUS_MORE_ENTRIES;
1115         } else {
1116                 status = NT_STATUS_OK;
1117         }
1118
1119         samr_array->count = num_groups;
1120         samr_array->entries = samr_entries;
1121
1122         *r->out.sam = samr_array;
1123         *r->out.num_entries = num_groups;
1124         *r->out.resume_handle = num_groups + *r->in.resume_handle;
1125
1126         DEBUG(5,("_samr_EnumDomainGroups: %d\n", __LINE__));
1127
1128         return status;
1129 }
1130
1131 /*******************************************************************
1132  _samr_EnumDomainAliases
1133  ********************************************************************/
1134
1135 NTSTATUS _samr_EnumDomainAliases(pipes_struct *p,
1136                                  struct samr_EnumDomainAliases *r)
1137 {
1138         NTSTATUS status;
1139         struct samr_domain_info *dinfo;
1140         struct samr_displayentry *aliases;
1141         uint32 num_aliases = 0;
1142         struct samr_SamArray *samr_array = NULL;
1143         struct samr_SamEntry *samr_entries = NULL;
1144
1145         dinfo = policy_handle_find(p, r->in.domain_handle,
1146                                    SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL,
1147                                    struct samr_domain_info, &status);
1148         if (!NT_STATUS_IS_OK(status)) {
1149                 return status;
1150         }
1151
1152         DEBUG(5,("_samr_EnumDomainAliases: sid %s\n",
1153                  sid_string_dbg(&dinfo->sid)));
1154
1155         samr_array = TALLOC_ZERO_P(p->mem_ctx, struct samr_SamArray);
1156         if (!samr_array) {
1157                 return NT_STATUS_NO_MEMORY;
1158         }
1159
1160         become_root();
1161
1162         if (dinfo->disp_info->aliases == NULL) {
1163                 dinfo->disp_info->aliases = pdb_search_aliases(
1164                         dinfo->disp_info, &dinfo->sid);
1165                 if (dinfo->disp_info->aliases == NULL) {
1166                         unbecome_root();
1167                         return NT_STATUS_ACCESS_DENIED;
1168                 }
1169         }
1170
1171         num_aliases = pdb_search_entries(dinfo->disp_info->aliases,
1172                                          *r->in.resume_handle,
1173                                          MAX_SAM_ENTRIES, &aliases);
1174         unbecome_root();
1175
1176         /* Ensure we cache this enumeration. */
1177         set_disp_info_cache_timeout(dinfo->disp_info, DISP_INFO_CACHE_TIMEOUT);
1178
1179         make_group_sam_entry_list(p->mem_ctx, &samr_entries,
1180                                   num_aliases, aliases);
1181
1182         DEBUG(5,("_samr_EnumDomainAliases: %d\n", __LINE__));
1183
1184         if (MAX_SAM_ENTRIES <= num_aliases) {
1185                 status = STATUS_MORE_ENTRIES;
1186         } else {
1187                 status = NT_STATUS_OK;
1188         }
1189
1190         samr_array->count = num_aliases;
1191         samr_array->entries = samr_entries;
1192
1193         *r->out.sam = samr_array;
1194         *r->out.num_entries = num_aliases;
1195         *r->out.resume_handle = num_aliases + *r->in.resume_handle;
1196
1197         return status;
1198 }
1199
1200 /*******************************************************************
1201  inits a samr_DispInfoGeneral structure.
1202 ********************************************************************/
1203
1204 static NTSTATUS init_samr_dispinfo_1(TALLOC_CTX *ctx,
1205                                      struct samr_DispInfoGeneral *r,
1206                                      uint32_t num_entries,
1207                                      uint32_t start_idx,
1208                                      struct samr_displayentry *entries)
1209 {
1210         uint32 i;
1211
1212         DEBUG(10, ("init_samr_dispinfo_1: num_entries: %d\n", num_entries));
1213
1214         if (num_entries == 0) {
1215                 return NT_STATUS_OK;
1216         }
1217
1218         r->count = num_entries;
1219
1220         r->entries = TALLOC_ZERO_ARRAY(ctx, struct samr_DispEntryGeneral, num_entries);
1221         if (!r->entries) {
1222                 return NT_STATUS_NO_MEMORY;
1223         }
1224
1225         for (i = 0; i < num_entries ; i++) {
1226
1227                 init_lsa_String(&r->entries[i].account_name,
1228                                 entries[i].account_name);
1229
1230                 init_lsa_String(&r->entries[i].description,
1231                                 entries[i].description);
1232
1233                 init_lsa_String(&r->entries[i].full_name,
1234                                 entries[i].fullname);
1235
1236                 r->entries[i].rid = entries[i].rid;
1237                 r->entries[i].acct_flags = entries[i].acct_flags;
1238                 r->entries[i].idx = start_idx+i+1;
1239         }
1240
1241         return NT_STATUS_OK;
1242 }
1243
1244 /*******************************************************************
1245  inits a samr_DispInfoFull structure.
1246 ********************************************************************/
1247
1248 static NTSTATUS init_samr_dispinfo_2(TALLOC_CTX *ctx,
1249                                      struct samr_DispInfoFull *r,
1250                                      uint32_t num_entries,
1251                                      uint32_t start_idx,
1252                                      struct samr_displayentry *entries)
1253 {
1254         uint32_t i;
1255
1256         DEBUG(10, ("init_samr_dispinfo_2: num_entries: %d\n", num_entries));
1257
1258         if (num_entries == 0) {
1259                 return NT_STATUS_OK;
1260         }
1261
1262         r->count = num_entries;
1263
1264         r->entries = TALLOC_ZERO_ARRAY(ctx, struct samr_DispEntryFull, num_entries);
1265         if (!r->entries) {
1266                 return NT_STATUS_NO_MEMORY;
1267         }
1268
1269         for (i = 0; i < num_entries ; i++) {
1270
1271                 init_lsa_String(&r->entries[i].account_name,
1272                                 entries[i].account_name);
1273
1274                 init_lsa_String(&r->entries[i].description,
1275                                 entries[i].description);
1276
1277                 r->entries[i].rid = entries[i].rid;
1278                 r->entries[i].acct_flags = entries[i].acct_flags;
1279                 r->entries[i].idx = start_idx+i+1;
1280         }
1281
1282         return NT_STATUS_OK;
1283 }
1284
1285 /*******************************************************************
1286  inits a samr_DispInfoFullGroups structure.
1287 ********************************************************************/
1288
1289 static NTSTATUS init_samr_dispinfo_3(TALLOC_CTX *ctx,
1290                                      struct samr_DispInfoFullGroups *r,
1291                                      uint32_t num_entries,
1292                                      uint32_t start_idx,
1293                                      struct samr_displayentry *entries)
1294 {
1295         uint32_t i;
1296
1297         DEBUG(5, ("init_samr_dispinfo_3: num_entries: %d\n", num_entries));
1298
1299         if (num_entries == 0) {
1300                 return NT_STATUS_OK;
1301         }
1302
1303         r->count = num_entries;
1304
1305         r->entries = TALLOC_ZERO_ARRAY(ctx, struct samr_DispEntryFullGroup, num_entries);
1306         if (!r->entries) {
1307                 return NT_STATUS_NO_MEMORY;
1308         }
1309
1310         for (i = 0; i < num_entries ; i++) {
1311
1312                 init_lsa_String(&r->entries[i].account_name,
1313                                 entries[i].account_name);
1314
1315                 init_lsa_String(&r->entries[i].description,
1316                                 entries[i].description);
1317
1318                 r->entries[i].rid = entries[i].rid;
1319                 r->entries[i].acct_flags = entries[i].acct_flags;
1320                 r->entries[i].idx = start_idx+i+1;
1321         }
1322
1323         return NT_STATUS_OK;
1324 }
1325
1326 /*******************************************************************
1327  inits a samr_DispInfoAscii structure.
1328 ********************************************************************/
1329
1330 static NTSTATUS init_samr_dispinfo_4(TALLOC_CTX *ctx,
1331                                      struct samr_DispInfoAscii *r,
1332                                      uint32_t num_entries,
1333                                      uint32_t start_idx,
1334                                      struct samr_displayentry *entries)
1335 {
1336         uint32_t i;
1337
1338         DEBUG(5, ("init_samr_dispinfo_4: num_entries: %d\n", num_entries));
1339
1340         if (num_entries == 0) {
1341                 return NT_STATUS_OK;
1342         }
1343
1344         r->count = num_entries;
1345
1346         r->entries = TALLOC_ZERO_ARRAY(ctx, struct samr_DispEntryAscii, num_entries);
1347         if (!r->entries) {
1348                 return NT_STATUS_NO_MEMORY;
1349         }
1350
1351         for (i = 0; i < num_entries ; i++) {
1352
1353                 init_lsa_AsciiStringLarge(&r->entries[i].account_name,
1354                                           entries[i].account_name);
1355
1356                 r->entries[i].idx = start_idx+i+1;
1357         }
1358
1359         return NT_STATUS_OK;
1360 }
1361
1362 /*******************************************************************
1363  inits a samr_DispInfoAscii structure.
1364 ********************************************************************/
1365
1366 static NTSTATUS init_samr_dispinfo_5(TALLOC_CTX *ctx,
1367                                      struct samr_DispInfoAscii *r,
1368                                      uint32_t num_entries,
1369                                      uint32_t start_idx,
1370                                      struct samr_displayentry *entries)
1371 {
1372         uint32_t i;
1373
1374         DEBUG(5, ("init_samr_dispinfo_5: num_entries: %d\n", num_entries));
1375
1376         if (num_entries == 0) {
1377                 return NT_STATUS_OK;
1378         }
1379
1380         r->count = num_entries;
1381
1382         r->entries = TALLOC_ZERO_ARRAY(ctx, struct samr_DispEntryAscii, num_entries);
1383         if (!r->entries) {
1384                 return NT_STATUS_NO_MEMORY;
1385         }
1386
1387         for (i = 0; i < num_entries ; i++) {
1388
1389                 init_lsa_AsciiStringLarge(&r->entries[i].account_name,
1390                                           entries[i].account_name);
1391
1392                 r->entries[i].idx = start_idx+i+1;
1393         }
1394
1395         return NT_STATUS_OK;
1396 }
1397
1398 /*******************************************************************
1399  _samr_QueryDisplayInfo
1400  ********************************************************************/
1401
1402 NTSTATUS _samr_QueryDisplayInfo(pipes_struct *p,
1403                                 struct samr_QueryDisplayInfo *r)
1404 {
1405         NTSTATUS status;
1406         struct samr_domain_info *dinfo;
1407         uint32 struct_size=0x20; /* W2K always reply that, client doesn't care */
1408
1409         uint32 max_entries = r->in.max_entries;
1410
1411         union samr_DispInfo *disp_info = r->out.info;
1412
1413         uint32 temp_size=0, total_data_size=0;
1414         NTSTATUS disp_ret = NT_STATUS_UNSUCCESSFUL;
1415         uint32 num_account = 0;
1416         enum remote_arch_types ra_type = get_remote_arch();
1417         int max_sam_entries = (ra_type == RA_WIN95) ? MAX_SAM_ENTRIES_W95 : MAX_SAM_ENTRIES_W2K;
1418         struct samr_displayentry *entries = NULL;
1419
1420         DEBUG(5,("_samr_QueryDisplayInfo: %d\n", __LINE__));
1421
1422         dinfo = policy_handle_find(p, r->in.domain_handle,
1423                                    SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS, NULL,
1424                                    struct samr_domain_info, &status);
1425         if (!NT_STATUS_IS_OK(status)) {
1426                 return status;
1427         }
1428
1429         if (sid_check_is_builtin(&dinfo->sid)) {
1430                 DEBUG(5,("_samr_QueryDisplayInfo: no users in BUILTIN\n"));
1431                 return NT_STATUS_OK;
1432         }
1433
1434         /*
1435          * calculate how many entries we will return.
1436          * based on
1437          * - the number of entries the client asked
1438          * - our limit on that
1439          * - the starting point (enumeration context)
1440          * - the buffer size the client will accept
1441          */
1442
1443         /*
1444          * We are a lot more like W2K. Instead of reading the SAM
1445          * each time to find the records we need to send back,
1446          * we read it once and link that copy to the sam handle.
1447          * For large user list (over the MAX_SAM_ENTRIES)
1448          * it's a definitive win.
1449          * second point to notice: between enumerations
1450          * our sam is now the same as it's a snapshoot.
1451          * third point: got rid of the static SAM_USER_21 struct
1452          * no more intermediate.
1453          * con: it uses much more memory, as a full copy is stored
1454          * in memory.
1455          *
1456          * If you want to change it, think twice and think
1457          * of the second point , that's really important.
1458          *
1459          * JFM, 12/20/2001
1460          */
1461
1462         if ((r->in.level < 1) || (r->in.level > 5)) {
1463                 DEBUG(0,("_samr_QueryDisplayInfo: Unknown info level (%u)\n",
1464                          (unsigned int)r->in.level ));
1465                 return NT_STATUS_INVALID_INFO_CLASS;
1466         }
1467
1468         /* first limit the number of entries we will return */
1469         if (r->in.max_entries > max_sam_entries) {
1470                 DEBUG(5, ("_samr_QueryDisplayInfo: client requested %d "
1471                           "entries, limiting to %d\n", r->in.max_entries,
1472                           max_sam_entries));
1473                 max_entries = max_sam_entries;
1474         }
1475
1476         /* calculate the size and limit on the number of entries we will
1477          * return */
1478
1479         temp_size=max_entries*struct_size;
1480
1481         if (temp_size > r->in.buf_size) {
1482                 max_entries = MIN((r->in.buf_size / struct_size),max_entries);;
1483                 DEBUG(5, ("_samr_QueryDisplayInfo: buffer size limits to "
1484                           "only %d entries\n", max_entries));
1485         }
1486
1487         become_root();
1488
1489         /* THe following done as ROOT. Don't return without unbecome_root(). */
1490
1491         switch (r->in.level) {
1492         case 1:
1493         case 4:
1494                 if (dinfo->disp_info->users == NULL) {
1495                         dinfo->disp_info->users = pdb_search_users(
1496                                 dinfo->disp_info, ACB_NORMAL);
1497                         if (dinfo->disp_info->users == NULL) {
1498                                 unbecome_root();
1499                                 return NT_STATUS_ACCESS_DENIED;
1500                         }
1501                         DEBUG(10,("_samr_QueryDisplayInfo: starting user enumeration at index %u\n",
1502                                 (unsigned  int)r->in.start_idx));
1503                 } else {
1504                         DEBUG(10,("_samr_QueryDisplayInfo: using cached user enumeration at index %u\n",
1505                                 (unsigned  int)r->in.start_idx));
1506                 }
1507
1508                 num_account = pdb_search_entries(dinfo->disp_info->users,
1509                                                  r->in.start_idx, max_entries,
1510                                                  &entries);
1511                 break;
1512         case 2:
1513                 if (dinfo->disp_info->machines == NULL) {
1514                         dinfo->disp_info->machines = pdb_search_users(
1515                                 dinfo->disp_info, ACB_WSTRUST|ACB_SVRTRUST);
1516                         if (dinfo->disp_info->machines == NULL) {
1517                                 unbecome_root();
1518                                 return NT_STATUS_ACCESS_DENIED;
1519                         }
1520                         DEBUG(10,("_samr_QueryDisplayInfo: starting machine enumeration at index %u\n",
1521                                 (unsigned  int)r->in.start_idx));
1522                 } else {
1523                         DEBUG(10,("_samr_QueryDisplayInfo: using cached machine enumeration at index %u\n",
1524                                 (unsigned  int)r->in.start_idx));
1525                 }
1526
1527                 num_account = pdb_search_entries(dinfo->disp_info->machines,
1528                                                  r->in.start_idx, max_entries,
1529                                                  &entries);
1530                 break;
1531         case 3:
1532         case 5:
1533                 if (dinfo->disp_info->groups == NULL) {
1534                         dinfo->disp_info->groups = pdb_search_groups(
1535                                 dinfo->disp_info);
1536                         if (dinfo->disp_info->groups == NULL) {
1537                                 unbecome_root();
1538                                 return NT_STATUS_ACCESS_DENIED;
1539                         }
1540                         DEBUG(10,("_samr_QueryDisplayInfo: starting group enumeration at index %u\n",
1541                                 (unsigned  int)r->in.start_idx));
1542                 } else {
1543                         DEBUG(10,("_samr_QueryDisplayInfo: using cached group enumeration at index %u\n",
1544                                 (unsigned  int)r->in.start_idx));
1545                 }
1546
1547                 num_account = pdb_search_entries(dinfo->disp_info->groups,
1548                                                  r->in.start_idx, max_entries,
1549                                                  &entries);
1550                 break;
1551         default:
1552                 unbecome_root();
1553                 smb_panic("info class changed");
1554                 break;
1555         }
1556         unbecome_root();
1557
1558
1559         /* Now create reply structure */
1560         switch (r->in.level) {
1561         case 1:
1562                 disp_ret = init_samr_dispinfo_1(p->mem_ctx, &disp_info->info1,
1563                                                 num_account, r->in.start_idx,
1564                                                 entries);
1565                 break;
1566         case 2:
1567                 disp_ret = init_samr_dispinfo_2(p->mem_ctx, &disp_info->info2,
1568                                                 num_account, r->in.start_idx,
1569                                                 entries);
1570                 break;
1571         case 3:
1572                 disp_ret = init_samr_dispinfo_3(p->mem_ctx, &disp_info->info3,
1573                                                 num_account, r->in.start_idx,
1574                                                 entries);
1575                 break;
1576         case 4:
1577                 disp_ret = init_samr_dispinfo_4(p->mem_ctx, &disp_info->info4,
1578                                                 num_account, r->in.start_idx,
1579                                                 entries);
1580                 break;
1581         case 5:
1582                 disp_ret = init_samr_dispinfo_5(p->mem_ctx, &disp_info->info5,
1583                                                 num_account, r->in.start_idx,
1584                                                 entries);
1585                 break;
1586         default:
1587                 smb_panic("info class changed");
1588                 break;
1589         }
1590
1591         if (!NT_STATUS_IS_OK(disp_ret))
1592                 return disp_ret;
1593
1594         /* calculate the total size */
1595         total_data_size=num_account*struct_size;
1596
1597         if (max_entries <= num_account) {
1598                 status = STATUS_MORE_ENTRIES;
1599         } else {
1600                 status = NT_STATUS_OK;
1601         }
1602
1603         /* Ensure we cache this enumeration. */
1604         set_disp_info_cache_timeout(dinfo->disp_info, DISP_INFO_CACHE_TIMEOUT);
1605
1606         DEBUG(5, ("_samr_QueryDisplayInfo: %d\n", __LINE__));
1607
1608         *r->out.total_size = total_data_size;
1609         *r->out.returned_size = temp_size;
1610
1611         return status;
1612 }
1613
1614 /****************************************************************
1615  _samr_QueryDisplayInfo2
1616 ****************************************************************/
1617
1618 NTSTATUS _samr_QueryDisplayInfo2(pipes_struct *p,
1619                                  struct samr_QueryDisplayInfo2 *r)
1620 {
1621         struct samr_QueryDisplayInfo q;
1622
1623         q.in.domain_handle      = r->in.domain_handle;
1624         q.in.level              = r->in.level;
1625         q.in.start_idx          = r->in.start_idx;
1626         q.in.max_entries        = r->in.max_entries;
1627         q.in.buf_size           = r->in.buf_size;
1628
1629         q.out.total_size        = r->out.total_size;
1630         q.out.returned_size     = r->out.returned_size;
1631         q.out.info              = r->out.info;
1632
1633         return _samr_QueryDisplayInfo(p, &q);
1634 }
1635
1636 /****************************************************************
1637  _samr_QueryDisplayInfo3
1638 ****************************************************************/
1639
1640 NTSTATUS _samr_QueryDisplayInfo3(pipes_struct *p,
1641                                  struct samr_QueryDisplayInfo3 *r)
1642 {
1643         struct samr_QueryDisplayInfo q;
1644
1645         q.in.domain_handle      = r->in.domain_handle;
1646         q.in.level              = r->in.level;
1647         q.in.start_idx          = r->in.start_idx;
1648         q.in.max_entries        = r->in.max_entries;
1649         q.in.buf_size           = r->in.buf_size;
1650
1651         q.out.total_size        = r->out.total_size;
1652         q.out.returned_size     = r->out.returned_size;
1653         q.out.info              = r->out.info;
1654
1655         return _samr_QueryDisplayInfo(p, &q);
1656 }
1657
1658 /*******************************************************************
1659  _samr_QueryAliasInfo
1660  ********************************************************************/
1661
1662 NTSTATUS _samr_QueryAliasInfo(pipes_struct *p,
1663                               struct samr_QueryAliasInfo *r)
1664 {
1665         struct samr_alias_info *ainfo;
1666         struct acct_info info;
1667         NTSTATUS status;
1668         union samr_AliasInfo *alias_info = NULL;
1669         const char *alias_name = NULL;
1670         const char *alias_description = NULL;
1671
1672         DEBUG(5,("_samr_QueryAliasInfo: %d\n", __LINE__));
1673
1674         ainfo = policy_handle_find(p, r->in.alias_handle,
1675                                    SAMR_ALIAS_ACCESS_LOOKUP_INFO, NULL,
1676                                    struct samr_alias_info, &status);
1677         if (!NT_STATUS_IS_OK(status)) {
1678                 return status;
1679         }
1680
1681         alias_info = TALLOC_ZERO_P(p->mem_ctx, union samr_AliasInfo);
1682         if (!alias_info) {
1683                 return NT_STATUS_NO_MEMORY;
1684         }
1685
1686         become_root();
1687         status = pdb_get_aliasinfo(&ainfo->sid, &info);
1688         unbecome_root();
1689
1690         if ( !NT_STATUS_IS_OK(status))
1691                 return status;
1692
1693         /* FIXME: info contains fstrings */
1694         alias_name = talloc_strdup(r, info.acct_name);
1695         alias_description = talloc_strdup(r, info.acct_desc);
1696
1697         switch (r->in.level) {
1698         case ALIASINFOALL:
1699                 alias_info->all.name.string             = alias_name;
1700                 alias_info->all.num_members             = 1; /* ??? */
1701                 alias_info->all.description.string      = alias_description;
1702                 break;
1703         case ALIASINFONAME:
1704                 alias_info->name.string                 = alias_name;
1705                 break;
1706         case ALIASINFODESCRIPTION:
1707                 alias_info->description.string          = alias_description;
1708                 break;
1709         default:
1710                 return NT_STATUS_INVALID_INFO_CLASS;
1711         }
1712
1713         *r->out.info = alias_info;
1714
1715         DEBUG(5,("_samr_QueryAliasInfo: %d\n", __LINE__));
1716
1717         return NT_STATUS_OK;
1718 }
1719
1720 /*******************************************************************
1721  _samr_LookupNames
1722  ********************************************************************/
1723
1724 NTSTATUS _samr_LookupNames(pipes_struct *p,
1725                            struct samr_LookupNames *r)
1726 {
1727         struct samr_domain_info *dinfo;
1728         NTSTATUS status;
1729         uint32 *rid;
1730         enum lsa_SidType *type;
1731         int i;
1732         int num_rids = r->in.num_names;
1733         struct samr_Ids rids, types;
1734         uint32_t num_mapped = 0;
1735
1736         DEBUG(5,("_samr_LookupNames: %d\n", __LINE__));
1737
1738         dinfo = policy_handle_find(p, r->in.domain_handle,
1739                                    0 /* Don't know the acc_bits yet */, NULL,
1740                                    struct samr_domain_info, &status);
1741         if (!NT_STATUS_IS_OK(status)) {
1742                 return status;
1743         }
1744
1745         if (num_rids > MAX_SAM_ENTRIES) {
1746                 num_rids = MAX_SAM_ENTRIES;
1747                 DEBUG(5,("_samr_LookupNames: truncating entries to %d\n", num_rids));
1748         }
1749
1750         rid = talloc_array(p->mem_ctx, uint32, num_rids);
1751         NT_STATUS_HAVE_NO_MEMORY(rid);
1752
1753         type = talloc_array(p->mem_ctx, enum lsa_SidType, num_rids);
1754         NT_STATUS_HAVE_NO_MEMORY(type);
1755
1756         DEBUG(5,("_samr_LookupNames: looking name on SID %s\n",
1757                  sid_string_dbg(&dinfo->sid)));
1758
1759         for (i = 0; i < num_rids; i++) {
1760
1761                 status = NT_STATUS_NONE_MAPPED;
1762                 type[i] = SID_NAME_UNKNOWN;
1763
1764                 rid[i] = 0xffffffff;
1765
1766                 if (sid_check_is_builtin(&dinfo->sid)) {
1767                         if (lookup_builtin_name(r->in.names[i].string,
1768                                                 &rid[i]))
1769                         {
1770                                 type[i] = SID_NAME_ALIAS;
1771                         }
1772                 } else {
1773                         lookup_global_sam_name(r->in.names[i].string, 0,
1774                                                &rid[i], &type[i]);
1775                 }
1776
1777                 if (type[i] != SID_NAME_UNKNOWN) {
1778                         num_mapped++;
1779                 }
1780         }
1781
1782         if (num_mapped == num_rids) {
1783                 status = NT_STATUS_OK;
1784         } else if (num_mapped == 0) {
1785                 status = NT_STATUS_NONE_MAPPED;
1786         } else {
1787                 status = STATUS_SOME_UNMAPPED;
1788         }
1789
1790         rids.count = num_rids;
1791         rids.ids = rid;
1792
1793         types.count = num_rids;
1794         types.ids = type;
1795
1796         *r->out.rids = rids;
1797         *r->out.types = types;
1798
1799         DEBUG(5,("_samr_LookupNames: %d\n", __LINE__));
1800
1801         return status;
1802 }
1803
1804 /****************************************************************
1805  _samr_ChangePasswordUser
1806 ****************************************************************/
1807
1808 NTSTATUS _samr_ChangePasswordUser(pipes_struct *p,
1809                                   struct samr_ChangePasswordUser *r)
1810 {
1811         NTSTATUS status;
1812         bool ret = false;
1813         struct samr_user_info *uinfo;
1814         struct samu *pwd;
1815         struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash;
1816         struct samr_Password lm_pwd, nt_pwd;
1817
1818         uinfo = policy_handle_find(p, r->in.user_handle,
1819                                    SAMR_USER_ACCESS_SET_PASSWORD, NULL,
1820                                    struct samr_user_info, &status);
1821         if (!NT_STATUS_IS_OK(status)) {
1822                 return status;
1823         }
1824
1825         DEBUG(5,("_samr_ChangePasswordUser: sid:%s\n",
1826                   sid_string_dbg(&uinfo->sid)));
1827
1828         if (!(pwd = samu_new(NULL))) {
1829                 return NT_STATUS_NO_MEMORY;
1830         }
1831
1832         become_root();
1833         ret = pdb_getsampwsid(pwd, &uinfo->sid);
1834         unbecome_root();
1835
1836         if (!ret) {
1837                 TALLOC_FREE(pwd);
1838                 return NT_STATUS_WRONG_PASSWORD;
1839         }
1840
1841         {
1842                 const uint8_t *lm_pass, *nt_pass;
1843
1844                 lm_pass = pdb_get_lanman_passwd(pwd);
1845                 nt_pass = pdb_get_nt_passwd(pwd);
1846
1847                 if (!lm_pass || !nt_pass) {
1848                         status = NT_STATUS_WRONG_PASSWORD;
1849                         goto out;
1850                 }
1851
1852                 memcpy(&lm_pwd.hash, lm_pass, sizeof(lm_pwd.hash));
1853                 memcpy(&nt_pwd.hash, nt_pass, sizeof(nt_pwd.hash));
1854         }
1855
1856         /* basic sanity checking on parameters.  Do this before any database ops */
1857         if (!r->in.lm_present || !r->in.nt_present ||
1858             !r->in.old_lm_crypted || !r->in.new_lm_crypted ||
1859             !r->in.old_nt_crypted || !r->in.new_nt_crypted) {
1860                 /* we should really handle a change with lm not
1861                    present */
1862                 status = NT_STATUS_INVALID_PARAMETER_MIX;
1863                 goto out;
1864         }
1865
1866         /* decrypt and check the new lm hash */
1867         D_P16(lm_pwd.hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash);
1868         D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash);
1869         if (memcmp(checkHash.hash, lm_pwd.hash, 16) != 0) {
1870                 status = NT_STATUS_WRONG_PASSWORD;
1871                 goto out;
1872         }
1873
1874         /* decrypt and check the new nt hash */
1875         D_P16(nt_pwd.hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash);
1876         D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash);
1877         if (memcmp(checkHash.hash, nt_pwd.hash, 16) != 0) {
1878                 status = NT_STATUS_WRONG_PASSWORD;
1879                 goto out;
1880         }
1881
1882         /* The NT Cross is not required by Win2k3 R2, but if present
1883            check the nt cross hash */
1884         if (r->in.cross1_present && r->in.nt_cross) {
1885                 D_P16(lm_pwd.hash, r->in.nt_cross->hash, checkHash.hash);
1886                 if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
1887                         status = NT_STATUS_WRONG_PASSWORD;
1888                         goto out;
1889                 }
1890         }
1891
1892         /* The LM Cross is not required by Win2k3 R2, but if present
1893            check the lm cross hash */
1894         if (r->in.cross2_present && r->in.lm_cross) {
1895                 D_P16(nt_pwd.hash, r->in.lm_cross->hash, checkHash.hash);
1896                 if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
1897                         status = NT_STATUS_WRONG_PASSWORD;
1898                         goto out;
1899                 }
1900         }
1901
1902         if (!pdb_set_nt_passwd(pwd, new_ntPwdHash.hash, PDB_CHANGED) ||
1903             !pdb_set_lanman_passwd(pwd, new_lmPwdHash.hash, PDB_CHANGED)) {
1904                 status = NT_STATUS_ACCESS_DENIED;
1905                 goto out;
1906         }
1907
1908         status = pdb_update_sam_account(pwd);
1909  out:
1910         TALLOC_FREE(pwd);
1911
1912         return status;
1913 }
1914
1915 /*******************************************************************
1916  _samr_ChangePasswordUser2
1917  ********************************************************************/
1918
1919 NTSTATUS _samr_ChangePasswordUser2(pipes_struct *p,
1920                                    struct samr_ChangePasswordUser2 *r)
1921 {
1922         struct smbd_server_connection *sconn = smbd_server_conn;
1923         NTSTATUS status;
1924         fstring user_name;
1925         fstring wks;
1926
1927         DEBUG(5,("_samr_ChangePasswordUser2: %d\n", __LINE__));
1928
1929         fstrcpy(user_name, r->in.account->string);
1930         fstrcpy(wks, r->in.server->string);
1931
1932         DEBUG(5,("_samr_ChangePasswordUser2: user: %s wks: %s\n", user_name, wks));
1933
1934         /*
1935          * Pass the user through the NT -> unix user mapping
1936          * function.
1937          */
1938
1939         (void)map_username(sconn, user_name);
1940
1941         /*
1942          * UNIX username case mangling not required, pass_oem_change
1943          * is case insensitive.
1944          */
1945
1946         status = pass_oem_change(user_name,
1947                                  r->in.lm_password->data,
1948                                  r->in.lm_verifier->hash,
1949                                  r->in.nt_password->data,
1950                                  r->in.nt_verifier->hash,
1951                                  NULL);
1952
1953         DEBUG(5,("_samr_ChangePasswordUser2: %d\n", __LINE__));
1954
1955         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1956                 return NT_STATUS_WRONG_PASSWORD;
1957         }
1958
1959         return status;
1960 }
1961
1962 /****************************************************************
1963  _samr_OemChangePasswordUser2
1964 ****************************************************************/
1965
1966 NTSTATUS _samr_OemChangePasswordUser2(pipes_struct *p,
1967                                       struct samr_OemChangePasswordUser2 *r)
1968 {
1969         struct smbd_server_connection *sconn = smbd_server_conn;
1970         NTSTATUS status;
1971         fstring user_name;
1972         const char *wks = NULL;
1973
1974         DEBUG(5,("_samr_OemChangePasswordUser2: %d\n", __LINE__));
1975
1976         fstrcpy(user_name, r->in.account->string);
1977         if (r->in.server && r->in.server->string) {
1978                 wks = r->in.server->string;
1979         }
1980
1981         DEBUG(5,("_samr_OemChangePasswordUser2: user: %s wks: %s\n", user_name, wks));
1982
1983         /*
1984          * Pass the user through the NT -> unix user mapping
1985          * function.
1986          */
1987
1988         (void)map_username(sconn, user_name);
1989
1990         /*
1991          * UNIX username case mangling not required, pass_oem_change
1992          * is case insensitive.
1993          */
1994
1995         if (!r->in.hash || !r->in.password) {
1996                 return NT_STATUS_INVALID_PARAMETER;
1997         }
1998
1999         status = pass_oem_change(user_name,
2000                                  r->in.password->data,
2001                                  r->in.hash->hash,
2002                                  0,
2003                                  0,
2004                                  NULL);
2005
2006         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
2007                 return NT_STATUS_WRONG_PASSWORD;
2008         }
2009
2010         DEBUG(5,("_samr_OemChangePasswordUser2: %d\n", __LINE__));
2011
2012         return status;
2013 }
2014
2015 /*******************************************************************
2016  _samr_ChangePasswordUser3
2017  ********************************************************************/
2018
2019 NTSTATUS _samr_ChangePasswordUser3(pipes_struct *p,
2020                                    struct samr_ChangePasswordUser3 *r)
2021 {
2022         struct smbd_server_connection *sconn = smbd_server_conn;
2023         NTSTATUS status;
2024         fstring user_name;
2025         const char *wks = NULL;
2026         uint32 reject_reason;
2027         struct samr_DomInfo1 *dominfo = NULL;
2028         struct samr_ChangeReject *reject = NULL;
2029         uint32_t tmp;
2030
2031         DEBUG(5,("_samr_ChangePasswordUser3: %d\n", __LINE__));
2032
2033         fstrcpy(user_name, r->in.account->string);
2034         if (r->in.server && r->in.server->string) {
2035                 wks = r->in.server->string;
2036         }
2037
2038         DEBUG(5,("_samr_ChangePasswordUser3: user: %s wks: %s\n", user_name, wks));
2039
2040         /*
2041          * Pass the user through the NT -> unix user mapping
2042          * function.
2043          */
2044
2045         (void)map_username(sconn, user_name);
2046
2047         /*
2048          * UNIX username case mangling not required, pass_oem_change
2049          * is case insensitive.
2050          */
2051
2052         status = pass_oem_change(user_name,
2053                                  r->in.lm_password->data,
2054                                  r->in.lm_verifier->hash,
2055                                  r->in.nt_password->data,
2056                                  r->in.nt_verifier->hash,
2057                                  &reject_reason);
2058         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
2059                 return NT_STATUS_WRONG_PASSWORD;
2060         }
2061
2062         if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) ||
2063             NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_RESTRICTION)) {
2064
2065                 time_t u_expire, u_min_age;
2066                 uint32 account_policy_temp;
2067
2068                 dominfo = TALLOC_ZERO_P(p->mem_ctx, struct samr_DomInfo1);
2069                 if (!dominfo) {
2070                         return NT_STATUS_NO_MEMORY;
2071                 }
2072
2073                 reject = TALLOC_ZERO_P(p->mem_ctx, struct samr_ChangeReject);
2074                 if (!reject) {
2075                         return NT_STATUS_NO_MEMORY;
2076                 }
2077
2078                 become_root();
2079
2080                 /* AS ROOT !!! */
2081
2082                 pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &tmp);
2083                 dominfo->min_password_length = tmp;
2084
2085                 pdb_get_account_policy(AP_PASSWORD_HISTORY, &tmp);
2086                 dominfo->password_history_length = tmp;
2087
2088                 pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS,
2089                                        &dominfo->password_properties);
2090
2091                 pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp);
2092                 u_expire = account_policy_temp;
2093
2094                 pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp);
2095                 u_min_age = account_policy_temp;
2096
2097                 /* !AS ROOT */
2098
2099                 unbecome_root();
2100
2101                 unix_to_nt_time_abs((NTTIME *)&dominfo->max_password_age, u_expire);
2102                 unix_to_nt_time_abs((NTTIME *)&dominfo->min_password_age, u_min_age);
2103
2104                 if (lp_check_password_script() && *lp_check_password_script()) {
2105                         dominfo->password_properties |= DOMAIN_PASSWORD_COMPLEX;
2106                 }
2107
2108                 reject->reason = reject_reason;
2109
2110                 *r->out.dominfo = dominfo;
2111                 *r->out.reject = reject;
2112         }
2113
2114         DEBUG(5,("_samr_ChangePasswordUser3: %d\n", __LINE__));
2115
2116         return status;
2117 }
2118
2119 /*******************************************************************
2120 makes a SAMR_R_LOOKUP_RIDS structure.
2121 ********************************************************************/
2122
2123 static bool make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names,
2124                                   const char **names,
2125                                   struct lsa_String **lsa_name_array_p)
2126 {
2127         struct lsa_String *lsa_name_array = NULL;
2128         uint32_t i;
2129
2130         *lsa_name_array_p = NULL;
2131
2132         if (num_names != 0) {
2133                 lsa_name_array = TALLOC_ZERO_ARRAY(ctx, struct lsa_String, num_names);
2134                 if (!lsa_name_array) {
2135                         return false;
2136                 }
2137         }
2138
2139         for (i = 0; i < num_names; i++) {
2140                 DEBUG(10, ("names[%d]:%s\n", i, names[i] && *names[i] ? names[i] : ""));
2141                 init_lsa_String(&lsa_name_array[i], names[i]);
2142         }
2143
2144         *lsa_name_array_p = lsa_name_array;
2145
2146         return true;
2147 }
2148
2149 /*******************************************************************
2150  _samr_LookupRids
2151  ********************************************************************/
2152
2153 NTSTATUS _samr_LookupRids(pipes_struct *p,
2154                           struct samr_LookupRids *r)
2155 {
2156         struct samr_domain_info *dinfo;
2157         NTSTATUS status;
2158         const char **names;
2159         enum lsa_SidType *attrs = NULL;
2160         uint32 *wire_attrs = NULL;
2161         int num_rids = (int)r->in.num_rids;
2162         int i;
2163         struct lsa_Strings names_array;
2164         struct samr_Ids types_array;
2165         struct lsa_String *lsa_names = NULL;
2166
2167         DEBUG(5,("_samr_LookupRids: %d\n", __LINE__));
2168
2169         dinfo = policy_handle_find(p, r->in.domain_handle,
2170                                    0 /* Don't know the acc_bits yet */, NULL,
2171                                    struct samr_domain_info, &status);
2172         if (!NT_STATUS_IS_OK(status)) {
2173                 return status;
2174         }
2175
2176         if (num_rids > 1000) {
2177                 DEBUG(0, ("Got asked for %d rids (more than 1000) -- according "
2178                           "to samba4 idl this is not possible\n", num_rids));
2179                 return NT_STATUS_UNSUCCESSFUL;
2180         }
2181
2182         if (num_rids) {
2183                 names = TALLOC_ZERO_ARRAY(p->mem_ctx, const char *, num_rids);
2184                 attrs = TALLOC_ZERO_ARRAY(p->mem_ctx, enum lsa_SidType, num_rids);
2185                 wire_attrs = TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num_rids);
2186
2187                 if ((names == NULL) || (attrs == NULL) || (wire_attrs==NULL))
2188                         return NT_STATUS_NO_MEMORY;
2189         } else {
2190                 names = NULL;
2191                 attrs = NULL;
2192                 wire_attrs = NULL;
2193         }
2194
2195         become_root();  /* lookup_sid can require root privs */
2196         status = pdb_lookup_rids(&dinfo->sid, num_rids, r->in.rids,
2197                                  names, attrs);
2198         unbecome_root();
2199
2200         if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED) && (num_rids == 0)) {
2201                 status = NT_STATUS_OK;
2202         }
2203
2204         if (!make_samr_lookup_rids(p->mem_ctx, num_rids, names,
2205                                    &lsa_names)) {
2206                 return NT_STATUS_NO_MEMORY;
2207         }
2208
2209         /* Convert from enum lsa_SidType to uint32 for wire format. */
2210         for (i = 0; i < num_rids; i++) {
2211                 wire_attrs[i] = (uint32)attrs[i];
2212         }
2213
2214         names_array.count = num_rids;
2215         names_array.names = lsa_names;
2216
2217         types_array.count = num_rids;
2218         types_array.ids = wire_attrs;
2219
2220         *r->out.names = names_array;
2221         *r->out.types = types_array;
2222
2223         DEBUG(5,("_samr_LookupRids: %d\n", __LINE__));
2224
2225         return status;
2226 }
2227
2228 /*******************************************************************
2229  _samr_OpenUser
2230 ********************************************************************/
2231
2232 NTSTATUS _samr_OpenUser(pipes_struct *p,
2233                         struct samr_OpenUser *r)
2234 {
2235         struct samu *sampass=NULL;
2236         DOM_SID sid;
2237         struct samr_domain_info *dinfo;
2238         struct samr_user_info *uinfo;
2239         SEC_DESC *psd = NULL;
2240         uint32    acc_granted;
2241         uint32    des_access = r->in.access_mask;
2242         uint32_t extra_access = 0;
2243         size_t    sd_size;
2244         bool ret;
2245         NTSTATUS nt_status;
2246         SE_PRIV se_rights;
2247         NTSTATUS status;
2248
2249         dinfo = policy_handle_find(p, r->in.domain_handle,
2250                                    SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, NULL,
2251                                    struct samr_domain_info, &status);
2252         if (!NT_STATUS_IS_OK(status)) {
2253                 return status;
2254         }
2255
2256         if ( !(sampass = samu_new( p->mem_ctx )) ) {
2257                 return NT_STATUS_NO_MEMORY;
2258         }
2259
2260         /* append the user's RID to it */
2261
2262         if (!sid_compose(&sid, &dinfo->sid, r->in.rid))
2263                 return NT_STATUS_NO_SUCH_USER;
2264
2265         /* check if access can be granted as requested by client. */
2266
2267         map_max_allowed_access(p->server_info->ptok, &des_access);
2268
2269         make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &sid, SAMR_USR_RIGHTS_WRITE_PW);
2270         se_map_generic(&des_access, &usr_generic_mapping);
2271
2272         /*
2273          * Get the sampass first as we need to check privilages
2274          * based on what kind of user object this is.
2275          * But don't reveal info too early if it didn't exist.
2276          */
2277
2278         become_root();
2279         ret=pdb_getsampwsid(sampass, &sid);
2280         unbecome_root();
2281
2282         se_priv_copy(&se_rights, &se_priv_none);
2283
2284         /*
2285          * We do the override access checks on *open*, not at
2286          * SetUserInfo time.
2287          */
2288         if (ret) {
2289                 uint32_t acb_info = pdb_get_acct_ctrl(sampass);
2290
2291                 if ((acb_info & ACB_WSTRUST) &&
2292                                 user_has_any_privilege(p->server_info->ptok,
2293                                                 &se_machine_account)) {
2294                         /*
2295                          * SeMachineAccount is needed to add
2296                          * GENERIC_RIGHTS_USER_WRITE to a machine
2297                          * account.
2298                          */
2299                         se_priv_add(&se_rights, &se_machine_account);
2300                         DEBUG(10,("_samr_OpenUser: adding machine account "
2301                                 "rights to handle for user %s\n",
2302                                 pdb_get_username(sampass) ));
2303                 }
2304                 if ((acb_info & ACB_NORMAL) &&
2305                                 user_has_any_privilege(p->server_info->ptok,
2306                                                 &se_add_users)) {
2307                         /*
2308                          * SeAddUsers is needed to add
2309                          * GENERIC_RIGHTS_USER_WRITE to a normal
2310                          * account.
2311                          */
2312                         se_priv_add(&se_rights, &se_add_users);
2313                         DEBUG(10,("_samr_OpenUser: adding add user "
2314                                 "rights to handle for user %s\n",
2315                                 pdb_get_username(sampass) ));
2316                 }
2317                 /*
2318                  * Cheat - allow GENERIC_RIGHTS_USER_WRITE if pipe user is
2319                  * in DOMAIN_GROUP_RID_ADMINS. This is almost certainly not
2320                  * what Windows does but is a hack for people who haven't
2321                  * set up privilages on groups in Samba.
2322                  */
2323                 if (acb_info & (ACB_SVRTRUST|ACB_DOMTRUST)) {
2324                         if (lp_enable_privileges() && nt_token_check_domain_rid(p->server_info->ptok,
2325                                                         DOMAIN_GROUP_RID_ADMINS)) {
2326                                 des_access &= ~GENERIC_RIGHTS_USER_WRITE;
2327                                 extra_access = GENERIC_RIGHTS_USER_WRITE;
2328                                 DEBUG(4,("_samr_OpenUser: Allowing "
2329                                         "GENERIC_RIGHTS_USER_WRITE for "
2330                                         "rid admins\n"));
2331                         }
2332                 }
2333         }
2334
2335         TALLOC_FREE(sampass);
2336
2337         nt_status = access_check_object(psd, p->server_info->ptok,
2338                 &se_rights, GENERIC_RIGHTS_USER_WRITE, des_access,
2339                 &acc_granted, "_samr_OpenUser");
2340
2341         if ( !NT_STATUS_IS_OK(nt_status) )
2342                 return nt_status;
2343
2344         /* check that the SID exists in our domain. */
2345         if (ret == False) {
2346                 return NT_STATUS_NO_SUCH_USER;
2347         }
2348
2349         /* If we did the rid admins hack above, allow access. */
2350         acc_granted |= extra_access;
2351
2352         uinfo = policy_handle_create(p, r->out.user_handle, acc_granted,
2353                                      struct samr_user_info, &nt_status);
2354         if (!NT_STATUS_IS_OK(nt_status)) {
2355                 return nt_status;
2356         }
2357         uinfo->sid = sid;
2358
2359         return NT_STATUS_OK;
2360 }
2361
2362 /*************************************************************************
2363  *************************************************************************/
2364
2365 static NTSTATUS init_samr_parameters_string(TALLOC_CTX *mem_ctx,
2366                                             DATA_BLOB *blob,
2367                                             struct lsa_BinaryString **_r)
2368 {
2369         struct lsa_BinaryString *r;
2370
2371         if (!blob || !_r) {
2372                 return NT_STATUS_INVALID_PARAMETER;
2373         }
2374
2375         r = TALLOC_ZERO_P(mem_ctx, struct lsa_BinaryString);
2376         if (!r) {
2377                 return NT_STATUS_NO_MEMORY;
2378         }
2379
2380         r->array = TALLOC_ZERO_ARRAY(mem_ctx, uint16_t, blob->length/2);
2381         if (!r->array) {
2382                 return NT_STATUS_NO_MEMORY;
2383         }
2384         memcpy(r->array, blob->data, blob->length);
2385         r->size = blob->length;
2386         r->length = blob->length;
2387
2388         if (!r->array) {
2389                 return NT_STATUS_NO_MEMORY;
2390         }
2391
2392         *_r = r;
2393
2394         return NT_STATUS_OK;
2395 }
2396
2397 /*************************************************************************
2398  get_user_info_1.
2399  *************************************************************************/
2400
2401 static NTSTATUS get_user_info_1(TALLOC_CTX *mem_ctx,
2402                                 struct samr_UserInfo1 *r,
2403                                 struct samu *pw,
2404                                 DOM_SID *domain_sid)
2405 {
2406         const DOM_SID *sid_group;
2407         uint32_t primary_gid;
2408
2409         become_root();
2410         sid_group = pdb_get_group_sid(pw);
2411         unbecome_root();
2412
2413         if (!sid_peek_check_rid(domain_sid, sid_group, &primary_gid)) {
2414                 DEBUG(0, ("get_user_info_1: User %s has Primary Group SID %s, \n"
2415                           "which conflicts with the domain sid %s.  Failing operation.\n",
2416                           pdb_get_username(pw), sid_string_dbg(sid_group),
2417                           sid_string_dbg(domain_sid)));
2418                 return NT_STATUS_UNSUCCESSFUL;
2419         }
2420
2421         r->account_name.string          = talloc_strdup(mem_ctx, pdb_get_username(pw));
2422         r->full_name.string             = talloc_strdup(mem_ctx, pdb_get_fullname(pw));
2423         r->primary_gid                  = primary_gid;
2424         r->description.string           = talloc_strdup(mem_ctx, pdb_get_acct_desc(pw));
2425         r->comment.string               = talloc_strdup(mem_ctx, pdb_get_comment(pw));
2426
2427         return NT_STATUS_OK;
2428 }
2429
2430 /*************************************************************************
2431  get_user_info_2.
2432  *************************************************************************/
2433
2434 static NTSTATUS get_user_info_2(TALLOC_CTX *mem_ctx,
2435                                 struct samr_UserInfo2 *r,
2436                                 struct samu *pw)
2437 {
2438         r->comment.string               = talloc_strdup(mem_ctx, pdb_get_comment(pw));
2439         r->unknown.string               = NULL;
2440         r->country_code                 = 0;
2441         r->code_page                    = 0;
2442
2443         return NT_STATUS_OK;
2444 }
2445
2446 /*************************************************************************
2447  get_user_info_3.
2448  *************************************************************************/
2449
2450 static NTSTATUS get_user_info_3(TALLOC_CTX *mem_ctx,
2451                                 struct samr_UserInfo3 *r,
2452                                 struct samu *pw,
2453                                 DOM_SID *domain_sid)
2454 {
2455         const DOM_SID *sid_user, *sid_group;
2456         uint32_t rid, primary_gid;
2457
2458         sid_user = pdb_get_user_sid(pw);
2459
2460         if (!sid_peek_check_rid(domain_sid, sid_user, &rid)) {
2461                 DEBUG(0, ("get_user_info_3: User %s has SID %s, \nwhich conflicts with "
2462                           "the domain sid %s.  Failing operation.\n",
2463                           pdb_get_username(pw), sid_string_dbg(sid_user),
2464                           sid_string_dbg(domain_sid)));
2465                 return NT_STATUS_UNSUCCESSFUL;
2466         }
2467
2468         become_root();
2469         sid_group = pdb_get_group_sid(pw);
2470         unbecome_root();
2471
2472         if (!sid_peek_check_rid(domain_sid, sid_group, &primary_gid)) {
2473                 DEBUG(0, ("get_user_info_3: User %s has Primary Group SID %s, \n"
2474                           "which conflicts with the domain sid %s.  Failing operation.\n",
2475                           pdb_get_username(pw), sid_string_dbg(sid_group),
2476                           sid_string_dbg(domain_sid)));
2477                 return NT_STATUS_UNSUCCESSFUL;
2478         }
2479
2480         unix_to_nt_time(&r->last_logon, pdb_get_logon_time(pw));
2481         unix_to_nt_time(&r->last_logoff, pdb_get_logoff_time(pw));
2482         unix_to_nt_time(&r->last_password_change, pdb_get_pass_last_set_time(pw));
2483         unix_to_nt_time(&r->allow_password_change, pdb_get_pass_can_change_time(pw));
2484         unix_to_nt_time(&r->force_password_change, pdb_get_pass_must_change_time(pw));
2485
2486         r->account_name.string  = talloc_strdup(mem_ctx, pdb_get_username(pw));
2487         r->full_name.string     = talloc_strdup(mem_ctx, pdb_get_fullname(pw));
2488         r->home_directory.string= talloc_strdup(mem_ctx, pdb_get_homedir(pw));
2489         r->home_drive.string    = talloc_strdup(mem_ctx, pdb_get_dir_drive(pw));
2490         r->logon_script.string  = talloc_strdup(mem_ctx, pdb_get_logon_script(pw));
2491         r->profile_path.string  = talloc_strdup(mem_ctx, pdb_get_profile_path(pw));
2492         r->workstations.string  = talloc_strdup(mem_ctx, pdb_get_workstations(pw));
2493
2494         r->logon_hours          = get_logon_hours_from_pdb(mem_ctx, pw);
2495         r->rid                  = rid;
2496         r->primary_gid          = primary_gid;
2497         r->acct_flags           = pdb_get_acct_ctrl(pw);
2498         r->bad_password_count   = pdb_get_bad_password_count(pw);
2499         r->logon_count          = pdb_get_logon_count(pw);
2500
2501         return NT_STATUS_OK;
2502 }
2503
2504 /*************************************************************************
2505  get_user_info_4.
2506  *************************************************************************/
2507
2508 static NTSTATUS get_user_info_4(TALLOC_CTX *mem_ctx,
2509                                 struct samr_UserInfo4 *r,
2510                                 struct samu *pw)
2511 {
2512         r->logon_hours          = get_logon_hours_from_pdb(mem_ctx, pw);
2513
2514         return NT_STATUS_OK;
2515 }
2516
2517 /*************************************************************************
2518  get_user_info_5.
2519  *************************************************************************/
2520
2521 static NTSTATUS get_user_info_5(TALLOC_CTX *mem_ctx,
2522                                 struct samr_UserInfo5 *r,
2523                                 struct samu *pw,
2524                                 DOM_SID *domain_sid)
2525 {
2526         const DOM_SID *sid_user, *sid_group;
2527         uint32_t rid, primary_gid;
2528
2529         sid_user = pdb_get_user_sid(pw);
2530
2531         if (!sid_peek_check_rid(domain_sid, sid_user, &rid)) {
2532                 DEBUG(0, ("get_user_info_5: User %s has SID %s, \nwhich conflicts with "
2533                           "the domain sid %s.  Failing operation.\n",
2534                           pdb_get_username(pw), sid_string_dbg(sid_user),
2535                           sid_string_dbg(domain_sid)));
2536                 return NT_STATUS_UNSUCCESSFUL;
2537         }
2538
2539         become_root();
2540         sid_group = pdb_get_group_sid(pw);
2541         unbecome_root();
2542
2543         if (!sid_peek_check_rid(domain_sid, sid_group, &primary_gid)) {
2544                 DEBUG(0, ("get_user_info_5: User %s has Primary Group SID %s, \n"
2545                           "which conflicts with the domain sid %s.  Failing operation.\n",
2546                           pdb_get_username(pw), sid_string_dbg(sid_group),
2547                           sid_string_dbg(domain_sid)));
2548                 return NT_STATUS_UNSUCCESSFUL;
2549         }
2550
2551         unix_to_nt_time(&r->last_logon, pdb_get_logon_time(pw));
2552         unix_to_nt_time(&r->last_logoff, pdb_get_logoff_time(pw));
2553         unix_to_nt_time(&r->acct_expiry, pdb_get_kickoff_time(pw));
2554         unix_to_nt_time(&r->last_password_change, pdb_get_pass_last_set_time(pw));
2555
2556         r->account_name.string  = talloc_strdup(mem_ctx, pdb_get_username(pw));
2557         r->full_name.string     = talloc_strdup(mem_ctx, pdb_get_fullname(pw));
2558         r->home_directory.string= talloc_strdup(mem_ctx, pdb_get_homedir(pw));
2559         r->home_drive.string    = talloc_strdup(mem_ctx, pdb_get_dir_drive(pw));
2560         r->logon_script.string  = talloc_strdup(mem_ctx, pdb_get_logon_script(pw));
2561         r->profile_path.string  = talloc_strdup(mem_ctx, pdb_get_profile_path(pw));
2562         r->description.string   = talloc_strdup(mem_ctx, pdb_get_acct_desc(pw));
2563         r->workstations.string  = talloc_strdup(mem_ctx, pdb_get_workstations(pw));
2564
2565         r->logon_hours          = get_logon_hours_from_pdb(mem_ctx, pw);
2566         r->rid                  = rid;
2567         r->primary_gid          = primary_gid;
2568         r->acct_flags           = pdb_get_acct_ctrl(pw);
2569         r->bad_password_count   = pdb_get_bad_password_count(pw);
2570         r->logon_count          = pdb_get_logon_count(pw);
2571
2572         return NT_STATUS_OK;
2573 }
2574
2575 /*************************************************************************
2576  get_user_info_6.
2577  *************************************************************************/
2578
2579 static NTSTATUS get_user_info_6(TALLOC_CTX *mem_ctx,
2580                                 struct samr_UserInfo6 *r,
2581                                 struct samu *pw)
2582 {
2583         r->account_name.string  = talloc_strdup(mem_ctx, pdb_get_username(pw));
2584         r->full_name.string     = talloc_strdup(mem_ctx, pdb_get_fullname(pw));
2585
2586         return NT_STATUS_OK;
2587 }
2588
2589 /*************************************************************************
2590  get_user_info_7. Safe. Only gives out account_name.
2591  *************************************************************************/
2592
2593 static NTSTATUS get_user_info_7(TALLOC_CTX *mem_ctx,
2594                                 struct samr_UserInfo7 *r,
2595                                 struct samu *smbpass)
2596 {
2597         r->account_name.string = talloc_strdup(mem_ctx, pdb_get_username(smbpass));
2598         if (!r->account_name.string) {
2599                 return NT_STATUS_NO_MEMORY;
2600         }
2601
2602         return NT_STATUS_OK;
2603 }
2604
2605 /*************************************************************************
2606  get_user_info_8.
2607  *************************************************************************/
2608
2609 static NTSTATUS get_user_info_8(TALLOC_CTX *mem_ctx,
2610                                 struct samr_UserInfo8 *r,
2611                                 struct samu *pw)
2612 {
2613         r->full_name.string     = talloc_strdup(mem_ctx, pdb_get_fullname(pw));
2614
2615         return NT_STATUS_OK;
2616 }
2617
2618 /*************************************************************************
2619  get_user_info_9. Only gives out primary group SID.
2620  *************************************************************************/
2621
2622 static NTSTATUS get_user_info_9(TALLOC_CTX *mem_ctx,
2623                                 struct samr_UserInfo9 *r,
2624                                 struct samu *smbpass)
2625 {
2626         r->primary_gid = pdb_get_group_rid(smbpass);
2627
2628         return NT_STATUS_OK;
2629 }
2630
2631 /*************************************************************************
2632  get_user_info_10.
2633  *************************************************************************/
2634
2635 static NTSTATUS get_user_info_10(TALLOC_CTX *mem_ctx,
2636                                  struct samr_UserInfo10 *r,
2637                                  struct samu *pw)
2638 {
2639         r->home_directory.string= talloc_strdup(mem_ctx, pdb_get_homedir(pw));
2640         r->home_drive.string    = talloc_strdup(mem_ctx, pdb_get_dir_drive(pw));
2641
2642         return NT_STATUS_OK;
2643 }
2644
2645 /*************************************************************************
2646  get_user_info_11.
2647  *************************************************************************/
2648
2649 static NTSTATUS get_user_info_11(TALLOC_CTX *mem_ctx,
2650                                  struct samr_UserInfo11 *r,
2651                                  struct samu *pw)
2652 {
2653         r->logon_script.string  = talloc_strdup(mem_ctx, pdb_get_logon_script(pw));
2654
2655         return NT_STATUS_OK;
2656 }
2657
2658 /*************************************************************************
2659  get_user_info_12.
2660  *************************************************************************/
2661
2662 static NTSTATUS get_user_info_12(TALLOC_CTX *mem_ctx,
2663                                  struct samr_UserInfo12 *r,
2664                                  struct samu *pw)
2665 {
2666         r->profile_path.string  = talloc_strdup(mem_ctx, pdb_get_profile_path(pw));
2667
2668         return NT_STATUS_OK;
2669 }
2670
2671 /*************************************************************************
2672  get_user_info_13.
2673  *************************************************************************/
2674
2675 static NTSTATUS get_user_info_13(TALLOC_CTX *mem_ctx,
2676                                  struct samr_UserInfo13 *r,
2677                                  struct samu *pw)
2678 {
2679         r->description.string   = talloc_strdup(mem_ctx, pdb_get_acct_desc(pw));
2680
2681         return NT_STATUS_OK;
2682 }
2683
2684 /*************************************************************************
2685  get_user_info_14.
2686  *************************************************************************/
2687
2688 static NTSTATUS get_user_info_14(TALLOC_CTX *mem_ctx,
2689                                  struct samr_UserInfo14 *r,
2690                                  struct samu *pw)
2691 {
2692         r->workstations.string  = talloc_strdup(mem_ctx, pdb_get_workstations(pw));
2693
2694         return NT_STATUS_OK;
2695 }
2696
2697 /*************************************************************************
2698  get_user_info_16. Safe. Only gives out acb bits.
2699  *************************************************************************/
2700
2701 static NTSTATUS get_user_info_16(TALLOC_CTX *mem_ctx,
2702                                  struct samr_UserInfo16 *r,
2703                                  struct samu *smbpass)
2704 {
2705         r->acct_flags = pdb_get_acct_ctrl(smbpass);
2706
2707         return NT_STATUS_OK;
2708 }
2709
2710 /*************************************************************************
2711  get_user_info_17.
2712  *************************************************************************/
2713
2714 static NTSTATUS get_user_info_17(TALLOC_CTX *mem_ctx,
2715                                  struct samr_UserInfo17 *r,
2716                                  struct samu *pw)
2717 {
2718         unix_to_nt_time(&r->acct_expiry, pdb_get_kickoff_time(pw));
2719
2720         return NT_STATUS_OK;
2721 }
2722
2723 /*************************************************************************
2724  get_user_info_18. OK - this is the killer as it gives out password info.
2725  Ensure that this is only allowed on an encrypted connection with a root
2726  user. JRA.
2727  *************************************************************************/
2728
2729 static NTSTATUS get_user_info_18(pipes_struct *p,
2730                                  TALLOC_CTX *mem_ctx,
2731                                  struct samr_UserInfo18 *r,
2732                                  DOM_SID *user_sid)
2733 {
2734         struct samu *smbpass=NULL;
2735         bool ret;
2736
2737         ZERO_STRUCTP(r);
2738
2739         if (p->auth.auth_type != PIPE_AUTH_TYPE_NTLMSSP || p->auth.auth_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
2740                 return NT_STATUS_ACCESS_DENIED;
2741         }
2742
2743         if (p->auth.auth_level != PIPE_AUTH_LEVEL_PRIVACY) {
2744                 return NT_STATUS_ACCESS_DENIED;
2745         }
2746
2747         /*
2748          * Do *NOT* do become_root()/unbecome_root() here ! JRA.
2749          */
2750
2751         if ( !(smbpass = samu_new( mem_ctx )) ) {
2752                 return NT_STATUS_NO_MEMORY;
2753         }
2754
2755         ret = pdb_getsampwsid(smbpass, user_sid);
2756
2757         if (ret == False) {
2758                 DEBUG(4, ("User %s not found\n", sid_string_dbg(user_sid)));
2759                 TALLOC_FREE(smbpass);
2760                 return (geteuid() == sec_initial_uid()) ? NT_STATUS_NO_SUCH_USER : NT_STATUS_ACCESS_DENIED;
2761         }
2762
2763         DEBUG(3,("User:[%s] 0x%x\n", pdb_get_username(smbpass), pdb_get_acct_ctrl(smbpass) ));
2764
2765         if ( pdb_get_acct_ctrl(smbpass) & ACB_DISABLED) {
2766                 TALLOC_FREE(smbpass);
2767                 return NT_STATUS_ACCOUNT_DISABLED;
2768         }
2769
2770         r->lm_pwd_active = true;
2771         r->nt_pwd_active = true;
2772         memcpy(r->lm_pwd.hash, pdb_get_lanman_passwd(smbpass), 16);
2773         memcpy(r->nt_pwd.hash, pdb_get_nt_passwd(smbpass), 16);
2774         r->password_expired = 0; /* FIXME */
2775
2776         TALLOC_FREE(smbpass);
2777
2778         return NT_STATUS_OK;
2779 }
2780
2781 /*************************************************************************
2782  get_user_info_20
2783  *************************************************************************/
2784
2785 static NTSTATUS get_user_info_20(TALLOC_CTX *mem_ctx,
2786                                  struct samr_UserInfo20 *r,
2787                                  struct samu *sampass)
2788 {
2789         const char *munged_dial = NULL;
2790         DATA_BLOB blob;
2791         NTSTATUS status;
2792         struct lsa_BinaryString *parameters = NULL;
2793
2794         ZERO_STRUCTP(r);
2795
2796         munged_dial = pdb_get_munged_dial(sampass);
2797
2798         DEBUG(3,("User:[%s] has [%s] (length: %d)\n", pdb_get_username(sampass),
2799                 munged_dial, (int)strlen(munged_dial)));
2800
2801         if (munged_dial) {
2802                 blob = base64_decode_data_blob(munged_dial);
2803         } else {
2804                 blob = data_blob_string_const_null("");
2805         }
2806
2807         status = init_samr_parameters_string(mem_ctx, &blob, &parameters);
2808         data_blob_free(&blob);
2809         if (!NT_STATUS_IS_OK(status)) {
2810                 return status;
2811         }
2812
2813         r->parameters = *parameters;
2814
2815         return NT_STATUS_OK;
2816 }
2817
2818
2819 /*************************************************************************
2820  get_user_info_21
2821  *************************************************************************/
2822
2823 static NTSTATUS get_user_info_21(TALLOC_CTX *mem_ctx,
2824                                  struct samr_UserInfo21 *r,
2825                                  struct samu *pw,
2826                                  DOM_SID *domain_sid,
2827                                  uint32_t acc_granted)
2828 {
2829         NTSTATUS status;
2830         const DOM_SID *sid_user, *sid_group;
2831         uint32_t rid, primary_gid;
2832         NTTIME force_password_change;
2833         time_t must_change_time;
2834         struct lsa_BinaryString *parameters = NULL;
2835         const char *munged_dial = NULL;
2836         DATA_BLOB blob;
2837
2838         ZERO_STRUCTP(r);
2839
2840         sid_user = pdb_get_user_sid(pw);
2841
2842         if (!sid_peek_check_rid(domain_sid, sid_user, &rid)) {
2843                 DEBUG(0, ("get_user_info_21: User %s has SID %s, \nwhich conflicts with "
2844                           "the domain sid %s.  Failing operation.\n",
2845                           pdb_get_username(pw), sid_string_dbg(sid_user),
2846                           sid_string_dbg(domain_sid)));
2847                 return NT_STATUS_UNSUCCESSFUL;
2848         }
2849
2850         become_root();
2851         sid_group = pdb_get_group_sid(pw);
2852         unbecome_root();
2853
2854         if (!sid_peek_check_rid(domain_sid, sid_group, &primary_gid)) {
2855                 DEBUG(0, ("get_user_info_21: User %s has Primary Group SID %s, \n"
2856                           "which conflicts with the domain sid %s.  Failing operation.\n",
2857                           pdb_get_username(pw), sid_string_dbg(sid_group),
2858                           sid_string_dbg(domain_sid)));
2859                 return NT_STATUS_UNSUCCESSFUL;
2860         }
2861
2862         unix_to_nt_time(&r->last_logon, pdb_get_logon_time(pw));
2863         unix_to_nt_time(&r->last_logoff, pdb_get_logoff_time(pw));
2864         unix_to_nt_time(&r->acct_expiry, pdb_get_kickoff_time(pw));
2865         unix_to_nt_time(&r->last_password_change, pdb_get_pass_last_set_time(pw));
2866         unix_to_nt_time(&r->allow_password_change, pdb_get_pass_can_change_time(pw));
2867
2868         must_change_time = pdb_get_pass_must_change_time(pw);
2869         if (must_change_time == get_time_t_max()) {
2870                 unix_to_nt_time_abs(&force_password_change, must_change_time);
2871         } else {
2872                 unix_to_nt_time(&force_password_change, must_change_time);
2873         }
2874
2875         munged_dial = pdb_get_munged_dial(pw);
2876         if (munged_dial) {
2877                 blob = base64_decode_data_blob(munged_dial);
2878         } else {
2879                 blob = data_blob_string_const_null("");
2880         }
2881
2882         status = init_samr_parameters_string(mem_ctx, &blob, &parameters);
2883         data_blob_free(&blob);
2884         if (!NT_STATUS_IS_OK(status)) {
2885                 return status;
2886         }
2887
2888         r->force_password_change        = force_password_change;
2889
2890         r->account_name.string          = talloc_strdup(mem_ctx, pdb_get_username(pw));
2891         r->full_name.string             = talloc_strdup(mem_ctx, pdb_get_fullname(pw));
2892         r->home_directory.string        = talloc_strdup(mem_ctx, pdb_get_homedir(pw));
2893         r->home_drive.string            = talloc_strdup(mem_ctx, pdb_get_dir_drive(pw));
2894         r->logon_script.string          = talloc_strdup(mem_ctx, pdb_get_logon_script(pw));
2895         r->profile_path.string          = talloc_strdup(mem_ctx, pdb_get_profile_path(pw));
2896         r->description.string           = talloc_strdup(mem_ctx, pdb_get_acct_desc(pw));
2897         r->workstations.string          = talloc_strdup(mem_ctx, pdb_get_workstations(pw));
2898         r->comment.string               = talloc_strdup(mem_ctx, pdb_get_comment(pw));
2899
2900         r->logon_hours                  = get_logon_hours_from_pdb(mem_ctx, pw);
2901         r->parameters                   = *parameters;
2902         r->rid                          = rid;
2903         r->primary_gid                  = primary_gid;
2904         r->acct_flags                   = pdb_get_acct_ctrl(pw);
2905         r->bad_password_count           = pdb_get_bad_password_count(pw);
2906         r->logon_count                  = pdb_get_logon_count(pw);
2907         r->fields_present               = pdb_build_fields_present(pw);
2908         r->password_expired             = (pdb_get_pass_must_change_time(pw) == 0) ?
2909                                                 PASS_MUST_CHANGE_AT_NEXT_LOGON : 0;
2910         r->country_code                 = 0;
2911         r->code_page                    = 0;
2912         r->lm_password_set              = 0;
2913         r->nt_password_set              = 0;
2914
2915 #if 0
2916
2917         /*
2918           Look at a user on a real NT4 PDC with usrmgr, press
2919           'ok'. Then you will see that fields_present is set to
2920           0x08f827fa. Look at the user immediately after that again,
2921           and you will see that 0x00fffff is returned. This solves
2922           the problem that you get access denied after having looked
2923           at the user.
2924           -- Volker
2925         */
2926
2927 #endif
2928
2929
2930         return NT_STATUS_OK;
2931 }
2932
2933 /*******************************************************************
2934  _samr_QueryUserInfo
2935  ********************************************************************/
2936
2937 NTSTATUS _samr_QueryUserInfo(pipes_struct *p,
2938                              struct samr_QueryUserInfo *r)
2939 {
2940         NTSTATUS status;
2941         union samr_UserInfo *user_info = NULL;
2942         struct samr_user_info *uinfo;
2943         DOM_SID domain_sid;
2944         uint32 rid;
2945         bool ret = false;
2946         struct samu *pwd = NULL;
2947         uint32_t acc_required, acc_granted;
2948
2949         switch (r->in.level) {
2950         case 1: /* UserGeneralInformation */
2951                 /* USER_READ_GENERAL */
2952                 acc_required = SAMR_USER_ACCESS_GET_NAME_ETC;
2953                 break;
2954         case 2: /* UserPreferencesInformation */
2955                 /* USER_READ_PREFERENCES | USER_READ_GENERAL */
2956                 acc_required = SAMR_USER_ACCESS_GET_LOCALE |
2957                                SAMR_USER_ACCESS_GET_NAME_ETC;
2958                 break;
2959         case 3: /* UserLogonInformation */
2960                 /* USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON | USER_READ_ACCOUNT */
2961                 acc_required = SAMR_USER_ACCESS_GET_NAME_ETC |
2962                                SAMR_USER_ACCESS_GET_LOCALE |
2963                                SAMR_USER_ACCESS_GET_LOGONINFO |
2964                                SAMR_USER_ACCESS_GET_ATTRIBUTES;
2965                 break;
2966         case 4: /* UserLogonHoursInformation */
2967                 /* USER_READ_LOGON */
2968                 acc_required = SAMR_USER_ACCESS_GET_LOGONINFO;
2969                 break;
2970         case 5: /* UserAccountInformation */
2971                 /* USER_READ_GENERAL | USER_READ_PREFERENCES | USER_READ_LOGON | USER_READ_ACCOUNT */
2972                 acc_required = SAMR_USER_ACCESS_GET_NAME_ETC |
2973                                SAMR_USER_ACCESS_GET_LOCALE |
2974                                SAMR_USER_ACCESS_GET_LOGONINFO |
2975                                SAMR_USER_ACCESS_GET_ATTRIBUTES;
2976                 break;
2977         case 6: /* UserNameInformation */
2978         case 7: /* UserAccountNameInformation */
2979         case 8: /* UserFullNameInformation */
2980         case 9: /* UserPrimaryGroupInformation */
2981         case 13: /* UserAdminCommentInformation */
2982                 /* USER_READ_GENERAL */
2983                 acc_required = SAMR_USER_ACCESS_GET_NAME_ETC;
2984                 break;
2985         case 10: /* UserHomeInformation */
2986         case 11: /* UserScriptInformation */
2987         case 12: /* UserProfileInformation */
2988         case 14: /* UserWorkStationsInformation */
2989                 /* USER_READ_LOGON */
2990                 acc_required = SAMR_USER_ACCESS_GET_LOGONINFO;
2991                 break;
2992         case 16: /* UserControlInformation */
2993         case 17: /* UserExpiresInformation */
2994         case 20: /* UserParametersInformation */
2995                 /* USER_READ_ACCOUNT */
2996                 acc_required = SAMR_USER_ACCESS_GET_ATTRIBUTES;
2997                 break;
2998         case 21: /* UserAllInformation */
2999                 /* FIXME! - gd */
3000                 acc_required = SAMR_USER_ACCESS_GET_ATTRIBUTES;
3001                 break;
3002         case 18: /* UserInternal1Information */
3003                 /* FIXME! - gd */
3004                 acc_required = SAMR_USER_ACCESS_GET_ATTRIBUTES;
3005                 break;
3006         case 23: /* UserInternal4Information */
3007         case 24: /* UserInternal4InformationNew */
3008         case 25: /* UserInternal4InformationNew */
3009         case 26: /* UserInternal5InformationNew */
3010         default:
3011                 return NT_STATUS_INVALID_INFO_CLASS;
3012                 break;
3013         }
3014
3015         uinfo = policy_handle_find(p, r->in.user_handle,
3016                                    acc_required, &acc_granted,
3017                                    struct samr_user_info, &status);
3018         if (!NT_STATUS_IS_OK(status)) {
3019                 return status;
3020         }
3021
3022         domain_sid = uinfo->sid;
3023
3024         sid_split_rid(&domain_sid, &rid);
3025
3026         if (!sid_check_is_in_our_domain(&uinfo->sid))
3027                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
3028
3029         DEBUG(5,("_samr_QueryUserInfo: sid:%s\n",
3030                  sid_string_dbg(&uinfo->sid)));
3031
3032         user_info = TALLOC_ZERO_P(p->mem_ctx, union samr_UserInfo);
3033         if (!user_info) {
3034                 return NT_STATUS_NO_MEMORY;
3035         }
3036
3037         DEBUG(5,("_samr_QueryUserInfo: user info level: %d\n", r->in.level));
3038
3039         if (!(pwd = samu_new(p->mem_ctx))) {
3040                 return NT_STATUS_NO_MEMORY;
3041         }
3042
3043         become_root();
3044         ret = pdb_getsampwsid(pwd, &uinfo->sid);
3045         unbecome_root();
3046
3047         if (ret == false) {
3048                 DEBUG(4,("User %s not found\n", sid_string_dbg(&uinfo->sid)));
3049                 TALLOC_FREE(pwd);
3050                 return NT_STATUS_NO_SUCH_USER;
3051         }
3052
3053         DEBUG(3,("User:[%s]\n", pdb_get_username(pwd)));
3054
3055         samr_clear_sam_passwd(pwd);
3056
3057         switch (r->in.level) {
3058         case 1:
3059                 status = get_user_info_1(p->mem_ctx, &user_info->info1, pwd, &domain_sid);
3060                 break;
3061         case 2:
3062                 status = get_user_info_2(p->mem_ctx, &user_info->info2, pwd);
3063                 break;
3064         case 3:
3065                 status = get_user_info_3(p->mem_ctx, &user_info->info3, pwd, &domain_sid);
3066                 break;
3067         case 4:
3068                 status = get_user_info_4(p->mem_ctx, &user_info->info4, pwd);
3069                 break;
3070         case 5:
3071                 status = get_user_info_5(p->mem_ctx, &user_info->info5, pwd, &domain_sid);
3072                 break;
3073         case 6:
3074                 status = get_user_info_6(p->mem_ctx, &user_info->info6, pwd);
3075                 break;
3076         case 7:
3077                 status = get_user_info_7(p->mem_ctx, &user_info->info7, pwd);
3078                 break;
3079         case 8:
3080                 status = get_user_info_8(p->mem_ctx, &user_info->info8, pwd);
3081                 break;
3082         case 9:
3083                 status = get_user_info_9(p->mem_ctx, &user_info->info9, pwd);
3084                 break;
3085         case 10:
3086                 status = get_user_info_10(p->mem_ctx, &user_info->info10, pwd);
3087                 break;
3088         case 11:
3089                 status = get_user_info_11(p->mem_ctx, &user_info->info11, pwd);
3090                 break;
3091         case 12:
3092                 status = get_user_info_12(p->mem_ctx, &user_info->info12, pwd);
3093                 break;
3094         case 13:
3095                 status = get_user_info_13(p->mem_ctx, &user_info->info13, pwd);
3096                 break;
3097         case 14:
3098                 status = get_user_info_14(p->mem_ctx, &user_info->info14, pwd);
3099                 break;
3100         case 16:
3101                 status = get_user_info_16(p->mem_ctx, &user_info->info16, pwd);
3102                 break;
3103         case 17:
3104                 status = get_user_info_17(p->mem_ctx, &user_info->info17, pwd);
3105                 break;
3106         case 18:
3107                 /* level 18 is special */
3108                 status = get_user_info_18(p, p->mem_ctx, &user_info->info18,
3109                                           &uinfo->sid);
3110                 break;
3111         case 20:
3112                 status = get_user_info_20(p->mem_ctx, &user_info->info20, pwd);
3113                 break;
3114         case 21:
3115                 status = get_user_info_21(p->mem_ctx, &user_info->info21, pwd, &domain_sid, acc_granted);
3116                 break;
3117         default:
3118                 status = NT_STATUS_INVALID_INFO_CLASS;
3119                 break;
3120         }
3121
3122         if (!NT_STATUS_IS_OK(status)) {
3123                 goto done;
3124         }
3125
3126         *r->out.info = user_info;
3127
3128  done:
3129         TALLOC_FREE(pwd);
3130
3131         DEBUG(5,("_samr_QueryUserInfo: %d\n", __LINE__));
3132
3133         return status;
3134 }
3135
3136 /****************************************************************
3137 ****************************************************************/
3138
3139 NTSTATUS _samr_QueryUserInfo2(pipes_struct *p,
3140                               struct samr_QueryUserInfo2 *r)
3141 {
3142         struct samr_QueryUserInfo u;
3143
3144         u.in.user_handle        = r->in.user_handle;
3145         u.in.level              = r->in.level;
3146         u.out.info              = r->out.info;
3147
3148         return _samr_QueryUserInfo(p, &u);
3149 }
3150
3151 /*******************************************************************
3152  _samr_GetGroupsForUser
3153  ********************************************************************/
3154
3155 NTSTATUS _samr_GetGroupsForUser(pipes_struct *p,
3156                                 struct samr_GetGroupsForUser *r)
3157 {
3158         struct samr_user_info *uinfo;
3159         struct samu *sam_pass=NULL;
3160         DOM_SID *sids;
3161         struct samr_RidWithAttribute dom_gid;
3162         struct samr_RidWithAttribute *gids = NULL;
3163         uint32 primary_group_rid;
3164         size_t num_groups = 0;
3165         gid_t *unix_gids;
3166         size_t i, num_gids;
3167         bool ret;
3168         NTSTATUS result;
3169         bool success = False;
3170
3171         struct samr_RidWithAttributeArray *rids = NULL;
3172
3173         /*
3174          * from the SID in the request:
3175          * we should send back the list of DOMAIN GROUPS
3176          * the user is a member of
3177          *
3178          * and only the DOMAIN GROUPS
3179          * no ALIASES !!! neither aliases of the domain
3180          * nor aliases of the builtin SID
3181          *
3182          * JFM, 12/2/2001
3183          */
3184
3185         DEBUG(5,("_samr_GetGroupsForUser: %d\n", __LINE__));
3186
3187         uinfo = policy_handle_find(p, r->in.user_handle,
3188                                    SAMR_USER_ACCESS_GET_GROUPS, NULL,
3189                                    struct samr_user_info, &result);
3190         if (!NT_STATUS_IS_OK(result)) {
3191                 return result;
3192         }
3193
3194         rids = TALLOC_ZERO_P(p->mem_ctx, struct samr_RidWithAttributeArray);
3195         if (!rids) {
3196                 return NT_STATUS_NO_MEMORY;
3197         }
3198
3199         if (!sid_check_is_in_our_domain(&uinfo->sid))
3200                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
3201
3202         if ( !(sam_pass = samu_new( p->mem_ctx )) ) {
3203                 return NT_STATUS_NO_MEMORY;
3204         }
3205
3206         become_root();
3207         ret = pdb_getsampwsid(sam_pass, &uinfo->sid);
3208         unbecome_root();
3209
3210         if (!ret) {
3211                 DEBUG(10, ("pdb_getsampwsid failed for %s\n",
3212                            sid_string_dbg(&uinfo->sid)));
3213                 return NT_STATUS_NO_SUCH_USER;
3214         }
3215
3216         sids = NULL;
3217
3218         /* make both calls inside the root block */
3219  &nbs