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