make_uni_hdr() reverted accidentally with a -1 on username length
[samba.git] / source3 / rpc_server / srv_samr.c
1
2 /* 
3  *  Unix SMB/Netbios implementation.
4  *  Version 1.9.
5  *  RPC Pipe client / server routines
6  *  Copyright (C) Andrew Tridgell              1992-1997,
7  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
8  *  Copyright (C) Paul Ashton                       1997.
9  *  
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *  
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *  
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25
26 #include "includes.h"
27 #include "nterr.h"
28
29 extern int DEBUGLEVEL;
30
31 extern BOOL sam_logon_in_ssb;
32 extern pstring samlogon_user;
33 extern fstring global_sam_name;
34 extern pstring global_myname;
35 extern DOM_SID global_sam_sid;
36 extern DOM_SID global_sid_S_1_1;
37 extern DOM_SID global_sid_S_1_5_20;
38
39 extern rid_name domain_group_rids[];
40 extern rid_name domain_alias_rids[];
41 extern rid_name builtin_alias_rids[];
42
43 /*******************************************************************
44   This next function should be replaced with something that
45   dynamically returns the correct user info..... JRA.
46  ********************************************************************/
47
48 static BOOL get_sampwd_entries(SAM_USER_INFO_21 *pw_buf,
49                                 int start_idx,
50                                 int *total_entries, int *num_entries,
51                                 int max_num_entries,
52                                 uint16 acb_mask)
53 {
54         void *vp = NULL;
55         struct sam_passwd *pwd = NULL;
56
57         (*num_entries) = 0;
58         (*total_entries) = 0;
59
60         if (pw_buf == NULL) return False;
61
62         vp = startsmbpwent(False);
63         if (!vp)
64         {
65                 DEBUG(0, ("get_sampwd_entries: Unable to open SMB password database.\n"));
66                 return False;
67         }
68
69         while (((pwd = getsam21pwent(vp)) != NULL) && (*num_entries) < max_num_entries)
70         {
71                 int user_name_len;
72
73                 if (start_idx > 0)
74                 {
75                         /* skip the requested number of entries.
76                            not very efficient, but hey...
77                          */
78                         start_idx--;
79                         continue;
80                 }
81
82                 user_name_len = strlen(pwd->smb_name);
83                 make_unistr2(&(pw_buf[(*num_entries)].uni_user_name), pwd->smb_name, user_name_len);
84                 make_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len, 
85                                user_name_len, 1);
86                 pw_buf[(*num_entries)].user_rid = pwd->user_rid;
87                 bzero( pw_buf[(*num_entries)].nt_pwd , 16);
88
89                 /* Now check if the NT compatible password is available. */
90                 if (pwd->smb_nt_passwd != NULL)
91                 {
92                         memcpy( pw_buf[(*num_entries)].nt_pwd , pwd->smb_nt_passwd, 16);
93                 }
94
95                 pw_buf[(*num_entries)].acb_info = (uint16)pwd->acct_ctrl;
96
97                 DEBUG(5, ("entry idx: %d user %s, rid 0x%x, acb %x",
98                           (*num_entries), pwd->smb_name,
99                           pwd->user_rid, pwd->acct_ctrl));
100
101                 if (acb_mask == 0 || IS_BITS_SET_SOME(pwd->acct_ctrl, acb_mask))
102                 {
103                         DEBUG(5,(" acb_mask %x accepts\n", acb_mask));
104                         (*num_entries)++;
105                 }
106                 else
107                 {
108                         DEBUG(5,(" acb_mask %x rejects\n", acb_mask));
109                 }
110
111                 (*total_entries)++;
112         }
113
114         endsmbpwent(vp);
115
116         return (*num_entries) > 0;
117 }
118
119 /*******************************************************************
120  samr_reply_unknown_1
121  ********************************************************************/
122 static void samr_reply_close_hnd(SAMR_Q_CLOSE_HND *q_u,
123                                 prs_struct *rdata)
124 {
125         SAMR_R_CLOSE_HND r_u;
126
127         /* set up the SAMR unknown_1 response */
128         bzero(r_u.pol.data, POL_HND_SIZE);
129
130         /* close the policy handle */
131         if (close_lsa_policy_hnd(&(q_u->pol)))
132         {
133                 r_u.status = 0;
134         }
135         else
136         {
137                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_INVALID;
138         }
139
140         DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
141
142         /* store the response in the SMB stream */
143         samr_io_r_close_hnd("", &r_u, rdata, 0);
144
145         DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
146
147 }
148
149 /*******************************************************************
150  api_samr_close_hnd
151  ********************************************************************/
152 static void api_samr_close_hnd( uint16 vuid, prs_struct *data, prs_struct *rdata)
153 {
154         SAMR_Q_CLOSE_HND q_u;
155
156         /* grab the samr unknown 1 */
157         samr_io_q_close_hnd("", &q_u, data, 0);
158
159         /* construct reply.  always indicate success */
160         samr_reply_close_hnd(&q_u, rdata);
161 }
162
163
164 /*******************************************************************
165  samr_reply_open_domain
166  ********************************************************************/
167 static void samr_reply_open_domain(SAMR_Q_OPEN_DOMAIN *q_u,
168                                 prs_struct *rdata)
169 {
170         SAMR_R_OPEN_DOMAIN r_u;
171         BOOL pol_open = False;
172
173         r_u.status = 0x0;
174
175         /* find the connection policy handle. */
176         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->connect_pol)) == -1))
177         {
178                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
179         }
180
181         /* get a (unique) handle.  open a policy on it. */
182         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.domain_pol))))
183         {
184                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
185         }
186
187         /* associate the domain SID with the (unique) handle. */
188         if (r_u.status == 0x0 && !set_lsa_policy_samr_sid(&(r_u.domain_pol), &(q_u->dom_sid.sid)))
189         {
190                 /* oh, whoops.  don't know what error message to return, here */
191                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
192         }
193
194         if (r_u.status != 0 && pol_open)
195         {
196                 close_lsa_policy_hnd(&(r_u.domain_pol));
197         }
198
199         DEBUG(5,("samr_open_domain: %d\n", __LINE__));
200
201         /* store the response in the SMB stream */
202         samr_io_r_open_domain("", &r_u, rdata, 0);
203
204         DEBUG(5,("samr_open_domain: %d\n", __LINE__));
205
206 }
207
208 /*******************************************************************
209  api_samr_open_domain
210  ********************************************************************/
211 static void api_samr_open_domain( uint16 vuid, prs_struct *data, prs_struct *rdata)
212 {
213         SAMR_Q_OPEN_DOMAIN q_u;
214
215         /* grab the samr open */
216         samr_io_q_open_domain("", &q_u, data, 0);
217
218         /* construct reply.  always indicate success */
219         samr_reply_open_domain(&q_u, rdata);
220 }
221
222
223 /*******************************************************************
224  samr_reply_unknown_2c
225  ********************************************************************/
226 static void samr_reply_unknown_2c(SAMR_Q_UNKNOWN_2C *q_u,
227                                 prs_struct *rdata)
228 {
229         SAMR_R_UNKNOWN_2C r_u;
230         uint32 status = 0x0;
231
232         /* find the policy handle.  open a policy on it. */
233         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->user_pol)) == -1))
234         {
235                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
236         }
237
238         /* find the user's rid */
239         if ((status == 0x0) && (get_lsa_policy_samr_rid(&(q_u->user_pol)) == 0xffffffff))
240         {
241                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
242         }
243
244         make_samr_r_unknown_2c(&r_u, status);
245
246         DEBUG(5,("samr_unknown_2c: %d\n", __LINE__));
247
248         /* store the response in the SMB stream */
249         samr_io_r_unknown_2c("", &r_u, rdata, 0);
250
251         DEBUG(5,("samr_unknown_2c: %d\n", __LINE__));
252
253 }
254
255 /*******************************************************************
256  api_samr_unknown_2c
257  ********************************************************************/
258 static void api_samr_unknown_2c( uint16 vuid, prs_struct *data, prs_struct *rdata)
259 {
260         SAMR_Q_UNKNOWN_2C q_u;
261
262         /* grab the samr open */
263         samr_io_q_unknown_2c("", &q_u, data, 0);
264
265         /* construct reply.  always indicate success */
266         samr_reply_unknown_2c(&q_u, rdata);
267 }
268
269
270 /*******************************************************************
271  samr_reply_unknown_3
272  ********************************************************************/
273 static void samr_reply_unknown_3(SAMR_Q_UNKNOWN_3 *q_u,
274                                 prs_struct *rdata)
275 {
276         SAMR_R_UNKNOWN_3 r_u;
277         DOM_SID3 sid[MAX_SAM_SIDS];
278         uint32 rid;
279         uint32 status;
280
281         status = 0x0;
282
283         /* find the policy handle.  open a policy on it. */
284         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->user_pol)) == -1))
285         {
286                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
287         }
288
289         /* find the user's rid */
290         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->user_pol))) == 0xffffffff)
291         {
292                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
293         }
294
295         if (status == 0x0)
296         {
297                 DOM_SID usr_sid;
298
299                 usr_sid = global_sam_sid;
300
301                 SMB_ASSERT_ARRAY(usr_sid.sub_auths, usr_sid.num_auths+1);
302
303                 /*
304                  * Add the user RID.
305                  */
306                 sid_append_rid(&usr_sid, rid);
307                 
308                 /* maybe need another 1 or 2 (S-1-5-0x20-0x220 and S-1-5-20-0x224) */
309                 /* these two are DOMAIN_ADMIN and DOMAIN_ACCT_OP group RIDs */
310                 make_dom_sid3(&(sid[0]), 0x035b, 0x0002, &global_sid_S_1_1);
311                 make_dom_sid3(&(sid[1]), 0x0044, 0x0002, &usr_sid);
312         }
313
314         make_samr_r_unknown_3(&r_u,
315                                 0x0001, 0x8004,
316                                 0x00000014, 0x0002, 0x0070,
317                                 2, sid, status);
318
319         DEBUG(5,("samr_unknown_3: %d\n", __LINE__));
320
321         /* store the response in the SMB stream */
322         samr_io_r_unknown_3("", &r_u, rdata, 0);
323
324         DEBUG(5,("samr_unknown_3: %d\n", __LINE__));
325
326 }
327
328 /*******************************************************************
329  api_samr_unknown_3
330  ********************************************************************/
331 static void api_samr_unknown_3( uint16 vuid, prs_struct *data, prs_struct *rdata)
332 {
333         SAMR_Q_UNKNOWN_3 q_u;
334
335         /* grab the samr open */
336         samr_io_q_unknown_3("", &q_u, data, 0);
337
338         /* construct reply.  always indicate success */
339         samr_reply_unknown_3(&q_u, rdata);
340 }
341
342
343 /*******************************************************************
344  samr_reply_enum_dom_users
345  ********************************************************************/
346 static void samr_reply_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_u,
347                                 prs_struct *rdata)
348 {
349         SAMR_R_ENUM_DOM_USERS r_e;
350         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
351         int num_entries;
352         int total_entries;
353
354         r_e.status = 0x0;
355         r_e.total_num_entries = 0;
356
357         /* find the policy handle.  open a policy on it. */
358         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
359         {
360                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
361         }
362
363         DEBUG(5,("samr_reply_enum_dom_users: %d\n", __LINE__));
364
365         become_root(True);
366         get_sampwd_entries(pass, 0, &total_entries, &num_entries, MAX_SAM_ENTRIES, q_u->acb_mask);
367         unbecome_root(True);
368
369         make_samr_r_enum_dom_users(&r_e, total_entries,
370                                    q_u->unknown_0, num_entries,
371                                    pass, r_e.status);
372
373         /* store the response in the SMB stream */
374         samr_io_r_enum_dom_users("", &r_e, rdata, 0);
375
376         DEBUG(5,("samr_enum_dom_users: %d\n", __LINE__));
377
378 }
379
380 /*******************************************************************
381  api_samr_enum_dom_users
382  ********************************************************************/
383 static void api_samr_enum_dom_users( uint16 vuid, prs_struct *data, prs_struct *rdata)
384 {
385         SAMR_Q_ENUM_DOM_USERS q_e;
386
387         /* grab the samr open */
388         samr_io_q_enum_dom_users("", &q_e, data, 0);
389
390         /* construct reply. */
391         samr_reply_enum_dom_users(&q_e, rdata);
392 }
393
394
395 /*******************************************************************
396  samr_reply_enum_dom_groups
397  ********************************************************************/
398 static void samr_reply_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_u,
399                                 prs_struct *rdata)
400 {
401         SAMR_R_ENUM_DOM_GROUPS r_e;
402         DOMAIN_GRP *grps = NULL;
403         int num_entries = 0;
404         BOOL got_grps;
405         DOM_SID sid;
406         fstring sid_str;
407
408         r_e.status = 0x0;
409         r_e.num_entries = 0;
410
411         /* find the policy handle.  open a policy on it. */
412         if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &sid))
413         {
414                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
415         }
416
417         sid_to_string(sid_str, &sid);
418
419         DEBUG(5,("samr_reply_enum_dom_groups: sid %s\n", sid_str));
420
421         /* well-known groups */
422         if (sid_equal(&sid, &global_sid_S_1_5_20))
423         {
424                 char *name;
425                 got_grps = True;
426
427                 while (num_entries < MAX_SAM_ENTRIES && ((name = domain_group_rids[num_entries].name) != NULL))
428                 {
429                         DOMAIN_GRP tmp_grp;
430
431                         fstrcpy(tmp_grp.name   , name);
432                         fstrcpy(tmp_grp.comment, "");
433                         tmp_grp.rid = domain_group_rids[num_entries].rid;
434                         tmp_grp.attr = 0x7;
435
436                         if (!add_domain_group(&grps, &num_entries, &tmp_grp))
437                         {
438                                 r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
439                                 break;
440                         }
441                 }
442         }
443         else if (sid_equal(&sid, &global_sam_sid))
444         {
445                 BOOL ret;
446                 char *name;
447                 got_grps = True;
448
449                 while (num_entries < MAX_SAM_ENTRIES && ((name = domain_group_rids[num_entries].name) != NULL))
450                 {
451                         DOMAIN_GRP tmp_grp;
452
453                         fstrcpy(tmp_grp.name   , name);
454                         fstrcpy(tmp_grp.comment, "");
455                         tmp_grp.rid = domain_group_rids[num_entries].rid;
456                         tmp_grp.attr = 0x7;
457
458                         if (!add_domain_group(&grps, &num_entries, &tmp_grp))
459                         {
460                                 r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
461                                 break;
462                         }
463                 }
464
465                 become_root(True);
466                 ret = enumdomgroups(&grps, &num_entries);
467                 unbecome_root(True);
468                 if (!ret)
469                 {
470                         r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
471                 }
472         }
473
474         if (r_e.status == 0 && got_grps)
475         {
476                 make_samr_r_enum_dom_groups(&r_e, q_u->start_idx, num_entries, grps, r_e.status);
477         }
478
479         /* store the response in the SMB stream */
480         samr_io_r_enum_dom_groups("", &r_e, rdata, 0);
481
482         if (grps != NULL)
483         {
484                 free(grps);
485         }
486
487         DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__));
488 }
489
490 /*******************************************************************
491  api_samr_enum_dom_groups
492  ********************************************************************/
493 static void api_samr_enum_dom_groups( uint16 vuid, prs_struct *data, prs_struct *rdata)
494 {
495         SAMR_Q_ENUM_DOM_GROUPS q_e;
496
497         /* grab the samr open */
498         samr_io_q_enum_dom_groups("", &q_e, data, 0);
499
500         /* construct reply. */
501         samr_reply_enum_dom_groups(&q_e, rdata);
502 }
503
504
505 /*******************************************************************
506  samr_reply_enum_dom_aliases
507  ********************************************************************/
508 static void samr_reply_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_u,
509                                 prs_struct *rdata)
510 {
511         SAMR_R_ENUM_DOM_ALIASES r_e;
512         LOCAL_GRP *alss = NULL;
513         int num_entries = 0;
514         DOM_SID sid;
515         fstring sid_str;
516
517         r_e.status = 0x0;
518         r_e.num_entries = 0;
519
520         /* find the policy handle.  open a policy on it. */
521         if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &sid))
522         {
523                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
524         }
525
526         sid_to_string(sid_str, &sid);
527
528         DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str));
529
530         /* well-known aliases */
531         if (sid_equal(&sid, &global_sid_S_1_5_20))
532         {
533                 char *name;
534
535                 while ((name = builtin_alias_rids[num_entries].name) != NULL)
536                 {
537                         LOCAL_GRP tmp_als;
538
539                         fstrcpy(tmp_als.name   , name);
540                         fstrcpy(tmp_als.comment, "");
541                         tmp_als.rid = builtin_alias_rids[num_entries].rid;
542
543                         if (!add_domain_alias(&alss, &num_entries, &tmp_als))
544                         {
545                                 r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
546                                 break;
547                         }
548                 }
549         }
550         else if (sid_equal(&sid, &global_sam_sid))
551         {
552                 BOOL ret;
553                 /* local aliases */
554                 num_entries = 0;
555
556                 become_root(True);
557                 ret = enumdomaliases(&alss, &num_entries);
558                 unbecome_root(True);
559                 if (!ret)
560                 {
561                         r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
562                 }
563         }
564                 
565         if (r_e.status == 0x0)
566         {
567                 make_samr_r_enum_dom_aliases(&r_e, num_entries, alss, r_e.status);
568         }
569
570         /* store the response in the SMB stream */
571         samr_io_r_enum_dom_aliases("", &r_e, rdata, 0);
572
573         if (alss != NULL)
574         {
575                 free(alss);
576         }
577
578         DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__));
579
580 }
581
582 /*******************************************************************
583  api_samr_enum_dom_aliases
584  ********************************************************************/
585 static void api_samr_enum_dom_aliases( uint16 vuid, prs_struct *data, prs_struct *rdata)
586 {
587         SAMR_Q_ENUM_DOM_ALIASES q_e;
588
589         /* grab the samr open */
590         samr_io_q_enum_dom_aliases("", &q_e, data, 0);
591
592         /* construct reply. */
593         samr_reply_enum_dom_aliases(&q_e, rdata);
594 }
595
596
597 /*******************************************************************
598  samr_reply_query_dispinfo
599  ********************************************************************/
600 static void samr_reply_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_u,
601                                 prs_struct *rdata)
602 {
603         SAMR_R_QUERY_DISPINFO r_e;
604         SAM_INFO_CTR ctr;
605         SAM_INFO_1 info1;
606         SAM_INFO_2 info2;
607         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
608         int num_entries = 0;
609         int total_entries = 0;
610         BOOL got_pwds;
611         uint16 switch_level = 0x0;
612
613         ZERO_STRUCT(r_e);
614
615         r_e.status = 0x0;
616
617         DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__));
618
619         /* find the policy handle.  open a policy on it. */
620         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
621         {
622                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
623                 DEBUG(5,("samr_reply_query_dispinfo: invalid handle\n"));
624         }
625
626         if (r_e.status == 0x0)
627         {
628                 become_root(True);
629                 got_pwds = get_sampwd_entries(pass, q_u->start_idx, &total_entries, &num_entries, MAX_SAM_ENTRIES, 0);
630                 unbecome_root(True);
631
632                 switch (q_u->switch_level)
633                 {
634                         case 0x1:
635                         {
636                         
637                                 /* query disp info is for users */
638                                 switch_level = 0x1;
639                                 make_sam_info_1(&info1, ACB_NORMAL,
640                                         q_u->start_idx, num_entries, pass);
641
642                                 ctr.sam.info1 = &info1;
643
644                                 break;
645                         }
646                         case 0x2:
647                         {
648                                 /* query disp info is for servers */
649                                 switch_level = 0x2;
650                                 make_sam_info_2(&info2, ACB_WSTRUST,
651                                         q_u->start_idx, num_entries, pass);
652
653                                 ctr.sam.info2 = &info2;
654
655                                 break;
656                         }
657                 }
658         }
659
660         if (r_e.status == 0 && got_pwds)
661         {
662                 make_samr_r_query_dispinfo(&r_e, switch_level, &ctr, r_e.status);
663         }
664
665         /* store the response in the SMB stream */
666         samr_io_r_query_dispinfo("", &r_e, rdata, 0);
667
668         DEBUG(5,("samr_query_dispinfo: %d\n", __LINE__));
669
670 }
671
672 /*******************************************************************
673  api_samr_query_dispinfo
674  ********************************************************************/
675 static void api_samr_query_dispinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
676 {
677         SAMR_Q_QUERY_DISPINFO q_e;
678
679         /* grab the samr open */
680         samr_io_q_query_dispinfo("", &q_e, data, 0);
681
682         /* construct reply. */
683         samr_reply_query_dispinfo(&q_e, rdata);
684 }
685
686
687 /*******************************************************************
688  samr_reply_query_aliasinfo
689  ********************************************************************/
690 static void samr_reply_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_u,
691                                 prs_struct *rdata)
692 {
693         SAMR_R_QUERY_ALIASINFO r_e;
694
695         r_e.status = 0x0;
696         r_e.ptr = 0;
697
698         /* find the policy handle.  open a policy on it. */
699         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
700         {
701                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
702         }
703
704         DEBUG(5,("samr_reply_query_aliasinfo: %d\n", __LINE__));
705
706         if (r_e.status == 0x0)
707         {
708                 if (q_u->switch_level != 3)
709                 {
710                         r_e.status = NT_STATUS_INVALID_INFO_CLASS;
711                 }
712         }
713
714         make_samr_r_query_aliasinfo(&r_e, q_u->switch_level,
715                             "<account description>",
716                                 r_e.status);
717
718         /* store the response in the SMB stream */
719         samr_io_r_query_aliasinfo("", &r_e, rdata, 0);
720
721         DEBUG(5,("samr_query_aliasinfo: %d\n", __LINE__));
722
723 }
724
725 /*******************************************************************
726  api_samr_query_aliasinfo
727  ********************************************************************/
728 static void api_samr_query_aliasinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
729 {
730         SAMR_Q_QUERY_ALIASINFO q_e;
731
732         /* grab the samr open */
733         samr_io_q_query_aliasinfo("", &q_e, data, 0);
734
735         /* construct reply. */
736         samr_reply_query_aliasinfo(&q_e, rdata);
737 }
738
739
740 /*******************************************************************
741  samr_reply_lookup_ids
742  ********************************************************************/
743 static void samr_reply_lookup_ids(SAMR_Q_LOOKUP_IDS *q_u,
744                                 prs_struct *rdata)
745 {
746         uint32 rid[MAX_SAM_ENTRIES];
747         uint32 status     = 0;
748         int num_rids = 0;
749         int i;
750         struct sam_passwd *sam_pass;
751         DOM_SID usr_sid;
752         DOM_SID dom_sid;
753         uint32 user_rid;
754         fstring sam_sid_str;
755         fstring dom_sid_str;
756         fstring usr_sid_str;
757
758         SAMR_R_LOOKUP_IDS r_u;
759
760         DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
761
762         /* find the policy handle.  open a policy on it. */
763         if (status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &dom_sid))
764         {
765                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
766         }
767         else
768         {
769                 sid_to_string(dom_sid_str, &dom_sid       );
770                 sid_to_string(sam_sid_str, &global_sam_sid);
771         }
772
773         if (num_rids > MAX_SAM_ENTRIES)
774         {
775                 num_rids = MAX_SAM_ENTRIES;
776                 DEBUG(5,("samr_lookup_ids: truncating entries to %d\n", num_rids));
777         }
778
779         if (status == 0x0)
780         {
781                 usr_sid = q_u->sid[0].sid;
782                 sid_split_rid(&usr_sid, &user_rid);
783                 sid_to_string(usr_sid_str, &usr_sid);
784
785         }
786
787         if (status == 0x0)
788         {
789                 /* find the user account */
790                 become_root(True);
791                 sam_pass = getsam21pwrid(user_rid);
792                 unbecome_root(True);
793
794                 if (sam_pass == NULL)
795                 {
796                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
797                         num_rids = 0;
798                 }
799         }
800
801         if (status == 0x0)
802         {
803                 if (sid_equal(&dom_sid, &global_sid_S_1_5_20))
804                 {
805                         DEBUG(5,("lookup on S-1-5-20\n"));
806                 }
807                 else if (sid_equal(&dom_sid, &usr_sid))
808                 {
809                         DOMAIN_GRP *mem_grp = NULL;
810                         BOOL ret;
811
812                         DEBUG(5,("lookup on Domain SID\n"));
813
814                         become_root(True);
815                         ret = getusergroupsnam(sam_pass->smb_name, &mem_grp, &num_rids);
816                         unbecome_root(True);
817
818                         num_rids = MIN(num_rids, MAX_SAM_ENTRIES);
819
820                         if (mem_grp != NULL)
821                         {
822                                 for (i = 0; i < num_rids; i++)
823                                 {
824                                         rid[i] = mem_grp[i].rid;
825                                 }
826                                 free(mem_grp);
827                         }
828                 }
829                 else
830                 {
831                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
832                 }
833         }
834
835         make_samr_r_lookup_ids(&r_u, num_rids, rid, status);
836
837         /* store the response in the SMB stream */
838         samr_io_r_lookup_ids("", &r_u, rdata, 0);
839
840         DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
841
842 }
843
844 /*******************************************************************
845  api_samr_lookup_ids
846  ********************************************************************/
847 static void api_samr_lookup_ids( uint16 vuid, prs_struct *data, prs_struct *rdata)
848 {
849         SAMR_Q_LOOKUP_IDS q_u;
850
851         /* grab the samr 0x10 */
852         samr_io_q_lookup_ids("", &q_u, data, 0);
853
854         /* construct reply.  always indicate success */
855         samr_reply_lookup_ids(&q_u, rdata);
856 }
857
858 /*******************************************************************
859  samr_reply_lookup_names
860  ********************************************************************/
861 static void samr_reply_lookup_names(SAMR_Q_LOOKUP_NAMES *q_u,
862                                 prs_struct *rdata)
863 {
864         uint32 rid [MAX_SAM_ENTRIES];
865         uint8  type[MAX_SAM_ENTRIES];
866         uint32 status     = 0;
867         int i;
868         int num_rids = q_u->num_rids1;
869
870         SAMR_R_LOOKUP_NAMES r_u;
871
872         DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
873
874         if (num_rids > MAX_SAM_ENTRIES)
875         {
876                 num_rids = MAX_SAM_ENTRIES;
877                 DEBUG(5,("samr_lookup_names: truncating entries to %d\n", num_rids));
878         }
879
880         SMB_ASSERT_ARRAY(q_u->uni_user_name, num_rids);
881
882         for (i = 0; i < num_rids && status == 0; i++)
883         {
884                 fstring name;
885                 fstrcpy(name, unistrn2(q_u->uni_user_name[i].buffer, q_u->uni_user_name[i].uni_str_len));
886
887                 status = lookup_rid(name, &(rid[i]), &(type[i]));
888         }
889
890         make_samr_r_lookup_names(&r_u, num_rids, rid, type, status);
891
892         /* store the response in the SMB stream */
893         samr_io_r_lookup_names("", &r_u, rdata, 0);
894
895         DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
896
897 }
898
899 /*******************************************************************
900  api_samr_lookup_names
901  ********************************************************************/
902 static void api_samr_lookup_names( uint16 vuid, prs_struct *data, prs_struct *rdata)
903 {
904         SAMR_Q_LOOKUP_NAMES q_u;
905
906         /* grab the samr lookup names */
907         samr_io_q_lookup_names("", &q_u, data, 0);
908
909         /* construct reply.  always indicate success */
910         samr_reply_lookup_names(&q_u, rdata);
911 }
912
913 /*******************************************************************
914  samr_reply_chgpasswd_user
915  ********************************************************************/
916 static void samr_reply_chgpasswd_user(SAMR_Q_CHGPASSWD_USER *q_u,
917                                 prs_struct *rdata)
918 {
919         SAMR_R_CHGPASSWD_USER r_u;
920         uint32 status = 0x0;
921         fstring user_name;
922         fstring wks;
923
924         fstrcpy(user_name, unistrn2(q_u->uni_user_name.buffer, q_u->uni_user_name.uni_str_len));
925         fstrcpy(wks      , unistrn2(q_u->uni_dest_host.buffer, q_u->uni_dest_host.uni_str_len));
926
927         DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks));
928
929         if (!pass_oem_change(user_name,
930                              q_u->lm_newpass.pass, q_u->lm_oldhash.hash,
931                              q_u->nt_newpass.pass, q_u->nt_oldhash.hash))
932         {
933                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
934         }
935
936         make_samr_r_chgpasswd_user(&r_u, status);
937
938         /* store the response in the SMB stream */
939         samr_io_r_chgpasswd_user("", &r_u, rdata, 0);
940
941         DEBUG(5,("samr_chgpasswd_user: %d\n", __LINE__));
942 }
943
944 /*******************************************************************
945  api_samr_chgpasswd_user
946  ********************************************************************/
947 static void api_samr_chgpasswd_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
948 {
949         SAMR_Q_CHGPASSWD_USER q_u;
950
951         /* unknown 38 command */
952         samr_io_q_chgpasswd_user("", &q_u, data, 0);
953
954         /* construct reply. */
955         samr_reply_chgpasswd_user(&q_u, rdata);
956 }
957
958
959 /*******************************************************************
960  samr_reply_unknown_38
961  ********************************************************************/
962 static void samr_reply_unknown_38(SAMR_Q_UNKNOWN_38 *q_u,
963                                 prs_struct *rdata)
964 {
965         SAMR_R_UNKNOWN_38 r_u;
966
967         DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
968
969         make_samr_r_unknown_38(&r_u);
970
971         /* store the response in the SMB stream */
972         samr_io_r_unknown_38("", &r_u, rdata, 0);
973
974         DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
975 }
976
977 /*******************************************************************
978  api_samr_unknown_38
979  ********************************************************************/
980 static void api_samr_unknown_38( uint16 vuid, prs_struct *data, prs_struct *rdata)
981 {
982         SAMR_Q_UNKNOWN_38 q_u;
983
984         /* unknown 38 command */
985         samr_io_q_unknown_38("", &q_u, data, 0);
986
987         /* construct reply.  always indicate success */
988         samr_reply_unknown_38(&q_u, rdata);
989 }
990
991
992 /*******************************************************************
993  samr_reply_unknown_12
994  ********************************************************************/
995 static void samr_reply_unknown_12(SAMR_Q_UNKNOWN_12 *q_u,
996                                 prs_struct *rdata)
997 {
998         fstring group_names[MAX_SAM_ENTRIES];
999         uint32  group_attrs[MAX_SAM_ENTRIES];
1000         uint32 status     = 0;
1001         int num_gids = q_u->num_gids1;
1002
1003         SAMR_R_UNKNOWN_12 r_u;
1004
1005         DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
1006
1007         /* find the policy handle.  open a policy on it. */
1008         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1009         {
1010                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1011         }
1012
1013         if (status == 0x0)
1014         {
1015                 int i;
1016                 if (num_gids > MAX_SAM_ENTRIES)
1017                 {
1018                         num_gids = MAX_SAM_ENTRIES;
1019                         DEBUG(5,("samr_unknown_12: truncating entries to %d\n", num_gids));
1020                 }
1021
1022                 for (i = 0; i < num_gids && status == 0; i++)
1023                 {
1024                         fstrcpy(group_names[i], "dummy group");
1025                         group_attrs[i] = 0x2;
1026                 }
1027         }
1028
1029         make_samr_r_unknown_12(&r_u, num_gids, group_names, group_attrs, status);
1030
1031         /* store the response in the SMB stream */
1032         samr_io_r_unknown_12("", &r_u, rdata, 0);
1033
1034         DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
1035
1036 }
1037
1038 /*******************************************************************
1039  api_samr_unknown_12
1040  ********************************************************************/
1041 static void api_samr_unknown_12( uint16 vuid, prs_struct *data, prs_struct *rdata)
1042 {
1043         SAMR_Q_UNKNOWN_12 q_u;
1044
1045         /* grab the samr lookup names */
1046         samr_io_q_unknown_12("", &q_u, data, 0);
1047
1048         /* construct reply.  always indicate success */
1049         samr_reply_unknown_12(&q_u, rdata);
1050 }
1051
1052
1053 /*******************************************************************
1054  samr_reply_open_user
1055  ********************************************************************/
1056 static void samr_reply_open_user(SAMR_Q_OPEN_USER *q_u,
1057                                 prs_struct *rdata,
1058                                 int status)
1059 {
1060         SAMR_R_OPEN_USER r_u;
1061         struct sam_passwd *sam_pass;
1062         BOOL pol_open = False;
1063
1064         /* set up the SAMR open_user response */
1065         bzero(r_u.user_pol.data, POL_HND_SIZE);
1066
1067         r_u.status = 0x0;
1068
1069         /* find the policy handle.  open a policy on it. */
1070         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
1071         {
1072                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1073         }
1074
1075         /* get a (unique) handle.  open a policy on it. */
1076         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.user_pol))))
1077         {
1078                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1079         }
1080
1081         become_root(True);
1082         sam_pass = getsam21pwrid(q_u->user_rid);
1083         unbecome_root(True);
1084
1085         /* check that the RID exists in our domain. */
1086         if (r_u.status == 0x0 && sam_pass == NULL)
1087         {
1088                 r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1089         }
1090
1091         /* associate the RID with the (unique) handle. */
1092         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.user_pol), q_u->user_rid))
1093         {
1094                 /* oh, whoops.  don't know what error message to return, here */
1095                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1096         }
1097
1098         if (r_u.status != 0 && pol_open)
1099         {
1100                 close_lsa_policy_hnd(&(r_u.user_pol));
1101         }
1102
1103         DEBUG(5,("samr_open_user: %d\n", __LINE__));
1104
1105         /* store the response in the SMB stream */
1106         samr_io_r_open_user("", &r_u, rdata, 0);
1107
1108         DEBUG(5,("samr_open_user: %d\n", __LINE__));
1109
1110 }
1111
1112 /*******************************************************************
1113  api_samr_open_user
1114  ********************************************************************/
1115 static void api_samr_open_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
1116 {
1117         SAMR_Q_OPEN_USER q_u;
1118
1119         /* grab the samr unknown 22 */
1120         samr_io_q_open_user("", &q_u, data, 0);
1121
1122         /* construct reply.  always indicate success */
1123         samr_reply_open_user(&q_u, rdata, 0x0);
1124 }
1125
1126
1127 /*************************************************************************
1128  get_user_info_10
1129  *************************************************************************/
1130 static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid)
1131 {
1132         struct smb_passwd *smb_pass;
1133
1134         if (!pwdb_rid_is_user(user_rid))
1135         {
1136                 DEBUG(4,("RID 0x%x is not a user RID\n", user_rid));
1137                 return False;
1138         }
1139
1140         become_root(True);
1141         smb_pass = getsmbpwrid(user_rid);
1142         unbecome_root(True);
1143
1144         if (smb_pass == NULL)
1145         {
1146                 DEBUG(4,("User 0x%x not found\n", user_rid));
1147                 return False;
1148         }
1149
1150         DEBUG(3,("User:[%s]\n", smb_pass->smb_name));
1151
1152         make_sam_user_info10(id10, smb_pass->acct_ctrl); 
1153
1154         return True;
1155 }
1156
1157 /*************************************************************************
1158  get_user_info_21
1159  *************************************************************************/
1160 static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid)
1161 {
1162         NTTIME dummy_time;
1163         struct sam_passwd *sam_pass;
1164         LOGON_HRS hrs;
1165         int i;
1166
1167         if (!pwdb_rid_is_user(user_rid))
1168         {
1169                 DEBUG(4,("RID 0x%x is not a user RID\n", user_rid));
1170                 return False;
1171         }
1172
1173         become_root(True);
1174         sam_pass = getsam21pwrid(user_rid);
1175         unbecome_root(True);
1176
1177         if (sam_pass == NULL)
1178         {
1179                 DEBUG(4,("User 0x%x not found\n", user_rid));
1180                 return False;
1181         }
1182
1183         DEBUG(3,("User:[%s]\n", sam_pass->smb_name));
1184
1185         dummy_time.low  = 0xffffffff;
1186         dummy_time.high = 0x7fffffff;
1187
1188         DEBUG(0,("get_user_info_21 - TODO: convert unix times to NTTIMEs\n"));
1189
1190         /* create a LOGON_HRS structure */
1191         hrs.len = sam_pass->hours_len;
1192         SMB_ASSERT_ARRAY(hrs.hours, hrs.len);
1193         for (i = 0; i < hrs.len; i++)
1194         {
1195                 hrs.hours[i] = sam_pass->hours[i];
1196         }
1197
1198         make_sam_user_info21(id21,
1199
1200                            &dummy_time, /* logon_time */
1201                            &dummy_time, /* logoff_time */
1202                            &dummy_time, /* kickoff_time */
1203                            &dummy_time, /* pass_last_set_time */
1204                            &dummy_time, /* pass_can_change_time */
1205                            &dummy_time, /* pass_must_change_time */
1206
1207                            sam_pass->smb_name, /* user_name */
1208                            sam_pass->full_name, /* full_name */
1209                            sam_pass->home_dir, /* home_dir */
1210                            sam_pass->dir_drive, /* dir_drive */
1211                            sam_pass->logon_script, /* logon_script */
1212                            sam_pass->profile_path, /* profile_path */
1213                            sam_pass->acct_desc, /* description */
1214                            sam_pass->workstations, /* workstations user can log in from */
1215                            sam_pass->unknown_str, /* don't know, yet */
1216                            sam_pass->munged_dial, /* dialin info.  contains dialin path and tel no */
1217
1218                            sam_pass->user_rid, /* RID user_id */
1219                            sam_pass->group_rid, /* RID group_id */
1220                        sam_pass->acct_ctrl,
1221
1222                    sam_pass->unknown_3, /* unknown_3 */
1223                        sam_pass->logon_divs, /* divisions per week */
1224                            &hrs, /* logon hours */
1225                        sam_pass->unknown_5,
1226                        sam_pass->unknown_6);
1227
1228         return True;
1229 }
1230
1231 /*******************************************************************
1232  samr_reply_query_userinfo
1233  ********************************************************************/
1234 static void samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u,
1235                                 prs_struct *rdata)
1236 {
1237         SAMR_R_QUERY_USERINFO r_u;
1238 #if 0
1239         SAM_USER_INFO_11 id11;
1240 #endif
1241         SAM_USER_INFO_10 id10;
1242         SAM_USER_INFO_21 id21;
1243         void *info = NULL;
1244
1245         uint32 status = 0x0;
1246         uint32 rid = 0x0;
1247
1248         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1249
1250         /* search for the handle */
1251         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1252         {
1253                 status = NT_STATUS_INVALID_HANDLE;
1254         }
1255
1256         /* find the user's rid */
1257         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1258         {
1259                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1260         }
1261
1262         DEBUG(5,("samr_reply_query_userinfo: rid:0x%x\n", rid));
1263
1264         /* ok!  user info levels (there are lots: see MSDEV help), off we go... */
1265         if (status == 0x0)
1266         {
1267                 switch (q_u->switch_value)
1268                 {
1269                         case 0x10:
1270                         {
1271                                 info = (void*)&id10;
1272                                 status = get_user_info_10(&id10, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1273                                 break;
1274                         }
1275 #if 0
1276 /* whoops - got this wrong.  i think.  or don't understand what's happening. */
1277                         case 0x11:
1278                         {
1279                                 NTTIME expire;
1280                                 info = (void*)&id11;
1281                                 
1282                                 expire.low  = 0xffffffff;
1283                                 expire.high = 0x7fffffff;
1284
1285                                 make_sam_user_info11(&id11, &expire, "BROOKFIELDS$", 0x03ef, 0x201, 0x0080);
1286
1287                                 break;
1288                         }
1289 #endif
1290                         case 21:
1291                         {
1292                                 info = (void*)&id21;
1293                                 status = get_user_info_21(&id21, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1294                                 break;
1295                         }
1296
1297                         default:
1298                         {
1299                                 status = NT_STATUS_INVALID_INFO_CLASS;
1300
1301                                 break;
1302                         }
1303                 }
1304         }
1305
1306         make_samr_r_query_userinfo(&r_u, q_u->switch_value, info, status);
1307
1308         /* store the response in the SMB stream */
1309         samr_io_r_query_userinfo("", &r_u, rdata, 0);
1310
1311         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1312
1313 }
1314
1315 /*******************************************************************
1316  api_samr_query_userinfo
1317  ********************************************************************/
1318 static void api_samr_query_userinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
1319 {
1320         SAMR_Q_QUERY_USERINFO q_u;
1321
1322         /* grab the samr unknown 24 */
1323         samr_io_q_query_userinfo("", &q_u, data, 0);
1324
1325         /* construct reply.  always indicate success */
1326         samr_reply_query_userinfo(&q_u, rdata);
1327 }
1328
1329
1330 /*******************************************************************
1331  samr_reply_query_usergroups
1332  ********************************************************************/
1333 static void samr_reply_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
1334                                 prs_struct *rdata)
1335 {
1336         SAMR_R_QUERY_USERGROUPS r_u;
1337         uint32 status = 0x0;
1338
1339         struct sam_passwd *sam_pass;
1340         DOM_GID *gids = NULL;
1341         int num_groups = 0;
1342         uint32 rid;
1343
1344         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1345
1346         /* find the policy handle.  open a policy on it. */
1347         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1348         {
1349                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1350         }
1351
1352         /* find the user's rid */
1353         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1354         {
1355                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1356         }
1357
1358         if (status == 0x0)
1359         {
1360                 become_root(True);
1361                 sam_pass = getsam21pwrid(rid);
1362                 unbecome_root(True);
1363
1364                 if (sam_pass == NULL)
1365                 {
1366                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1367                 }
1368         }
1369
1370         if (status == 0x0)
1371         {
1372                 DOMAIN_GRP *mem_grp = NULL;
1373                 BOOL ret;
1374
1375                 become_root(True);
1376                 ret = getusergroupsnam(sam_pass->smb_name, &mem_grp, &num_groups);
1377                 unbecome_root(True);
1378
1379                 gids = NULL;
1380                 num_groups = make_dom_gids(mem_grp, num_groups, &gids);
1381
1382                 if (mem_grp != NULL)
1383                 {
1384                         free(mem_grp);
1385                 }
1386         }
1387
1388         /* construct the response.  lkclXXXX: gids are not copied! */
1389         make_samr_r_query_usergroups(&r_u, num_groups, gids, status);
1390
1391         /* store the response in the SMB stream */
1392         samr_io_r_query_usergroups("", &r_u, rdata, 0);
1393
1394         if (gids)
1395         {
1396                 free((char *)gids);
1397         }
1398
1399         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1400
1401 }
1402
1403 /*******************************************************************
1404  api_samr_query_usergroups
1405  ********************************************************************/
1406 static void api_samr_query_usergroups( uint16 vuid, prs_struct *data, prs_struct *rdata)
1407 {
1408         SAMR_Q_QUERY_USERGROUPS q_u;
1409         /* grab the samr unknown 32 */
1410         samr_io_q_query_usergroups("", &q_u, data, 0);
1411
1412         /* construct reply. */
1413         samr_reply_query_usergroups(&q_u, rdata);
1414 }
1415
1416
1417 /*******************************************************************
1418  samr_reply_query_dom_info
1419  ********************************************************************/
1420 static void samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u,
1421                                 prs_struct *rdata)
1422 {
1423         SAMR_R_QUERY_DOMAIN_INFO r_u;
1424         SAM_UNK_CTR ctr;
1425         uint16 switch_value = 0x0;
1426         uint32 status = 0x0;
1427
1428         ZERO_STRUCT(r_u);
1429         ZERO_STRUCT(ctr);
1430
1431         r_u.ctr = &ctr;
1432
1433         DEBUG(5,("samr_reply_query_dom_info: %d\n", __LINE__));
1434
1435         /* find the policy handle.  open a policy on it. */
1436         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
1437         {
1438                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1439                 DEBUG(5,("samr_reply_query_dom_info: invalid handle\n"));
1440         }
1441
1442         if (status == 0x0)
1443         {
1444                 switch (q_u->switch_value)
1445                 {
1446                         case 0x02:
1447                         {
1448                                 switch_value = 0x2;
1449                                 make_unk_info2(&ctr.info.inf2, global_sam_name, global_myname);
1450
1451                                 break;
1452                         }
1453                         default:
1454                         {
1455                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
1456                                 break;
1457                         }
1458                 }
1459         }
1460
1461         make_samr_r_query_dom_info(&r_u, switch_value, &ctr, status);
1462
1463         /* store the response in the SMB stream */
1464         samr_io_r_query_dom_info("", &r_u, rdata, 0);
1465
1466         DEBUG(5,("samr_query_dom_info: %d\n", __LINE__));
1467
1468 }
1469
1470 /*******************************************************************
1471  api_samr_query_dom_info
1472  ********************************************************************/
1473 static void api_samr_query_dom_info( uint16 vuid, prs_struct *data, prs_struct *rdata)
1474 {
1475         SAMR_Q_QUERY_DOMAIN_INFO q_e;
1476
1477         /* grab the samr unknown 8 command */
1478         samr_io_q_query_dom_info("", &q_e, data, 0);
1479
1480         /* construct reply. */
1481         samr_reply_query_dom_info(&q_e, rdata);
1482 }
1483
1484
1485
1486 /*******************************************************************
1487  samr_reply_unknown_32
1488  ********************************************************************/
1489 static void samr_reply_unknown_32(SAMR_Q_UNKNOWN_32 *q_u,
1490                                 prs_struct *rdata,
1491                                 int status)
1492 {
1493         int i;
1494         SAMR_R_UNKNOWN_32 r_u;
1495
1496         /* set up the SAMR unknown_32 response */
1497         bzero(r_u.pol.data, POL_HND_SIZE);
1498         if (status == 0)
1499         {
1500                 for (i = 4; i < POL_HND_SIZE; i++)
1501                 {
1502                         r_u.pol.data[i] = i+1;
1503                 }
1504         }
1505
1506         make_dom_rid4(&(r_u.rid4), 0x0030, 0, 0);
1507         r_u.status    = status;
1508
1509         DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1510
1511         /* store the response in the SMB stream */
1512         samr_io_r_unknown_32("", &r_u, rdata, 0);
1513
1514         DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1515
1516 }
1517
1518 /*******************************************************************
1519  api_samr_unknown_32
1520  ********************************************************************/
1521 static void api_samr_unknown_32( uint16 vuid, prs_struct *data, prs_struct *rdata)
1522 {
1523         uint32 status = 0;
1524         struct sam_passwd *sam_pass;
1525         fstring mach_acct;
1526
1527         SAMR_Q_UNKNOWN_32 q_u;
1528
1529         /* grab the samr unknown 32 */
1530         samr_io_q_unknown_32("", &q_u, data, 0);
1531
1532         /* find the machine account: tell the caller if it exists.
1533            lkclXXXX i have *no* idea if this is a problem or not
1534            or even if you are supposed to construct a different
1535            reply if the account already exists...
1536          */
1537
1538         fstrcpy(mach_acct, unistrn2(q_u.uni_mach_acct.buffer,
1539                                     q_u.uni_mach_acct.uni_str_len));
1540
1541         become_root(True);
1542         sam_pass = getsam21pwnam(mach_acct);
1543         unbecome_root(True);
1544
1545         if (sam_pass != NULL)
1546         {
1547                 /* machine account exists: say so */
1548                 status = 0xC0000000 | NT_STATUS_USER_EXISTS;
1549         }
1550         else
1551         {
1552                 /* this could cause trouble... */
1553                 DEBUG(0,("trouble!\n"));
1554                 status = 0;
1555         }
1556
1557         /* construct reply. */
1558         samr_reply_unknown_32(&q_u, rdata, status);
1559 }
1560
1561
1562 /*******************************************************************
1563  samr_reply_connect_anon
1564  ********************************************************************/
1565 static void samr_reply_connect_anon(SAMR_Q_CONNECT_ANON *q_u,
1566                                 prs_struct *rdata)
1567 {
1568         SAMR_R_CONNECT_ANON r_u;
1569         BOOL pol_open = False;
1570
1571         /* set up the SAMR connect_anon response */
1572
1573         r_u.status = 0x0;
1574         /* get a (unique) handle.  open a policy on it. */
1575         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1576         {
1577                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1578         }
1579
1580         /* associate the domain SID with the (unique) handle. */
1581         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1582         {
1583                 /* oh, whoops.  don't know what error message to return, here */
1584                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1585         }
1586
1587         if (r_u.status != 0 && pol_open)
1588         {
1589                 close_lsa_policy_hnd(&(r_u.connect_pol));
1590         }
1591
1592         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
1593
1594         /* store the response in the SMB stream */
1595         samr_io_r_connect_anon("", &r_u, rdata, 0);
1596
1597         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
1598
1599 }
1600
1601 /*******************************************************************
1602  api_samr_connect_anon
1603  ********************************************************************/
1604 static void api_samr_connect_anon( uint16 vuid, prs_struct *data, prs_struct *rdata)
1605 {
1606         SAMR_Q_CONNECT_ANON q_u;
1607
1608         /* grab the samr open policy */
1609         samr_io_q_connect_anon("", &q_u, data, 0);
1610
1611         /* construct reply.  always indicate success */
1612         samr_reply_connect_anon(&q_u, rdata);
1613 }
1614
1615 /*******************************************************************
1616  samr_reply_connect
1617  ********************************************************************/
1618 static void samr_reply_connect(SAMR_Q_CONNECT *q_u,
1619                                 prs_struct *rdata)
1620 {
1621         SAMR_R_CONNECT r_u;
1622         BOOL pol_open = False;
1623
1624         /* set up the SAMR connect response */
1625
1626         r_u.status = 0x0;
1627         /* get a (unique) handle.  open a policy on it. */
1628         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1629         {
1630                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1631         }
1632
1633         /* associate the domain SID with the (unique) handle. */
1634         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1635         {
1636                 /* oh, whoops.  don't know what error message to return, here */
1637                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1638         }
1639
1640         if (r_u.status != 0 && pol_open)
1641         {
1642                 close_lsa_policy_hnd(&(r_u.connect_pol));
1643         }
1644
1645         DEBUG(5,("samr_connect: %d\n", __LINE__));
1646
1647         /* store the response in the SMB stream */
1648         samr_io_r_connect("", &r_u, rdata, 0);
1649
1650         DEBUG(5,("samr_connect: %d\n", __LINE__));
1651
1652 }
1653
1654 /*******************************************************************
1655  api_samr_connect
1656  ********************************************************************/
1657 static void api_samr_connect( uint16 vuid, prs_struct *data, prs_struct *rdata)
1658 {
1659         SAMR_Q_CONNECT q_u;
1660
1661         /* grab the samr open policy */
1662         samr_io_q_connect("", &q_u, data, 0);
1663
1664         /* construct reply.  always indicate success */
1665         samr_reply_connect(&q_u, rdata);
1666 }
1667
1668 /*******************************************************************
1669  samr_reply_open_alias
1670  ********************************************************************/
1671 static void samr_reply_open_alias(SAMR_Q_OPEN_ALIAS *q_u,
1672                                 prs_struct *rdata)
1673 {
1674         SAMR_R_OPEN_ALIAS r_u;
1675         BOOL pol_open = False;
1676
1677         /* set up the SAMR open_alias response */
1678
1679         r_u.status = 0x0;
1680         /* get a (unique) handle.  open a policy on it. */
1681         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.pol))))
1682         {
1683                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1684         }
1685
1686         /* associate a RID with the (unique) handle. */
1687         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.pol), q_u->rid_alias))
1688         {
1689                 /* oh, whoops.  don't know what error message to return, here */
1690                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1691         }
1692
1693         if (r_u.status != 0 && pol_open)
1694         {
1695                 close_lsa_policy_hnd(&(r_u.pol));
1696         }
1697
1698         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
1699
1700         /* store the response in the SMB stream */
1701         samr_io_r_open_alias("", &r_u, rdata, 0);
1702
1703         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
1704
1705 }
1706
1707 /*******************************************************************
1708  api_samr_open_alias
1709  ********************************************************************/
1710 static void api_samr_open_alias( uint16 vuid, prs_struct *data, prs_struct *rdata)
1711                                 
1712 {
1713         SAMR_Q_OPEN_ALIAS q_u;
1714
1715         /* grab the samr open policy */
1716         samr_io_q_open_alias("", &q_u, data, 0);
1717
1718         /* construct reply.  always indicate success */
1719         samr_reply_open_alias(&q_u, rdata);
1720 }
1721
1722 /*******************************************************************
1723  array of \PIPE\samr operations
1724  ********************************************************************/
1725 static struct api_struct api_samr_cmds [] =
1726 {
1727         { "SAMR_CLOSE_HND"        , SAMR_CLOSE_HND        , api_samr_close_hnd        },
1728         { "SAMR_CONNECT"          , SAMR_CONNECT          , api_samr_connect          },
1729         { "SAMR_CONNECT_ANON"     , SAMR_CONNECT_ANON     , api_samr_connect_anon     },
1730         { "SAMR_ENUM_DOM_USERS"   , SAMR_ENUM_DOM_USERS   , api_samr_enum_dom_users   },
1731         { "SAMR_ENUM_DOM_GROUPS"  , SAMR_ENUM_DOM_GROUPS  , api_samr_enum_dom_groups  },
1732         { "SAMR_ENUM_DOM_ALIASES" , SAMR_ENUM_DOM_ALIASES , api_samr_enum_dom_aliases },
1733         { "SAMR_LOOKUP_IDS"       , SAMR_LOOKUP_IDS       , api_samr_lookup_ids       },
1734         { "SAMR_LOOKUP_NAMES"     , SAMR_LOOKUP_NAMES     , api_samr_lookup_names     },
1735         { "SAMR_OPEN_USER"        , SAMR_OPEN_USER        , api_samr_open_user        },
1736         { "SAMR_QUERY_USERINFO"   , SAMR_QUERY_USERINFO   , api_samr_query_userinfo   },
1737         { "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info        },
1738         { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
1739         { "SAMR_QUERY_DISPINFO"   , SAMR_QUERY_DISPINFO   , api_samr_query_dispinfo   },
1740         { "SAMR_QUERY_ALIASINFO"  , SAMR_QUERY_ALIASINFO  , api_samr_query_aliasinfo  },
1741         { "SAMR_0x32"             , 0x32                  , api_samr_unknown_32       },
1742         { "SAMR_UNKNOWN_12"       , SAMR_UNKNOWN_12       , api_samr_unknown_12       },
1743         { "SAMR_UNKNOWN_38"       , SAMR_UNKNOWN_38       , api_samr_unknown_38       },
1744         { "SAMR_CHGPASSWD_USER"   , SAMR_CHGPASSWD_USER   , api_samr_chgpasswd_user   },
1745         { "SAMR_OPEN_ALIAS"       , SAMR_OPEN_ALIAS       , api_samr_open_alias       },
1746         { "SAMR_OPEN_DOMAIN"      , SAMR_OPEN_DOMAIN      , api_samr_open_domain      },
1747         { "SAMR_UNKNOWN_3"        , SAMR_UNKNOWN_3        , api_samr_unknown_3        },
1748         { "SAMR_UNKNOWN_2C"       , SAMR_UNKNOWN_2C       , api_samr_unknown_2c       },
1749         { NULL                    , 0                     , NULL                      }
1750 };
1751
1752 /*******************************************************************
1753  receives a samr pipe and responds.
1754  ********************************************************************/
1755 BOOL api_samr_rpc(pipes_struct *p, prs_struct *data)
1756 {
1757     return api_rpcTNP(p, "api_samr_rpc", api_samr_cmds, data);
1758 }
1759