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