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