jean-francois micouleau's well-alpha code for ldap password database stuff!
[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 rid_name domain_group_rids[];
34 extern rid_name domain_alias_rids[];
35
36 /*******************************************************************
37   This next function should be replaced with something that
38   dynamically returns the correct user info..... JRA.
39  ********************************************************************/
40
41 static BOOL get_smbpwd_entries(SAM_USER_INFO_21 *pw_buf,
42                                 int *total_entries, int *num_entries,
43                                 int max_num_entries,
44                                 uint16 acb_mask)
45 {
46         void *vp = NULL;
47         struct smb_passwd *pwd = NULL;
48
49         (*num_entries) = 0;
50         (*total_entries) = 0;
51
52         if (pw_buf == NULL) return False;
53
54         vp = startsmbpwent(False);
55         if (!vp)
56         {
57                 DEBUG(0, ("get_smbpwd_entries: Unable to open SMB password file.\n"));
58                 return False;
59         }
60
61         while (((pwd = getsmbpwent(vp)) != NULL) && (*num_entries) < max_num_entries)
62         {
63                 int user_name_len = strlen(pwd->smb_name);
64                 make_unistr2(&(pw_buf[(*num_entries)].uni_user_name), pwd->smb_name, user_name_len-1);
65                 make_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len-1, 
66                                user_name_len-1, 1);
67                 pw_buf[(*num_entries)].user_rid = pwd->smb_userid;
68                 bzero( pw_buf[(*num_entries)].nt_pwd , 16);
69
70                 /* Now check if the NT compatible password is available. */
71                 if (pwd->smb_nt_passwd != NULL)
72                 {
73                         memcpy( pw_buf[(*num_entries)].nt_pwd , pwd->smb_nt_passwd, 16);
74                 }
75
76                 pw_buf[(*num_entries)].acb_info = (uint16)pwd->acct_ctrl;
77
78                 DEBUG(5, ("get_smbpwd_entries: idx: %d user %s, uid %d, acb %x",
79                 (*num_entries), pwd->smb_name, pwd->smb_userid, pwd->acct_ctrl));
80
81                 if (acb_mask == 0 || IS_BITS_SET_SOME(pwd->acct_ctrl, acb_mask))
82                 {
83                         DEBUG(5,(" acb_mask %x accepts\n", acb_mask));
84                         (*num_entries)++;
85                 }
86                 else
87                 {
88                         DEBUG(5,(" acb_mask %x rejects\n", acb_mask));
89                 }
90
91                 (*total_entries)++;
92         }
93
94         endsmbpwent(vp);
95
96         return (*num_entries) > 0;
97 }
98
99 /*******************************************************************
100  samr_reply_unknown_1
101  ********************************************************************/
102 static void samr_reply_close_hnd(SAMR_Q_CLOSE_HND *q_u,
103                                 prs_struct *rdata)
104 {
105         SAMR_R_CLOSE_HND r_u;
106
107         /* set up the SAMR unknown_1 response */
108         bzero(&(r_u.pol.data), POL_HND_SIZE);
109
110         /* close the policy handle */
111         if (close_lsa_policy_hnd(&(q_u->pol)))
112         {
113                 r_u.status = 0;
114         }
115         else
116         {
117                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_INVALID;
118         }
119
120         DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
121
122         /* store the response in the SMB stream */
123         samr_io_r_close_hnd("", &r_u, rdata, 0);
124
125         DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
126
127 }
128
129 /*******************************************************************
130  api_samr_close_hnd
131  ********************************************************************/
132 static void api_samr_close_hnd( int uid, prs_struct *data, prs_struct *rdata)
133 {
134         SAMR_Q_CLOSE_HND q_u;
135
136         /* grab the samr unknown 1 */
137         samr_io_q_close_hnd("", &q_u, data, 0);
138
139         /* construct reply.  always indicate success */
140         samr_reply_close_hnd(&q_u, rdata);
141 }
142
143
144 /*******************************************************************
145  samr_reply_open_domain
146  ********************************************************************/
147 static void samr_reply_open_domain(SAMR_Q_OPEN_DOMAIN *q_u,
148                                 prs_struct *rdata)
149 {
150         SAMR_R_OPEN_DOMAIN r_u;
151         BOOL pol_open = False;
152         int pol_idx;
153
154         r_u.status = 0x0;
155
156         /* find the connection policy handle. */
157         if (r_u.status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->connect_pol))) == -1))
158         {
159                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
160         }
161
162         /* get a (unique) handle.  open a policy on it. */
163         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.domain_pol))))
164         {
165                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
166         }
167
168         /* associate the domain SID with the (unique) handle. */
169         if (r_u.status == 0x0 && !set_lsa_policy_samr_sid(&(r_u.domain_pol), &(q_u->dom_sid.sid)))
170         {
171                 /* oh, whoops.  don't know what error message to return, here */
172                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
173         }
174
175         if (r_u.status != 0 && pol_open)
176         {
177                 close_lsa_policy_hnd(&(r_u.domain_pol));
178         }
179
180         DEBUG(5,("samr_open_domain: %d\n", __LINE__));
181
182         /* store the response in the SMB stream */
183         samr_io_r_open_domain("", &r_u, rdata, 0);
184
185         DEBUG(5,("samr_open_domain: %d\n", __LINE__));
186
187 }
188
189 /*******************************************************************
190  api_samr_open_domain
191  ********************************************************************/
192 static void api_samr_open_domain( int uid, prs_struct *data, prs_struct *rdata)
193 {
194         SAMR_Q_OPEN_DOMAIN q_u;
195
196         /* grab the samr open */
197         samr_io_q_open_domain("", &q_u, data, 0);
198
199         /* construct reply.  always indicate success */
200         samr_reply_open_domain(&q_u, rdata);
201 }
202
203
204 /*******************************************************************
205  samr_reply_unknown_3
206  ********************************************************************/
207 static void samr_reply_unknown_3(SAMR_Q_UNKNOWN_3 *q_u,
208                                 prs_struct *rdata)
209 {
210         SAMR_R_UNKNOWN_3 r_u;
211         DOM_SID3 sid[MAX_SAM_SIDS];
212         fstring user_sid;
213         fstring user_rid;
214         int pol_idx;
215         uint32 rid;
216         uint32 status;
217
218         status = 0x0;
219
220         /* find the policy handle.  open a policy on it. */
221         if (status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->user_pol))) == -1))
222         {
223                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
224         }
225
226         /* find the user's rid */
227         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->user_pol))) == 0xffffffff)
228         {
229                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
230         }
231
232         if (status == 0x0)
233         {
234                 strcpy(user_sid, lp_domain_sid());
235                 sprintf(user_rid, "-%x", rid);
236                 strcat(user_sid, user_rid);
237
238                 /* maybe need another 1 or 2 (S-1-5-20-0x220 and S-1-5-20-0x224) */
239                 /* these two are DOMAIN_ADMIN and DOMAIN_ACCT_OP group RIDs */
240                 make_dom_sid3(&(sid[0]), 0x035b, 0x0002, "S-1-1");
241                 make_dom_sid3(&(sid[1]), 0x0044, 0x0002, user_sid);
242         }
243
244         make_samr_r_unknown_3(&r_u,
245                                 0x0001, 0x8004,
246                                 0x00000014, 0x0002, 0x0070,
247                                 2, sid, status);
248
249         DEBUG(5,("samr_unknown_3: %d\n", __LINE__));
250
251         /* store the response in the SMB stream */
252         samr_io_r_unknown_3("", &r_u, rdata, 0);
253
254         DEBUG(5,("samr_unknown_3: %d\n", __LINE__));
255
256 }
257
258 /*******************************************************************
259  api_samr_unknown_3
260  ********************************************************************/
261 static void api_samr_unknown_3( int uid, prs_struct *data, prs_struct *rdata)
262 {
263         SAMR_Q_UNKNOWN_3 q_u;
264
265         /* grab the samr open */
266         samr_io_q_unknown_3("", &q_u, data, 0);
267
268         /* construct reply.  always indicate success */
269         samr_reply_unknown_3(&q_u, rdata);
270 }
271
272
273 /*******************************************************************
274  samr_reply_enum_dom_users
275  ********************************************************************/
276 static void samr_reply_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_u,
277                                 prs_struct *rdata)
278 {
279         SAMR_R_ENUM_DOM_USERS r_e;
280         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
281         int num_entries;
282         int total_entries;
283         int pol_idx;
284         BOOL got_pwds;
285
286         r_e.status = 0x0;
287         r_e.total_num_entries = 0;
288
289         /* find the policy handle.  open a policy on it. */
290         if (r_e.status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->pol))) == -1))
291         {
292                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
293         }
294
295         DEBUG(5,("samr_reply_enum_dom_users: %d\n", __LINE__));
296
297         become_root(True);
298         got_pwds = get_smbpwd_entries(pass, &total_entries, &num_entries, MAX_SAM_ENTRIES, q_u->acb_mask);
299         unbecome_root(True);
300
301         make_samr_r_enum_dom_users(&r_e, total_entries,
302                                    q_u->unknown_0, num_entries,
303                                    pass, r_e.status);
304
305         /* store the response in the SMB stream */
306         samr_io_r_enum_dom_users("", &r_e, rdata, 0);
307
308         DEBUG(5,("samr_enum_dom_users: %d\n", __LINE__));
309
310 }
311
312 /*******************************************************************
313  api_samr_enum_dom_users
314  ********************************************************************/
315 static void api_samr_enum_dom_users( int uid, prs_struct *data, prs_struct *rdata)
316 {
317         SAMR_Q_ENUM_DOM_USERS q_e;
318
319         /* grab the samr open */
320         samr_io_q_enum_dom_users("", &q_e, data, 0);
321
322         /* construct reply. */
323         samr_reply_enum_dom_users(&q_e, rdata);
324 }
325
326
327 /*******************************************************************
328  samr_reply_enum_dom_groups
329  ********************************************************************/
330 static void samr_reply_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_u,
331                                 prs_struct *rdata)
332 {
333         SAMR_R_ENUM_DOM_GROUPS r_e;
334         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
335         int num_entries;
336         int pol_idx;
337         BOOL got_grps;
338         char *dummy_group = "Domain Admins";
339
340         r_e.status = 0x0;
341         r_e.num_entries = 0;
342
343         /* find the policy handle.  open a policy on it. */
344         if (r_e.status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->pol))) == -1))
345         {
346                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
347         }
348
349         DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__));
350
351         got_grps = True;
352         num_entries = 1;
353         make_unistr2(&(pass[0].uni_user_name), dummy_group, strlen(dummy_group));
354         pass[0].user_rid = DOMAIN_GROUP_RID_ADMINS;
355
356         if (r_e.status == 0 && got_grps)
357         {
358                 make_samr_r_enum_dom_groups(&r_e, q_u->start_idx, num_entries, pass, r_e.status);
359         }
360
361         /* store the response in the SMB stream */
362         samr_io_r_enum_dom_groups("", &r_e, rdata, 0);
363
364         DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__));
365
366 }
367
368 /*******************************************************************
369  api_samr_enum_dom_groups
370  ********************************************************************/
371 static void api_samr_enum_dom_groups( int uid, prs_struct *data, prs_struct *rdata)
372 {
373         SAMR_Q_ENUM_DOM_GROUPS q_e;
374
375         /* grab the samr open */
376         samr_io_q_enum_dom_groups("", &q_e, data, 0);
377
378         /* construct reply. */
379         samr_reply_enum_dom_groups(&q_e, rdata);
380 }
381
382
383 /*******************************************************************
384  samr_reply_enum_dom_aliases
385  ********************************************************************/
386 static void samr_reply_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_u,
387                                 prs_struct *rdata)
388 {
389         SAMR_R_ENUM_DOM_ALIASES r_e;
390         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
391         int num_entries;
392         int pol_idx;
393         BOOL got_aliases;
394         char *dummy_alias = "admins";
395
396         r_e.status = 0x0;
397         r_e.num_entries = 0;
398
399         /* find the policy handle.  open a policy on it. */
400         if (r_e.status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->pol))) == -1))
401         {
402                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
403         }
404
405         DEBUG(5,("samr_reply_enum_dom_aliases: %d\n", __LINE__));
406
407         got_aliases = True;
408         num_entries = 1;
409         make_unistr2(&(pass[0].uni_user_name), dummy_alias, strlen(dummy_alias));
410         pass[0].user_rid = DOMAIN_ALIAS_RID_ADMINS;
411
412         if (r_e.status == 0 && got_aliases)
413         {
414                 make_samr_r_enum_dom_aliases(&r_e, num_entries, pass, r_e.status);
415         }
416
417         /* store the response in the SMB stream */
418         samr_io_r_enum_dom_aliases("", &r_e, rdata, 0);
419
420         DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__));
421
422 }
423
424 /*******************************************************************
425  api_samr_enum_dom_aliases
426  ********************************************************************/
427 static void api_samr_enum_dom_aliases( int uid, prs_struct *data, prs_struct *rdata)
428 {
429         SAMR_Q_ENUM_DOM_ALIASES q_e;
430
431         /* grab the samr open */
432         samr_io_q_enum_dom_aliases("", &q_e, data, 0);
433
434         /* construct reply. */
435         samr_reply_enum_dom_aliases(&q_e, rdata);
436 }
437
438
439 /*******************************************************************
440  samr_reply_query_dispinfo
441  ********************************************************************/
442 static void samr_reply_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_u,
443                                 prs_struct *rdata)
444 {
445         SAMR_R_QUERY_DISPINFO r_e;
446         SAM_INFO_CTR ctr;
447         SAM_INFO_1 info1;
448         SAM_INFO_2 info2;
449         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
450         int num_entries;
451         int total_entries;
452         int pol_idx;
453         BOOL got_pwds;
454         uint16 switch_level = 0x0;
455
456         r_e.status = 0x0;
457
458         /* find the policy handle.  open a policy on it. */
459         if (r_e.status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->pol))) == -1))
460         {
461                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
462         }
463
464         DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__));
465
466 #ifndef USE_LDAP
467         become_root(True);
468
469         got_pwds = get_smbpwd_entries(pass, &total_entries, &num_entries, MAX_SAM_ENTRIES, 0);
470
471         unbecome_root(True);
472 #endif
473
474         switch (q_u->switch_level)
475         {
476                 case 0x1:
477                 {
478                 
479                         /* query disp info is for users */
480                         switch_level = 0x1;
481 #ifdef USE_LDAP                 
482                         got_pwds = get_ldap_entries(pass, 
483                                                     &total_entries, 
484                                                     &num_entries,
485                                                     MAX_SAM_ENTRIES, 
486                                                     0, 
487                                                     switch_level);
488 #endif                
489                         make_sam_info_1(&info1, ACB_NORMAL,
490                                 q_u->start_idx, num_entries, pass);
491
492                         ctr.sam.info1 = &info1;
493
494                         break;
495                 }
496                 case 0x2:
497                 {
498                         /* query disp info is for servers */
499                         switch_level = 0x2;
500 #ifdef USE_LDAP                 
501                         got_pwds = get_ldap_entries(pass, 
502                                                     &total_entries, 
503                                                     &num_entries,
504                                                     MAX_SAM_ENTRIES, 
505                                                     0, 
506                                                     switch_level);
507 #endif                
508                         make_sam_info_2(&info2, ACB_WSTRUST,
509                                 q_u->start_idx, num_entries, pass);
510
511                         ctr.sam.info2 = &info2;
512
513                         break;
514                 }
515         }
516
517         if (r_e.status == 0 && got_pwds)
518         {
519                 make_samr_r_query_dispinfo(&r_e, switch_level, &ctr, r_e.status);
520         }
521
522         /* store the response in the SMB stream */
523         samr_io_r_query_dispinfo("", &r_e, rdata, 0);
524
525         DEBUG(5,("samr_query_dispinfo: %d\n", __LINE__));
526
527 }
528
529 /*******************************************************************
530  api_samr_query_dispinfo
531  ********************************************************************/
532 static void api_samr_query_dispinfo( int uid, prs_struct *data, prs_struct *rdata)
533 {
534         SAMR_Q_QUERY_DISPINFO q_e;
535
536         /* grab the samr open */
537         samr_io_q_query_dispinfo("", &q_e, data, 0);
538
539         /* construct reply. */
540         samr_reply_query_dispinfo(&q_e, rdata);
541 }
542
543
544 /*******************************************************************
545  samr_reply_query_aliasinfo
546  ********************************************************************/
547 static void samr_reply_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_u,
548                                 prs_struct *rdata)
549 {
550         SAMR_R_QUERY_ALIASINFO r_e;
551         int pol_idx;
552         BOOL got_alias;
553
554         r_e.status = 0x0;
555         r_e.ptr = 0;
556
557         /* find the policy handle.  open a policy on it. */
558         if (r_e.status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->pol))) == -1))
559         {
560                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
561         }
562
563         DEBUG(5,("samr_reply_query_aliasinfo: %d\n", __LINE__));
564
565         if (r_e.status == 0x0)
566         {
567                 if (q_u->switch_level != 3)
568                 {
569                         r_e.status = NT_STATUS_INVALID_INFO_CLASS;
570                 }
571         }
572
573         if (r_e.status == 0x0)
574         {
575                 got_alias = True;
576         }
577
578         make_samr_r_query_aliasinfo(&r_e, q_u->switch_level,
579                             "<account description>",
580                                 r_e.status);
581
582         /* store the response in the SMB stream */
583         samr_io_r_query_aliasinfo("", &r_e, rdata, 0);
584
585         DEBUG(5,("samr_query_aliasinfo: %d\n", __LINE__));
586
587 }
588
589 /*******************************************************************
590  api_samr_query_aliasinfo
591  ********************************************************************/
592 static void api_samr_query_aliasinfo( int uid, prs_struct *data, prs_struct *rdata)
593 {
594         SAMR_Q_QUERY_ALIASINFO q_e;
595
596         /* grab the samr open */
597         samr_io_q_query_aliasinfo("", &q_e, data, 0);
598
599         /* construct reply. */
600         samr_reply_query_aliasinfo(&q_e, rdata);
601 }
602
603
604 /*******************************************************************
605  samr_reply_lookup_ids
606  ********************************************************************/
607 static void samr_reply_lookup_ids(SAMR_Q_LOOKUP_IDS *q_u,
608                                 prs_struct *rdata)
609 {
610         uint32 rid[MAX_SAM_ENTRIES];
611         uint32 status     = 0;
612         int num_rids = q_u->num_sids1;
613
614         SAMR_R_LOOKUP_IDS r_u;
615
616         DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
617
618         if (num_rids > MAX_SAM_ENTRIES)
619         {
620                 num_rids = MAX_SAM_ENTRIES;
621                 DEBUG(5,("samr_lookup_ids: truncating entries to %d\n", num_rids));
622         }
623
624 #if 0
625         int i;
626         for (i = 0; i < num_rids && status == 0; i++)
627         {
628                 struct smb_passwd *smb_pass;
629                 fstring user_name;
630
631                 fstrcpy(user_name, unistrn2(q_u->uni_user_name[i].buffer,
632                                                                         q_u->uni_user_name[i].uni_str_len));
633
634                 /* find the user account */
635                 become_root(True);
636                 smb_pass = get_smbpwd_entry(user_name, 0);
637                 unbecome_root(True);
638
639                 if (smb_pass == NULL)
640                 {
641                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
642                         rid[i] = 0;
643                 }
644                 else
645                 {
646                         /* lkclXXXX SHOULD use name_to_rid() here! */
647                         rid[i] = smb_pass->smb_userid;
648                 }
649         }
650 #endif
651
652         num_rids = 1;
653         rid[0] = DOMAIN_ALIAS_RID_USERS;
654
655         make_samr_r_lookup_ids(&r_u, num_rids, rid, status);
656
657         /* store the response in the SMB stream */
658         samr_io_r_lookup_ids("", &r_u, rdata, 0);
659
660         DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
661
662 }
663
664 /*******************************************************************
665  api_samr_lookup_ids
666  ********************************************************************/
667 static void api_samr_lookup_ids( int uid, prs_struct *data, prs_struct *rdata)
668 {
669         SAMR_Q_LOOKUP_IDS q_u;
670
671         /* grab the samr 0x10 */
672         samr_io_q_lookup_ids("", &q_u, data, 0);
673
674         /* construct reply.  always indicate success */
675         samr_reply_lookup_ids(&q_u, rdata);
676 }
677
678 /*******************************************************************
679  samr_reply_lookup_names
680  ********************************************************************/
681 static void samr_reply_lookup_names(SAMR_Q_LOOKUP_NAMES *q_u,
682                                 prs_struct *rdata)
683 {
684         uint32 rid[MAX_SAM_ENTRIES];
685         uint32 status     = 0;
686         int i;
687         int num_rids = q_u->num_rids1;
688
689         SAMR_R_LOOKUP_NAMES r_u;
690
691         DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
692
693         if (num_rids > MAX_SAM_ENTRIES)
694         {
695                 num_rids = MAX_SAM_ENTRIES;
696                 DEBUG(5,("samr_lookup_names: truncating entries to %d\n", num_rids));
697         }
698
699         for (i = 0; i < num_rids && status == 0; i++)
700         {
701                 fstring name;
702
703                 status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
704
705                 fstrcpy(name, unistrn2(q_u->uni_user_name[i].buffer, q_u->uni_user_name[i].uni_str_len));
706
707                 status = (status != 0x0) ? lookup_user_rid (name, &(rid[i])) : status;
708                 status = (status != 0x0) ? lookup_group_rid(name, &(rid[i])) : status;
709                 status = (status != 0x0) ? lookup_alias_rid(name, &(rid[i])) : status;
710         }
711
712         make_samr_r_lookup_names(&r_u, num_rids, rid, status);
713
714         /* store the response in the SMB stream */
715         samr_io_r_lookup_names("", &r_u, rdata, 0);
716
717         DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
718
719 }
720
721 /*******************************************************************
722  api_samr_lookup_names
723  ********************************************************************/
724 static void api_samr_lookup_names( int uid, prs_struct *data, prs_struct *rdata)
725 {
726         SAMR_Q_LOOKUP_NAMES q_u;
727
728         /* grab the samr lookup names */
729         samr_io_q_lookup_names("", &q_u, data, 0);
730
731         /* construct reply.  always indicate success */
732         samr_reply_lookup_names(&q_u, rdata);
733 }
734
735
736 /*******************************************************************
737  samr_reply_unknown_12
738  ********************************************************************/
739 static void samr_reply_unknown_12(SAMR_Q_UNKNOWN_12 *q_u,
740                                 prs_struct *rdata)
741 {
742         fstring group_names[MAX_SAM_ENTRIES];
743         uint32  group_attrs[MAX_SAM_ENTRIES];
744         uint32 status     = 0;
745         int num_gids = q_u->num_gids1;
746         uint32 pol_idx;
747
748         SAMR_R_UNKNOWN_12 r_u;
749
750         DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
751
752         /* find the policy handle.  open a policy on it. */
753         if (status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->pol))) == -1))
754         {
755                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
756         }
757
758         if (status == 0x0)
759         {
760                 int i;
761                 if (num_gids > MAX_SAM_ENTRIES)
762                 {
763                         num_gids = MAX_SAM_ENTRIES;
764                         DEBUG(5,("samr_unknown_12: truncating entries to %d\n", num_gids));
765                 }
766
767                 for (i = 0; i < num_gids && status == 0; i++)
768                 {
769                         fstrcpy(group_names[i], "dummy group");
770                         group_attrs[i] = 0x2;
771                 }
772         }
773
774         make_samr_r_unknown_12(&r_u, num_gids, group_names, group_attrs, status);
775
776         /* store the response in the SMB stream */
777         samr_io_r_unknown_12("", &r_u, rdata, 0);
778
779         DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
780
781 }
782
783 /*******************************************************************
784  api_samr_unknown_12
785  ********************************************************************/
786 static void api_samr_unknown_12( int uid, prs_struct *data, prs_struct *rdata)
787 {
788         SAMR_Q_UNKNOWN_12 q_u;
789
790         /* grab the samr lookup names */
791         samr_io_q_unknown_12("", &q_u, data, 0);
792
793         /* construct reply.  always indicate success */
794         samr_reply_unknown_12(&q_u, rdata);
795 }
796
797
798 /*******************************************************************
799  samr_reply_open_user
800  ********************************************************************/
801 static void samr_reply_open_user(SAMR_Q_OPEN_USER *q_u,
802                                 prs_struct *rdata,
803                                 int status)
804 {
805         SAMR_R_OPEN_USER r_u;
806         struct smb_passwd *smb_pass;
807         int pol_idx;
808         BOOL pol_open = False;
809
810         /* set up the SAMR open_user response */
811         bzero(&(r_u.user_pol.data), POL_HND_SIZE);
812
813         r_u.status = 0x0;
814
815         /* find the policy handle.  open a policy on it. */
816         if (r_u.status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->domain_pol))) == -1))
817         {
818                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
819         }
820
821         /* get a (unique) handle.  open a policy on it. */
822         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.user_pol))))
823         {
824                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
825         }
826
827         become_root(True);
828         smb_pass = getsmbpwuid(q_u->user_rid);
829         unbecome_root(True);
830
831         /* check that the RID exists in our domain. */
832         if (r_u.status == 0x0 && smb_pass == NULL)
833         {
834                 r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
835         }
836
837         /* associate the RID with the (unique) handle. */
838         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.user_pol), q_u->user_rid))
839         {
840                 /* oh, whoops.  don't know what error message to return, here */
841                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
842         }
843
844         if (r_u.status != 0 && pol_open)
845         {
846                 close_lsa_policy_hnd(&(r_u.user_pol));
847         }
848
849         DEBUG(5,("samr_open_user: %d\n", __LINE__));
850
851         /* store the response in the SMB stream */
852         samr_io_r_open_user("", &r_u, rdata, 0);
853
854         DEBUG(5,("samr_open_user: %d\n", __LINE__));
855
856 }
857
858 /*******************************************************************
859  api_samr_open_user
860  ********************************************************************/
861 static void api_samr_open_user( int uid, prs_struct *data, prs_struct *rdata)
862 {
863         SAMR_Q_OPEN_USER q_u;
864
865         /* grab the samr unknown 22 */
866         samr_io_q_open_user("", &q_u, data, 0);
867
868         /* construct reply.  always indicate success */
869         samr_reply_open_user(&q_u, rdata, 0x0);
870 }
871
872
873 /*************************************************************************
874  get_user_info_21
875  *************************************************************************/
876 static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 rid)
877 {
878         NTTIME dummy_time;
879
880         pstring logon_script;
881         pstring profile_path;
882         pstring home_drive;
883         pstring home_dir;
884         pstring description;
885         pstring workstations;
886         pstring full_name;
887         pstring munged_dialin;
888         pstring unknown_str;
889
890         uint32 r_uid;
891         uint32 r_gid;
892
893         LOGON_HRS hrs;
894         int i;
895
896         struct smb_passwd *smb_pass;
897
898         become_root(True);
899         smb_pass = getsmbpwuid(rid);
900         unbecome_root(True);
901
902         if (smb_pass == NULL)
903         {
904                 return False;
905         }
906
907         DEBUG(3,("User:[%s]\n", smb_pass->smb_name));
908
909         dummy_time.low  = 0xffffffff;
910         dummy_time.high = 0x7fffffff;
911
912         pstrcpy(samlogon_user, smb_pass->smb_name);
913
914         if (samlogon_user[strlen(samlogon_user)-1] != '$')
915         {
916                 if (!name_to_rid(samlogon_user, &r_uid, &r_gid))
917                 {
918                         return False;
919                 }
920
921                 /* XXXX hack to get standard_sub_basic() to use sam logon username */
922                 /* possibly a better way would be to do a become_user() call */
923                 sam_logon_in_ssb = True;
924
925                 pstrcpy(full_name    , "<Full Name>");
926                 pstrcpy(logon_script , lp_logon_script     ());
927                 pstrcpy(profile_path , lp_logon_path       ());
928                 pstrcpy(home_drive   , lp_logon_drive      ());
929                 pstrcpy(home_dir     , lp_logon_home       ());
930                 pstrcpy(description  , "<Description>");
931                 pstrcpy(workstations , "");
932                 pstrcpy(unknown_str  , "");
933                 pstrcpy(munged_dialin, "");
934
935                 sam_logon_in_ssb = False;
936         }
937         else
938         {
939                 r_uid = smb_pass->smb_userid;
940                 r_gid = DOMAIN_GROUP_RID_USERS;
941
942                 pstrcpy(samlogon_user, smb_pass->smb_name);
943
944                 pstrcpy(full_name    , "");
945                 pstrcpy(logon_script , "");
946                 pstrcpy(profile_path , "");
947                 pstrcpy(home_drive   , "");
948                 pstrcpy(home_dir     , "");
949                 pstrcpy(description  , "");
950                 pstrcpy(workstations , "");
951                 pstrcpy(unknown_str  , "");
952                 pstrcpy(munged_dialin, "");
953         }
954
955         hrs.len = 21;
956         for (i = 0; i < hrs.len; i++)
957         {
958                 hrs.hours[i] = 0xff;
959         }
960         make_sam_user_info21(id21,
961
962                            &dummy_time, /* logon_time */
963                            &dummy_time, /* logoff_time */
964                            &dummy_time, /* kickoff_time */
965                            &dummy_time, /* pass_last_set_time */
966                            &dummy_time, /* pass_can_change_time */
967                            &dummy_time, /* pass_must_change_time */
968
969                            samlogon_user, /* user_name */
970                            full_name, /* full_name */
971                            home_dir, /* home_dir */
972                            home_drive, /* dir_drive */
973                            logon_script, /* logon_script */
974                            profile_path, /* profile_path */
975                            description, /* description */
976                            workstations, /* workstations user can log in from */
977                            unknown_str, /* don't know, yet */
978                            munged_dialin, /* dialin info.  contains dialin path and tel no */
979
980                            r_uid, /* RID user_id */
981                            r_gid, /* RID group_id */
982                        smb_pass->acct_ctrl,
983
984                    0x00ffffff, /* unknown_3 */
985                        168, /* divisions per week */
986                            &hrs, /* logon hours */
987                        0x00020000,
988                        0x000004ec);
989
990         return True;
991 }
992
993 /*******************************************************************
994  samr_reply_query_userinfo
995  ********************************************************************/
996 static void samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u,
997                                 prs_struct *rdata)
998 {
999         SAMR_R_QUERY_USERINFO r_u;
1000 #if 0
1001         SAM_USER_INFO_11 id11;
1002 #endif
1003         SAM_USER_INFO_21 id21;
1004         void *info = NULL;
1005
1006         uint32 status = 0x0;
1007         uint32 rid;
1008         int obj_idx;
1009
1010         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1011
1012         /* search for the handle */
1013         if (status == 0x0 && (obj_idx = find_lsa_policy_by_hnd(&(q_u->pol))) == -1)
1014         {
1015                 status = NT_STATUS_INVALID_HANDLE;
1016         }
1017
1018         /* find the user's rid */
1019         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1020         {
1021                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1022         }
1023
1024         /* ok!  user info levels (there are lots: see MSDEV help), off we go... */
1025         if (status == 0x0)
1026         {
1027                 switch (q_u->switch_value)
1028                 {
1029 #if 0
1030 /* whoops - got this wrong.  i think.  or don't understand what's happening. */
1031                         case 0x11:
1032                         {
1033                                 NTTIME expire;
1034                                 info = (void*)&id11;
1035                                 
1036                                 expire.low  = 0xffffffff;
1037                                 expire.high = 0x7fffffff;
1038
1039                                 make_sam_user_info11(&id11, &expire, "BROOKFIELDS$", 0x03ef, 0x201, 0x0080);
1040
1041                                 break;
1042                         }
1043 #endif
1044                         case 21:
1045                         {
1046                                 info = (void*)&id21;
1047 #ifdef USE_LDAP
1048                                 status = ldap_get_user_info_21(&id21, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1049 #else                           
1050                                 status = get_user_info_21(&id21, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1051 #endif
1052                                 break;
1053                         }
1054
1055                         default:
1056                         {
1057                                 status = NT_STATUS_INVALID_INFO_CLASS;
1058
1059                                 break;
1060                         }
1061                 }
1062         }
1063
1064         make_samr_r_query_userinfo(&r_u, q_u->switch_value, info, status);
1065
1066         /* store the response in the SMB stream */
1067         samr_io_r_query_userinfo("", &r_u, rdata, 0);
1068
1069         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1070
1071 }
1072
1073 /*******************************************************************
1074  api_samr_query_userinfo
1075  ********************************************************************/
1076 static void api_samr_query_userinfo( int uid, prs_struct *data, prs_struct *rdata)
1077 {
1078         SAMR_Q_QUERY_USERINFO q_u;
1079
1080         /* grab the samr unknown 24 */
1081         samr_io_q_query_userinfo("", &q_u, data, 0);
1082
1083         /* construct reply.  always indicate success */
1084         samr_reply_query_userinfo(&q_u, rdata);
1085 }
1086
1087
1088 /*******************************************************************
1089  samr_reply_query_usergroups
1090  ********************************************************************/
1091 static void samr_reply_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
1092                                 prs_struct *rdata)
1093 {
1094         SAMR_R_QUERY_USERGROUPS r_u;
1095         uint32 status = 0x0;
1096
1097         struct smb_passwd *smb_pass;
1098         DOM_GID gids[LSA_MAX_GROUPS];
1099         int num_groups = 0;
1100         int pol_idx;
1101         uint32 rid;
1102
1103         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1104
1105         /* find the policy handle.  open a policy on it. */
1106         if (status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->pol))) == -1))
1107         {
1108                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1109         }
1110
1111         /* find the user's rid */
1112         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1113         {
1114                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1115         }
1116
1117         if (status == 0x0)
1118         {
1119                 become_root(True);
1120                 smb_pass = getsmbpwuid(rid);
1121                 unbecome_root(True);
1122
1123                 if (smb_pass == NULL)
1124                 {
1125                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1126                 }
1127         }
1128
1129         if (status == 0x0)
1130         {
1131                 pstring groups;
1132                 get_domain_user_groups(groups, smb_pass->smb_name);
1133                 num_groups = make_dom_gids(groups, gids);
1134         }
1135
1136         /* construct the response.  lkclXXXX: gids are not copied! */
1137         make_samr_r_query_usergroups(&r_u, num_groups, gids, status);
1138
1139         /* store the response in the SMB stream */
1140         samr_io_r_query_usergroups("", &r_u, rdata, 0);
1141
1142         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1143
1144 }
1145
1146 /*******************************************************************
1147  api_samr_query_usergroups
1148  ********************************************************************/
1149 static void api_samr_query_usergroups( int uid, prs_struct *data, prs_struct *rdata)
1150 {
1151         SAMR_Q_QUERY_USERGROUPS q_u;
1152         /* grab the samr unknown 32 */
1153         samr_io_q_query_usergroups("", &q_u, data, 0);
1154
1155         /* construct reply. */
1156         samr_reply_query_usergroups(&q_u, rdata);
1157 }
1158
1159
1160 /*******************************************************************
1161  samr_reply_unknown_32
1162  ********************************************************************/
1163 static void samr_reply_unknown_32(SAMR_Q_UNKNOWN_32 *q_u,
1164                                 prs_struct *rdata,
1165                                 int status)
1166 {
1167         int i;
1168         SAMR_R_UNKNOWN_32 r_u;
1169
1170         /* set up the SAMR unknown_32 response */
1171         bzero(&(r_u.pol.data), POL_HND_SIZE);
1172         if (status == 0)
1173         {
1174                 for (i = 4; i < POL_HND_SIZE; i++)
1175                 {
1176                         r_u.pol.data[i] = i+1;
1177                 }
1178         }
1179
1180         make_dom_rid4(&(r_u.rid4), 0x0030, 0, 0);
1181         r_u.status    = status;
1182
1183         DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1184
1185         /* store the response in the SMB stream */
1186         samr_io_r_unknown_32("", &r_u, rdata, 0);
1187
1188         DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1189
1190 }
1191
1192 /*******************************************************************
1193  api_samr_unknown_32
1194  ********************************************************************/
1195 static void api_samr_unknown_32( int uid, prs_struct *data, prs_struct *rdata)
1196 {
1197         uint32 status = 0;
1198         struct smb_passwd *smb_pass;
1199         fstring mach_acct;
1200
1201         SAMR_Q_UNKNOWN_32 q_u;
1202
1203         /* grab the samr unknown 32 */
1204         samr_io_q_unknown_32("", &q_u, data, 0);
1205
1206         /* find the machine account: tell the caller if it exists.
1207            lkclXXXX i have *no* idea if this is a problem or not
1208            or even if you are supposed to construct a different
1209            reply if the account already exists...
1210          */
1211
1212         fstrcpy(mach_acct, unistrn2(q_u.uni_mach_acct.buffer,
1213                                     q_u.uni_mach_acct.uni_str_len));
1214
1215         become_root(True);
1216         smb_pass = getsmbpwnam(mach_acct);
1217         unbecome_root(True);
1218
1219         if (smb_pass != NULL)
1220         {
1221                 /* machine account exists: say so */
1222                 status = 0xC0000000 | NT_STATUS_USER_EXISTS;
1223         }
1224         else
1225         {
1226                 /* this could cause trouble... */
1227                 status = 0;
1228         }
1229
1230         /* construct reply. */
1231         samr_reply_unknown_32(&q_u, rdata, status);
1232 }
1233
1234
1235 /*******************************************************************
1236  samr_reply_connect
1237  ********************************************************************/
1238 static void samr_reply_connect(SAMR_Q_CONNECT *q_u,
1239                                 prs_struct *rdata)
1240 {
1241         SAMR_R_CONNECT r_u;
1242         BOOL pol_open = False;
1243
1244         /* set up the SAMR connect response */
1245
1246         r_u.status = 0x0;
1247         /* get a (unique) handle.  open a policy on it. */
1248         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1249         {
1250                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1251         }
1252
1253         /* associate the domain SID with the (unique) handle. */
1254         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1255         {
1256                 /* oh, whoops.  don't know what error message to return, here */
1257                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1258         }
1259
1260         if (r_u.status != 0 && pol_open)
1261         {
1262                 close_lsa_policy_hnd(&(r_u.connect_pol));
1263         }
1264
1265         DEBUG(5,("samr_connect: %d\n", __LINE__));
1266
1267         /* store the response in the SMB stream */
1268         samr_io_r_connect("", &r_u, rdata, 0);
1269
1270         DEBUG(5,("samr_connect: %d\n", __LINE__));
1271
1272 }
1273
1274 /*******************************************************************
1275  api_samr_connect
1276  ********************************************************************/
1277 static void api_samr_connect( int uid, prs_struct *data, prs_struct *rdata)
1278 {
1279         SAMR_Q_CONNECT q_u;
1280
1281         /* grab the samr open policy */
1282         samr_io_q_connect("", &q_u, data, 0);
1283
1284         /* construct reply.  always indicate success */
1285         samr_reply_connect(&q_u, rdata);
1286 }
1287
1288 /*******************************************************************
1289  samr_reply_open_alias
1290  ********************************************************************/
1291 static void samr_reply_open_alias(SAMR_Q_OPEN_ALIAS *q_u,
1292                                 prs_struct *rdata)
1293 {
1294         SAMR_R_OPEN_ALIAS r_u;
1295         BOOL pol_open = False;
1296
1297         /* set up the SAMR open_alias response */
1298
1299         r_u.status = 0x0;
1300         /* get a (unique) handle.  open a policy on it. */
1301         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.pol))))
1302         {
1303                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1304         }
1305
1306         /* associate a RID with the (unique) handle. */
1307         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.pol), q_u->rid_alias))
1308         {
1309                 /* oh, whoops.  don't know what error message to return, here */
1310                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1311         }
1312
1313         if (r_u.status != 0 && pol_open)
1314         {
1315                 close_lsa_policy_hnd(&(r_u.pol));
1316         }
1317
1318         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
1319
1320         /* store the response in the SMB stream */
1321         samr_io_r_open_alias("", &r_u, rdata, 0);
1322
1323         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
1324
1325 }
1326
1327 /*******************************************************************
1328  api_samr_open_alias
1329  ********************************************************************/
1330 static void api_samr_open_alias( int uid, prs_struct *data, prs_struct *rdata)
1331                                 
1332 {
1333         SAMR_Q_OPEN_ALIAS q_u;
1334
1335         /* grab the samr open policy */
1336         samr_io_q_open_alias("", &q_u, data, 0);
1337
1338         /* construct reply.  always indicate success */
1339         samr_reply_open_alias(&q_u, rdata);
1340 }
1341
1342 /*******************************************************************
1343  array of \PIPE\samr operations
1344  ********************************************************************/
1345 static struct api_struct api_samr_cmds [] =
1346 {
1347         { "SAMR_CLOSE_HND"        , SAMR_CLOSE_HND        , api_samr_close_hnd        },
1348         { "SAMR_CONNECT"          , SAMR_CONNECT          , api_samr_connect          },
1349         { "SAMR_ENUM_DOM_USERS"   , SAMR_ENUM_DOM_USERS   , api_samr_enum_dom_users   },
1350         { "SAMR_ENUM_DOM_GROUPS"  , SAMR_ENUM_DOM_GROUPS  , api_samr_enum_dom_groups  },
1351         { "SAMR_ENUM_DOM_ALIASES" , SAMR_ENUM_DOM_ALIASES , api_samr_enum_dom_aliases },
1352         { "SAMR_LOOKUP_IDS"       , SAMR_LOOKUP_IDS       , api_samr_lookup_ids       },
1353         { "SAMR_LOOKUP_NAMES"     , SAMR_LOOKUP_NAMES     , api_samr_lookup_names     },
1354         { "SAMR_OPEN_USER"        , SAMR_OPEN_USER        , api_samr_open_user        },
1355         { "SAMR_QUERY_USERINFO"   , SAMR_QUERY_USERINFO   , api_samr_query_userinfo   },
1356         { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
1357         { "SAMR_QUERY_DISPINFO"   , SAMR_QUERY_DISPINFO   , api_samr_query_dispinfo   },
1358         { "SAMR_QUERY_ALIASINFO"  , SAMR_QUERY_ALIASINFO  , api_samr_query_aliasinfo  },
1359         { "SAMR_0x32"             , 0x32                  , api_samr_unknown_32       },
1360         { "SAMR_UNKNOWN_12"       , SAMR_UNKNOWN_12       , api_samr_unknown_12       },
1361         { "SAMR_OPEN_ALIAS"       , SAMR_OPEN_ALIAS       , api_samr_open_alias       },
1362         { "SAMR_OPEN_DOMAIN"      , SAMR_OPEN_DOMAIN      , api_samr_open_domain      },
1363         { "SAMR_UNKNOWN_3"        , SAMR_UNKNOWN_3        , api_samr_unknown_3        },
1364     { NULL                    , 0                     , NULL                      }
1365 };
1366
1367 /*******************************************************************
1368  receives a samr pipe and responds.
1369  ********************************************************************/
1370 BOOL api_samr_rpc(pipes_struct *p, prs_struct *data)
1371 {
1372     return api_rpcTNP(p, "api_samr_rpc", api_samr_cmds, data);
1373 }
1374