weekend work. user / group database API.
[samba.git] / source3 / rpc_client / cli_samr.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NT Domain Authentication SMB / MSRPC client
5    Copyright (C) Andrew Tridgell 1994-1997
6    Copyright (C) Luke Kenneth Casson Leighton 1996-1997
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23
24
25 #ifdef SYSLOG
26 #undef SYSLOG
27 #endif
28
29 #include "includes.h"
30 #include "nterr.h"
31
32 extern int DEBUGLEVEL;
33
34
35
36 /****************************************************************************
37 do a SAMR query user groups
38 ****************************************************************************/
39 BOOL get_samr_query_usergroups(struct cli_state *cli, 
40                                 POLICY_HND *pol_open_domain, uint32 user_rid,
41                                 uint32 *num_groups, DOM_GID *gid)
42 {
43         POLICY_HND pol_open_user;
44         if (pol_open_domain == NULL || num_groups == NULL || gid == NULL) return False;
45
46         /* send open domain (on user sid) */
47         if (!do_samr_open_user(cli,
48                                 pol_open_domain,
49                                 0x02011b, user_rid,
50                                 &pol_open_user))
51         {
52                 return False;
53         }
54
55         /* send user groups query */
56         if (!do_samr_query_usergroups(cli,
57                                 &pol_open_user,
58                                 num_groups, gid))
59         {
60                 DEBUG(5,("do_samr_query_usergroups: error in query user groups\n"));
61         }
62
63         return do_samr_close(cli, &pol_open_user);
64 }
65
66 /****************************************************************************
67 do a SAMR query user info
68 ****************************************************************************/
69 BOOL get_samr_query_userinfo(struct cli_state *cli, 
70                                 POLICY_HND *pol_open_domain,
71                                 uint32 info_level,
72                                 uint32 user_rid, SAM_USER_INFO_21 *usr)
73 {
74         POLICY_HND pol_open_user;
75         if (pol_open_domain == NULL || usr == NULL) return False;
76
77         bzero(usr, sizeof(*usr));
78
79         /* send open domain (on user sid) */
80         if (!do_samr_open_user(cli,
81                                 pol_open_domain,
82                                 0x02011b, user_rid,
83                                 &pol_open_user))
84         {
85                 return False;
86         }
87
88         /* send user info query */
89         if (!do_samr_query_userinfo(cli,
90                                 &pol_open_user,
91                                 info_level, (void*)usr))
92         {
93                 DEBUG(5,("do_samr_query_userinfo: error in query user info, level 0x%x\n",
94                           info_level));
95         }
96
97         return do_samr_close(cli, &pol_open_user);
98 }
99
100 /****************************************************************************
101 do a SAMR change user password command
102 ****************************************************************************/
103 BOOL do_samr_chgpasswd_user(struct cli_state *cli,
104                 char *srv_name, char *user_name,
105                 char nt_newpass[516], uchar nt_oldhash[16],
106                 char lm_newpass[516], uchar lm_oldhash[16])
107 {
108         prs_struct data;
109         prs_struct rdata;
110
111         SAMR_Q_CHGPASSWD_USER q_e;
112         BOOL valid_pwc = False;
113
114         /* create and send a MSRPC command with api SAMR_CHGPASSWD_USER */
115
116         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
117         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
118
119         DEBUG(4,("SAMR Change User Password. server:%s username:%s\n",
120                 srv_name, user_name));
121
122         make_samr_q_chgpasswd_user(&q_e, srv_name, user_name,
123                                    nt_newpass, nt_oldhash,
124                                    lm_newpass, lm_oldhash);
125
126         /* turn parameters into data stream */
127         samr_io_q_chgpasswd_user("", &q_e, &data, 0);
128
129         /* send the data on \PIPE\ */
130         if (rpc_api_pipe_req(cli, SAMR_CHGPASSWD_USER, &data, &rdata))
131         {
132                 SAMR_R_CHGPASSWD_USER r_e;
133                 BOOL p;
134
135                 samr_io_r_chgpasswd_user("", &r_e, &rdata, 0);
136
137                 p = rdata.offset != 0;
138                 if (p && r_e.status != 0)
139                 {
140                         /* report error code */
141                         DEBUG(0,("SAMR_R_CHGPASSWD_USER: %s\n", get_nt_error_msg(r_e.status)));
142                         p = False;
143                 }
144
145                 if (p)
146                 {
147                         valid_pwc = True;
148                 }
149         }
150
151         prs_mem_free(&data   );
152         prs_mem_free(&rdata  );
153
154         return valid_pwc;
155 }
156
157 /****************************************************************************
158 do a SAMR unknown 0x38 command
159 ****************************************************************************/
160 BOOL do_samr_unknown_38(struct cli_state *cli, char *srv_name)
161 {
162         prs_struct data;
163         prs_struct rdata;
164
165         SAMR_Q_UNKNOWN_38 q_e;
166         BOOL valid_un8 = False;
167
168         /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */
169
170         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
171         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
172
173         DEBUG(4,("SAMR Unknown 38 server:%s\n", srv_name));
174
175         make_samr_q_unknown_38(&q_e, srv_name);
176
177         /* turn parameters into data stream */
178         samr_io_q_unknown_38("", &q_e, &data, 0);
179
180         /* send the data on \PIPE\ */
181         if (rpc_api_pipe_req(cli, SAMR_UNKNOWN_38, &data, &rdata))
182         {
183                 SAMR_R_UNKNOWN_38 r_e;
184                 BOOL p;
185
186                 samr_io_r_unknown_38("", &r_e, &rdata, 0);
187
188                 p = rdata.offset != 0;
189 #if 0
190                 if (p && r_e.status != 0)
191                 {
192                         /* report error code */
193                         DEBUG(0,("SAMR_R_UNKNOWN_38: %s\n", get_nt_error_msg(r_e.status)));
194                         p = False;
195                 }
196 #endif
197                 if (p)
198                 {
199                         valid_un8 = True;
200                 }
201         }
202
203         prs_mem_free(&data   );
204         prs_mem_free(&rdata  );
205
206         return valid_un8;
207 }
208
209 /****************************************************************************
210 do a SAMR unknown 0x8 command
211 ****************************************************************************/
212 BOOL do_samr_query_dom_info(struct cli_state *cli, 
213                                 POLICY_HND *domain_pol, uint16 switch_value)
214 {
215         prs_struct data;
216         prs_struct rdata;
217
218         SAMR_Q_QUERY_DOMAIN_INFO q_e;
219         BOOL valid_un8 = False;
220
221         /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */
222
223         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
224         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
225
226         DEBUG(4,("SAMR Unknown 8 switch:%d\n", switch_value));
227
228         if (domain_pol == NULL) return False;
229
230         /* store the parameters */
231         make_samr_q_query_dom_info(&q_e, domain_pol, switch_value);
232
233         /* turn parameters into data stream */
234         samr_io_q_query_dom_info("", &q_e, &data, 0);
235
236         /* send the data on \PIPE\ */
237         if (rpc_api_pipe_req(cli, SAMR_QUERY_DOMAIN_INFO, &data, &rdata))
238         {
239 #if 0
240                 SAMR_R_QUERY_DOMAIN_INFO r_e;
241                 BOOL p;
242
243                 samr_io_r_query_dom_info("", &r_e, &rdata, 0);
244
245                 p = rdata.offset != 0;
246                 if (p && r_e.status != 0)
247                 {
248                         /* report error code */
249                         DEBUG(0,("SAMR_R_QUERY_DOMAIN_INFO: %s\n", get_nt_error_msg(r_e.status)));
250                         p = False;
251                 }
252
253                 if (p)
254                 {
255                         valid_un8 = True;
256                 }
257 #endif
258         }
259
260         prs_mem_free(&data   );
261         prs_mem_free(&rdata  );
262
263         return valid_un8;
264 }
265
266 /****************************************************************************
267 do a SAMR enumerate users
268 ****************************************************************************/
269 BOOL do_samr_enum_dom_users(struct cli_state *cli, 
270                                 POLICY_HND *pol, uint16 num_entries, uint16 unk_0,
271                                 uint16 acb_mask, uint16 unk_1, uint32 size,
272                                 struct acct_info **sam,
273                                 int *num_sam_users)
274 {
275         prs_struct data;
276         prs_struct rdata;
277
278         SAMR_Q_ENUM_DOM_USERS q_e;
279     BOOL valid_pol = False;
280
281         /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */
282
283         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
284         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
285
286         DEBUG(4,("SAMR Enum SAM DB max size:%x\n", size));
287
288         if (pol == NULL || num_sam_users == NULL) return False;
289
290         /* store the parameters */
291         make_samr_q_enum_dom_users(&q_e, pol,
292                                    num_entries, unk_0,
293                                    acb_mask, unk_1, size);
294
295         /* turn parameters into data stream */
296         samr_io_q_enum_dom_users("", &q_e, &data, 0);
297
298         /* send the data on \PIPE\ */
299         if (rpc_api_pipe_req(cli, SAMR_ENUM_DOM_USERS, &data, &rdata))
300         {
301                 SAMR_R_ENUM_DOM_USERS r_e;
302                 BOOL p;
303
304                 samr_io_r_enum_dom_users("", &r_e, &rdata, 0);
305
306                 p = rdata.offset != 0;
307                 if (p && r_e.status != 0)
308                 {
309                         /* report error code */
310                         DEBUG(0,("SAMR_R_ENUM_DOM_USERS: %s\n", get_nt_error_msg(r_e.status)));
311                         p = False;
312                 }
313
314                 if (p)
315                 {
316                         int i;
317                         int name_idx = 0;
318
319                         *num_sam_users = r_e.num_entries2;
320                         if (*num_sam_users > MAX_SAM_ENTRIES)
321                         {
322                                 *num_sam_users = MAX_SAM_ENTRIES;
323                                 DEBUG(2,("do_samr_enum_dom_users: sam user entries limited to %d\n",
324                                           *num_sam_users));
325                         }
326
327                         *sam = (struct acct_info*) malloc(sizeof(struct acct_info) * (*num_sam_users));
328                                     
329                         if ((*sam) == NULL)
330                         {
331                                 *num_sam_users = 0;
332                         }
333
334                         for (i = 0; i < *num_sam_users; i++)
335                         {
336
337                                 (*sam)[i].user_rid = r_e.sam[i].rid;
338                                 if (r_e.sam[i].hdr_name.buffer)
339                                 {
340                                         char *acct_name = unistrn2(r_e.uni_acct_name[name_idx].buffer,
341                                                                    r_e.uni_acct_name[name_idx].uni_str_len);
342                                         fstrcpy((*sam)[i].acct_name, acct_name);
343                                         name_idx++;
344                                 }
345                                 else
346                                 {
347                                         bzero((*sam)[i].acct_name, sizeof((*sam)[i].acct_name));
348                                 }
349                                 DEBUG(5,("do_samr_enum_dom_users: idx: %4d rid: %8x acct: %s\n",
350                                           i, (*sam)[i].user_rid, (*sam)[i].acct_name));
351                         }
352                         valid_pol = True;
353                 }
354         }
355
356         prs_mem_free(&data   );
357         prs_mem_free(&rdata  );
358
359         return valid_pol;
360 }
361
362 /****************************************************************************
363 do a SAMR Connect
364 ****************************************************************************/
365 BOOL do_samr_connect(struct cli_state *cli, 
366                                 char *srv_name, uint32 unknown_0,
367                                 POLICY_HND *connect_pol)
368 {
369         prs_struct data;
370         prs_struct rdata;
371
372         SAMR_Q_CONNECT q_o;
373     BOOL valid_pol = False;
374
375         /* create and send a MSRPC command with api SAMR_CONNECT */
376
377         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
378         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
379
380         DEBUG(4,("SAMR Open Policy server:%s undoc value:%x\n",
381                                 srv_name, unknown_0));
382
383         if (srv_name == NULL || connect_pol == NULL) return False;
384
385         /* store the parameters */
386         make_samr_q_connect(&q_o, srv_name, unknown_0);
387
388         /* turn parameters into data stream */
389         samr_io_q_connect("", &q_o,  &data, 0);
390
391         /* send the data on \PIPE\ */
392         if (rpc_api_pipe_req(cli, SAMR_CONNECT, &data, &rdata))
393         {
394                 SAMR_R_CONNECT r_o;
395                 BOOL p;
396
397                 samr_io_r_connect("", &r_o, &rdata, 0);
398                 p = rdata.offset != 0;
399                 
400                 if (p && r_o.status != 0)
401                 {
402                         /* report error code */
403                         DEBUG(0,("SAMR_R_CONNECT: %s\n", get_nt_error_msg(r_o.status)));
404                         p = False;
405                 }
406
407                 if (p)
408                 {
409                         memcpy(connect_pol, &r_o.connect_pol, sizeof(r_o.connect_pol));
410                         valid_pol = True;
411                 }
412         }
413
414         prs_mem_free(&data   );
415         prs_mem_free(&rdata  );
416
417         return valid_pol;
418 }
419
420 /****************************************************************************
421 do a SAMR Open User
422 ****************************************************************************/
423 BOOL do_samr_open_user(struct cli_state *cli, 
424                                 POLICY_HND *pol, uint32 unk_0, uint32 rid, 
425                                 POLICY_HND *user_pol)
426 {
427         prs_struct data;
428         prs_struct rdata;
429
430         SAMR_Q_OPEN_USER q_o;
431     BOOL valid_pol = False;
432
433         /* create and send a MSRPC command with api SAMR_OPEN_USER */
434
435         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
436         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
437
438         DEBUG(4,("SAMR Open User.  unk_0: %08x RID:%x\n",
439                   unk_0, rid));
440
441         if (pol == NULL || user_pol == NULL) return False;
442
443         /* store the parameters */
444         make_samr_q_open_user(&q_o, pol, unk_0, rid);
445
446         /* turn parameters into data stream */
447         samr_io_q_open_user("", &q_o,  &data, 0);
448
449         /* send the data on \PIPE\ */
450         if (rpc_api_pipe_req(cli, SAMR_OPEN_USER, &data, &rdata))
451         {
452                 SAMR_R_OPEN_USER r_o;
453                 BOOL p;
454
455                 samr_io_r_open_user("", &r_o, &rdata, 0);
456                 p = rdata.offset != 0;
457                 
458                 if (p && r_o.status != 0)
459                 {
460                         /* report error code */
461                         DEBUG(0,("SAMR_R_OPEN_USER: %s\n", get_nt_error_msg(r_o.status)));
462                         p = False;
463                 }
464
465                 if (p)
466                 {
467                         memcpy(user_pol, &r_o.user_pol, sizeof(r_o.user_pol));
468                         valid_pol = True;
469                 }
470         }
471
472         prs_mem_free(&data   );
473         prs_mem_free(&rdata  );
474
475         return valid_pol;
476 }
477
478 /****************************************************************************
479 do a SAMR Open Domain
480 ****************************************************************************/
481 BOOL do_samr_open_domain(struct cli_state *cli, 
482                                 POLICY_HND *connect_pol, uint32 rid, DOM_SID *sid,
483                                 POLICY_HND *domain_pol)
484 {
485         pstring sid_str;
486         prs_struct data;
487         prs_struct rdata;
488
489         SAMR_Q_OPEN_DOMAIN q_o;
490         BOOL valid_pol = False;
491
492         /* create and send a MSRPC command with api SAMR_OPEN_DOMAIN */
493
494         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
495         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
496
497         sid_to_string(sid_str, sid);
498         DEBUG(4,("SAMR Open Domain.  SID:%s RID:%x\n", sid_str, rid));
499
500         if (connect_pol == NULL || sid == NULL || domain_pol == NULL) return False;
501
502         /* store the parameters */
503         make_samr_q_open_domain(&q_o, connect_pol, rid, sid);
504
505         /* turn parameters into data stream */
506         samr_io_q_open_domain("", &q_o,  &data, 0);
507
508         /* send the data on \PIPE\ */
509         if (rpc_api_pipe_req(cli, SAMR_OPEN_DOMAIN, &data, &rdata))
510         {
511                 SAMR_R_OPEN_DOMAIN r_o;
512                 BOOL p;
513
514                 samr_io_r_open_domain("", &r_o, &rdata, 0);
515                 p = rdata.offset != 0;
516
517                 if (p && r_o.status != 0)
518                 {
519                         /* report error code */
520                         DEBUG(0,("SAMR_R_OPEN_DOMAIN: %s\n", get_nt_error_msg(r_o.status)));
521                         p = False;
522                 }
523
524                 if (p)
525                 {
526                         memcpy(domain_pol, &r_o.domain_pol, sizeof(r_o.domain_pol));
527                         valid_pol = True;
528                 }
529         }
530
531         prs_mem_free(&data   );
532         prs_mem_free(&rdata  );
533
534         return valid_pol;
535 }
536
537 /****************************************************************************
538 do a SAMR Query Unknown 12
539 ****************************************************************************/
540 BOOL do_samr_query_unknown_12(struct cli_state *cli, 
541                                 POLICY_HND *pol, uint32 rid, uint32 num_gids, uint32 *gids,
542                                 uint32 *num_aliases,
543                                 fstring als_names    [MAX_LOOKUP_SIDS],
544                                 uint32  num_als_users[MAX_LOOKUP_SIDS])
545 {
546         prs_struct data;
547         prs_struct rdata;
548
549         SAMR_Q_UNKNOWN_12 q_o;
550     BOOL valid_query = False;
551
552         /* create and send a MSRPC command with api SAMR_UNKNOWN_12 */
553
554         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
555         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
556
557         DEBUG(4,("SAMR Query Unknown 12.\n"));
558
559         if (pol == NULL || rid == 0 || num_gids == 0 || gids == NULL ||
560             num_aliases == NULL || als_names == NULL || num_als_users == NULL ) return False;
561
562         /* store the parameters */
563         make_samr_q_unknown_12(&q_o, pol, rid, num_gids, gids);
564
565         /* turn parameters into data stream */
566         samr_io_q_unknown_12("", &q_o,  &data, 0);
567
568         /* send the data on \PIPE\ */
569         if (rpc_api_pipe_req(cli, SAMR_UNKNOWN_12, &data, &rdata))
570         {
571                 SAMR_R_UNKNOWN_12 r_o;
572                 BOOL p;
573
574                 samr_io_r_unknown_12("", &r_o, &rdata, 0);
575                 p = rdata.offset != 0;
576                 
577                 if (p && r_o.status != 0)
578                 {
579                         /* report error code */
580                         DEBUG(0,("SAMR_R_UNKNOWN_12: %s\n", get_nt_error_msg(r_o.status)));
581                         p = False;
582                 }
583
584                 if (p)
585                 {
586                         if (r_o.ptr_aliases != 0 && r_o.ptr_als_usrs != 0 &&
587                             r_o.num_als_usrs1 == r_o.num_aliases1)
588                         {
589                                 int i;
590
591                                 valid_query = True;
592                                 *num_aliases = r_o.num_aliases1;
593
594                                 for (i = 0; i < r_o.num_aliases1; i++)
595                                 {
596                                         fstrcpy(als_names[i], unistrn2(r_o.uni_als_name[i].buffer, r_o.uni_als_name[i].uni_str_len));
597                                 }
598                                 for (i = 0; i < r_o.num_als_usrs1; i++)
599                                 {
600                                         num_als_users[i] = r_o.num_als_usrs[i];
601                                 }
602                         }
603                         else if (r_o.ptr_aliases == 0 && r_o.ptr_als_usrs == 0)
604                         {
605                                 valid_query = True;
606                                 *num_aliases = 0;
607                         }
608                         else
609                         {
610                                 p = False;
611                         }
612                 }
613         }
614
615         prs_mem_free(&data   );
616         prs_mem_free(&rdata  );
617
618         return valid_query;
619 }
620
621 /****************************************************************************
622 do a SAMR Query User Aliases
623 ****************************************************************************/
624 BOOL do_samr_query_useraliases(struct cli_state *cli, 
625                                 POLICY_HND *pol, DOM_SID *sid,
626                                 uint32 *num_aliases, uint32 *rid)
627 {
628         prs_struct data;
629         prs_struct rdata;
630
631         SAMR_Q_QUERY_USERALIASES q_o;
632         BOOL valid_query = False;
633
634         /* create and send a MSRPC command with api SAMR_QUERY_USERALIASES */
635
636         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
637         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
638
639         DEBUG(4,("SAMR Query User Aliases.\n"));
640
641         if (pol == NULL || sid == NULL || rid == NULL || num_aliases == 0) return False;
642
643         /* store the parameters */
644         make_samr_q_query_useraliases(&q_o, pol, sid);
645
646         /* turn parameters into data stream */
647         samr_io_q_query_useraliases("", &q_o,  &data, 0);
648
649         /* send the data on \PIPE\ */
650         if (rpc_api_pipe_req(cli, SAMR_QUERY_USERALIASES, &data, &rdata))
651         {
652                 SAMR_R_QUERY_USERALIASES r_o;
653                 BOOL p;
654
655                 /* get user info */
656                 r_o.rid = rid;
657
658                 samr_io_r_query_useraliases("", &r_o, &rdata, 0);
659                 p = rdata.offset != 0;
660                 
661                 if (p && r_o.status != 0)
662                 {
663                         /* report error code */
664                         DEBUG(0,("SAMR_R_QUERY_USERALIASES: %s\n", get_nt_error_msg(r_o.status)));
665                         p = False;
666                 }
667
668                 if (p && r_o.ptr != 0)
669                 {
670                         valid_query = True;
671                         *num_aliases = r_o.num_entries;
672                 }
673
674         }
675
676         prs_mem_free(&data   );
677         prs_mem_free(&rdata  );
678
679         return valid_query;
680 }
681
682 /****************************************************************************
683 do a SAMR Query User Groups
684 ****************************************************************************/
685 BOOL do_samr_query_usergroups(struct cli_state *cli, 
686                                 POLICY_HND *pol, uint32 *num_groups, DOM_GID *gid)
687 {
688         prs_struct data;
689         prs_struct rdata;
690
691         SAMR_Q_QUERY_USERGROUPS q_o;
692         BOOL valid_query = False;
693
694         /* create and send a MSRPC command with api SAMR_QUERY_USERGROUPS */
695
696         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
697         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
698
699         DEBUG(4,("SAMR Query User Groups.\n"));
700
701         if (pol == NULL || gid == NULL || num_groups == 0) return False;
702
703         /* store the parameters */
704         make_samr_q_query_usergroups(&q_o, pol);
705
706         /* turn parameters into data stream */
707         samr_io_q_query_usergroups("", &q_o,  &data, 0);
708
709         /* send the data on \PIPE\ */
710         if (rpc_api_pipe_req(cli, SAMR_QUERY_USERGROUPS, &data, &rdata))
711         {
712                 SAMR_R_QUERY_USERGROUPS r_o;
713                 BOOL p;
714
715                 /* get user info */
716                 r_o.gid = gid;
717
718                 samr_io_r_query_usergroups("", &r_o, &rdata, 0);
719                 p = rdata.offset != 0;
720                 
721                 if (p && r_o.status != 0)
722                 {
723                         /* report error code */
724                         DEBUG(0,("SAMR_R_QUERY_USERGROUPS: %s\n", get_nt_error_msg(r_o.status)));
725                         p = False;
726                 }
727
728                 if (p && r_o.ptr_0 != 0)
729                 {
730                         valid_query = True;
731                         *num_groups = r_o.num_entries;
732                 }
733
734         }
735
736         prs_mem_free(&data   );
737         prs_mem_free(&rdata  );
738
739         return valid_query;
740 }
741
742 /****************************************************************************
743 do a SAMR Query User Info
744 ****************************************************************************/
745 BOOL do_samr_query_userinfo(struct cli_state *cli, 
746                                 POLICY_HND *pol, uint16 switch_value, void* usr)
747 {
748         prs_struct data;
749         prs_struct rdata;
750
751         SAMR_Q_QUERY_USERINFO q_o;
752     BOOL valid_query = False;
753
754         /* create and send a MSRPC command with api SAMR_QUERY_USERINFO */
755
756         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
757         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
758
759         DEBUG(4,("SAMR Query User Info.  level: %d\n", switch_value));
760
761         if (pol == NULL || usr == NULL || switch_value == 0) return False;
762
763         /* store the parameters */
764         make_samr_q_query_userinfo(&q_o, pol, switch_value);
765
766         /* turn parameters into data stream */
767         samr_io_q_query_userinfo("", &q_o,  &data, 0);
768
769         /* send the data on \PIPE\ */
770         if (rpc_api_pipe_req(cli, SAMR_QUERY_USERINFO, &data, &rdata))
771         {
772                 SAMR_R_QUERY_USERINFO r_o;
773                 BOOL p;
774
775                 /* get user info */
776                 r_o.info.id = usr;
777
778                 samr_io_r_query_userinfo("", &r_o, &rdata, 0);
779                 p = rdata.offset != 0;
780                 
781                 if (p && r_o.status != 0)
782                 {
783                         /* report error code */
784                         DEBUG(0,("SAMR_R_QUERY_USERINFO: %s\n", get_nt_error_msg(r_o.status)));
785                         p = False;
786                 }
787
788                 if (p && r_o.switch_value != switch_value)
789                 {
790                         DEBUG(0,("SAMR_R_QUERY_USERINFO: received incorrect level %d\n",
791                                   r_o.switch_value));
792                 }
793
794                 if (p && r_o.ptr != 0)
795                 {
796                         valid_query = True;
797                 }
798         }
799
800         prs_mem_free(&data   );
801         prs_mem_free(&rdata  );
802
803         return valid_query;
804 }
805
806 /****************************************************************************
807 do a SAMR Close
808 ****************************************************************************/
809 BOOL do_samr_close(struct cli_state *cli, POLICY_HND *hnd)
810 {
811         prs_struct data;
812         prs_struct rdata;
813
814         SAMR_Q_CLOSE_HND q_c;
815     BOOL valid_close = False;
816
817         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
818         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
819
820         if (hnd == NULL) return False;
821
822         /* create and send a MSRPC command with api SAMR_CLOSE_HND */
823
824         DEBUG(4,("SAMR Close\n"));
825
826         /* store the parameters */
827         make_samr_q_close_hnd(&q_c, hnd);
828
829         /* turn parameters into data stream */
830         samr_io_q_close_hnd("", &q_c,  &data, 0);
831
832         /* send the data on \PIPE\ */
833         if (rpc_api_pipe_req(cli, SAMR_CLOSE_HND, &data, &rdata))
834         {
835                 SAMR_R_CLOSE_HND r_c;
836                 BOOL p;
837
838                 samr_io_r_close_hnd("", &r_c, &rdata, 0);
839                 p = rdata.offset != 0;
840
841                 if (p && r_c.status != 0)
842                 {
843                         /* report error code */
844                         DEBUG(0,("SAMR_CLOSE_HND: %s\n", get_nt_error_msg(r_c.status)));
845                         p = False;
846                 }
847
848                 if (p)
849                 {
850                         /* check that the returned policy handle is all zeros */
851                         int i;
852                         valid_close = True;
853
854                         for (i = 0; i < sizeof(r_c.pol.data); i++)
855                         {
856                                 if (r_c.pol.data[i] != 0)
857                                 {
858                                         valid_close = False;
859                                         break;
860                                 }
861                         }       
862                         if (!valid_close)
863                         {
864                                 DEBUG(0,("SAMR_CLOSE_HND: non-zero handle returned\n"));
865                         }
866                 }
867         }
868
869         prs_mem_free(&data   );
870         prs_mem_free(&rdata  );
871
872         return valid_close;
873 }
874