7a04d8ec356d0aa47724f02d7be67a1b60425598
[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, int t_idx, uint16 fnum, 
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, t_idx, fnum,
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, t_idx, fnum,
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, t_idx, fnum, &pol_open_user);
64 }
65
66 /****************************************************************************
67 do a SAMR query user info
68 ****************************************************************************/
69 BOOL get_samr_query_userinfo(struct cli_state *cli, int t_idx, uint16 fnum, 
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, t_idx, fnum,
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, t_idx, fnum,
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, t_idx, fnum, &pol_open_user);
98 }
99
100 /****************************************************************************
101 do a SAMR unknown 0x8 command
102 ****************************************************************************/
103 BOOL do_samr_unknown_8(struct cli_state *cli, int t_idx, uint16 fnum, 
104                                 POLICY_HND *domain_pol, uint16 switch_value)
105 {
106         prs_struct data;
107         prs_struct rdata;
108
109         SAMR_Q_UNKNOWN_8 q_e;
110     BOOL valid_un8 = False;
111
112         /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */
113
114         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
115         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
116
117         DEBUG(4,("SAMR Unknown 8 switch:%d\n", switch_value));
118
119         if (domain_pol == NULL || fnum == 0xffff) return False;
120
121         /* store the parameters */
122         make_samr_q_unknown_8(&q_e, domain_pol, switch_value);
123
124         /* turn parameters into data stream */
125         samr_io_q_unknown_8("", &q_e, &data, 0);
126
127         /* send the data on \PIPE\ */
128         if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_UNKNOWN_8, &data, &rdata))
129         {
130 #if 0
131
132                 SAMR_R_UNKNOWN_8 r_e;
133                 BOOL p;
134
135                 samr_io_r_unknown_8("", &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_UNKNOWN_8: %s\n", get_nt_error_msg(r_e.status)));
142                         p = False;
143                 }
144
145                 if (p)
146                 {
147                         valid_un8 = True;
148                 }
149 #endif
150         }
151
152         prs_mem_free(&data   );
153         prs_mem_free(&rdata  );
154
155         return valid_un8;
156 }
157
158 /****************************************************************************
159 do a SAMR enumerate users
160 ****************************************************************************/
161 BOOL do_samr_enum_dom_users(struct cli_state *cli, int t_idx, uint16 fnum, 
162                                 POLICY_HND *pol, uint16 num_entries, uint16 unk_0,
163                                 uint16 acb_mask, uint16 unk_1, uint32 size,
164                                 struct acct_info sam[MAX_SAM_ENTRIES],
165                                 int *num_sam_users)
166 {
167         prs_struct data;
168         prs_struct rdata;
169
170         SAMR_Q_ENUM_DOM_USERS q_e;
171     BOOL valid_pol = False;
172
173         /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */
174
175         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
176         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
177
178         DEBUG(4,("SAMR Enum SAM DB max size:%x\n", size));
179
180         if (pol == NULL || sam == NULL || num_sam_users == NULL || fnum == 0xffff) return False;
181
182         /* store the parameters */
183         make_samr_q_enum_dom_users(&q_e, pol,
184                                    num_entries, unk_0,
185                                    acb_mask, unk_1, size);
186
187         /* turn parameters into data stream */
188         samr_io_q_enum_dom_users("", &q_e, &data, 0);
189
190         /* send the data on \PIPE\ */
191         if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_ENUM_DOM_USERS, &data, &rdata))
192         {
193                 SAMR_R_ENUM_DOM_USERS r_e;
194                 BOOL p;
195
196                 samr_io_r_enum_dom_users("", &r_e, &rdata, 0);
197
198                 p = rdata.offset != 0;
199                 if (p && r_e.status != 0)
200                 {
201                         /* report error code */
202                         DEBUG(0,("SAMR_R_ENUM_DOM_USERS: %s\n", get_nt_error_msg(r_e.status)));
203                         p = False;
204                 }
205
206                 if (p)
207                 {
208                         int i;
209                         int name_idx = 0;
210
211                         *num_sam_users = r_e.num_entries2;
212                         if (*num_sam_users > MAX_SAM_ENTRIES)
213                         {
214                                 *num_sam_users = MAX_SAM_ENTRIES;
215                                 DEBUG(2,("do_samr_enum_dom_users: sam user entries limited to %d\n",
216                                           *num_sam_users));
217                         }
218                         for (i = 0; i < *num_sam_users; i++)
219                         {
220                                 sam[i].smb_userid = r_e.sam[i].rid;
221                                 if (r_e.sam[i].hdr_name.buffer)
222                                 {
223                                         char *acct_name = unistrn2(r_e.uni_acct_name[name_idx].buffer,
224                                                                    r_e.uni_acct_name[name_idx].uni_str_len);
225                                         fstrcpy(sam[i].acct_name, acct_name);
226                                         name_idx++;
227                                 }
228                                 else
229                                 {
230                                         bzero(sam[i].acct_name, sizeof(sam[i].acct_name));
231                                 }
232                                 DEBUG(5,("do_samr_enum_dom_users: idx: %4d rid: %8x acct: %s\n",
233                                           i, sam[i].smb_userid, sam[i].acct_name));
234                         }
235                         valid_pol = True;
236                 }
237         }
238
239         prs_mem_free(&data   );
240         prs_mem_free(&rdata  );
241
242         return valid_pol;
243 }
244
245 /****************************************************************************
246 do a SAMR Connect
247 ****************************************************************************/
248 BOOL do_samr_connect(struct cli_state *cli, int t_idx, uint16 fnum, 
249                                 char *srv_name, uint32 unknown_0,
250                                 POLICY_HND *connect_pol)
251 {
252         prs_struct data;
253         prs_struct rdata;
254
255         SAMR_Q_CONNECT q_o;
256     BOOL valid_pol = False;
257
258         /* create and send a MSRPC command with api SAMR_CONNECT */
259
260         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
261         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
262
263         DEBUG(4,("SAMR Open Policy server:%s undoc value:%x\n",
264                                 srv_name, unknown_0));
265
266         if (srv_name == NULL || connect_pol == NULL || fnum == 0xffff) return False;
267
268         /* store the parameters */
269         make_samr_q_connect(&q_o, srv_name, unknown_0);
270
271         /* turn parameters into data stream */
272         samr_io_q_connect("", &q_o,  &data, 0);
273
274         /* send the data on \PIPE\ */
275         if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_CONNECT, &data, &rdata))
276         {
277                 SAMR_R_CONNECT r_o;
278                 BOOL p;
279
280                 samr_io_r_connect("", &r_o, &rdata, 0);
281                 p = rdata.offset != 0;
282                 
283                 if (p && r_o.status != 0)
284                 {
285                         /* report error code */
286                         DEBUG(0,("SAMR_R_CONNECT: %s\n", get_nt_error_msg(r_o.status)));
287                         p = False;
288                 }
289
290                 if (p)
291                 {
292                         memcpy(connect_pol, &r_o.connect_pol, sizeof(r_o.connect_pol));
293                         valid_pol = True;
294                 }
295         }
296
297         prs_mem_free(&data   );
298         prs_mem_free(&rdata  );
299
300         return valid_pol;
301 }
302
303 /****************************************************************************
304 do a SAMR Open User
305 ****************************************************************************/
306 BOOL do_samr_open_user(struct cli_state *cli, int t_idx, uint16 fnum, 
307                                 POLICY_HND *pol, uint32 unk_0, uint32 rid, 
308                                 POLICY_HND *user_pol)
309 {
310         prs_struct data;
311         prs_struct rdata;
312
313         SAMR_Q_OPEN_USER q_o;
314     BOOL valid_pol = False;
315
316         /* create and send a MSRPC command with api SAMR_OPEN_USER */
317
318         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
319         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
320
321         DEBUG(4,("SAMR Open User.  unk_0: %08x RID:%x\n",
322                   unk_0, rid));
323
324         if (pol == NULL || user_pol == NULL || fnum == 0xffff) return False;
325
326         /* store the parameters */
327         make_samr_q_open_user(&q_o, pol, unk_0, rid);
328
329         /* turn parameters into data stream */
330         samr_io_q_open_user("", &q_o,  &data, 0);
331
332         /* send the data on \PIPE\ */
333         if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_OPEN_USER, &data, &rdata))
334         {
335                 SAMR_R_OPEN_USER r_o;
336                 BOOL p;
337
338                 samr_io_r_open_user("", &r_o, &rdata, 0);
339                 p = rdata.offset != 0;
340                 
341                 if (p && r_o.status != 0)
342                 {
343                         /* report error code */
344                         DEBUG(0,("SAMR_R_OPEN_USER: %s\n", get_nt_error_msg(r_o.status)));
345                         p = False;
346                 }
347
348                 if (p)
349                 {
350                         memcpy(user_pol, &r_o.user_pol, sizeof(r_o.user_pol));
351                         valid_pol = True;
352                 }
353         }
354
355         prs_mem_free(&data   );
356         prs_mem_free(&rdata  );
357
358         return valid_pol;
359 }
360
361 /****************************************************************************
362 do a SAMR Open Domain
363 ****************************************************************************/
364 BOOL do_samr_open_domain(struct cli_state *cli, int t_idx, uint16 fnum, 
365                                 POLICY_HND *connect_pol, uint32 rid, char *sid,
366                                 POLICY_HND *domain_pol)
367 {
368         prs_struct data;
369         prs_struct rdata;
370
371         SAMR_Q_OPEN_DOMAIN q_o;
372     BOOL valid_pol = False;
373
374         /* create and send a MSRPC command with api SAMR_OPEN_DOMAIN */
375
376         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
377         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
378
379         DEBUG(4,("SAMR Open Domain.  SID:%s RID:%x\n", sid, rid));
380
381         if (connect_pol == NULL || sid == NULL || domain_pol == NULL || fnum == 0xffff) return False;
382
383         /* store the parameters */
384         make_samr_q_open_domain(&q_o, connect_pol, rid, sid);
385
386         /* turn parameters into data stream */
387         samr_io_q_open_domain("", &q_o,  &data, 0);
388
389         /* send the data on \PIPE\ */
390         if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_OPEN_DOMAIN, &data, &rdata))
391         {
392                 SAMR_R_OPEN_DOMAIN r_o;
393                 BOOL p;
394
395                 samr_io_r_open_domain("", &r_o, &rdata, 0);
396                 p = rdata.offset != 0;
397
398                 if (p && r_o.status != 0)
399                 {
400                         /* report error code */
401                         DEBUG(0,("SAMR_R_OPEN_DOMAIN: %s\n", get_nt_error_msg(r_o.status)));
402                         p = False;
403                 }
404
405                 if (p)
406                 {
407                         memcpy(domain_pol, &r_o.domain_pol, sizeof(r_o.domain_pol));
408                         valid_pol = True;
409                 }
410         }
411
412         prs_mem_free(&data   );
413         prs_mem_free(&rdata  );
414
415         return valid_pol;
416 }
417
418 /****************************************************************************
419 do a SAMR Query Unknown 12
420 ****************************************************************************/
421 BOOL do_samr_query_unknown_12(struct cli_state *cli, int t_idx, uint16 fnum, 
422                                 POLICY_HND *pol, uint32 rid, uint32 num_gids, uint32 *gids,
423                                 uint32 *num_aliases,
424                                 fstring als_names    [MAX_LOOKUP_SIDS],
425                                 uint32  num_als_users[MAX_LOOKUP_SIDS])
426 {
427         prs_struct data;
428         prs_struct rdata;
429
430         SAMR_Q_UNKNOWN_12 q_o;
431     BOOL valid_query = False;
432
433         /* create and send a MSRPC command with api SAMR_UNKNOWN_12 */
434
435         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
436         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
437
438         DEBUG(4,("SAMR Query Unknown 12.\n"));
439
440         if (pol == NULL || rid == 0 || num_gids == 0 || gids == NULL ||
441             num_aliases == NULL || als_names == NULL || num_als_users == NULL ||
442             fnum == 0xffff) return False;
443
444         /* store the parameters */
445         make_samr_q_unknown_12(&q_o, pol, rid, num_gids, gids);
446
447         /* turn parameters into data stream */
448         samr_io_q_unknown_12("", &q_o,  &data, 0);
449
450         /* send the data on \PIPE\ */
451         if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_UNKNOWN_12, &data, &rdata))
452         {
453                 SAMR_R_UNKNOWN_12 r_o;
454                 BOOL p;
455
456                 samr_io_r_unknown_12("", &r_o, &rdata, 0);
457                 p = rdata.offset != 0;
458                 
459                 if (p && r_o.status != 0)
460                 {
461                         /* report error code */
462                         DEBUG(0,("SAMR_R_UNKNOWN_12: %s\n", get_nt_error_msg(r_o.status)));
463                         p = False;
464                 }
465
466                 if (p)
467                 {
468                         if (r_o.ptr_aliases != 0 && r_o.ptr_als_usrs != 0 &&
469                             r_o.num_als_usrs1 == r_o.num_aliases1)
470                         {
471                                 int i;
472
473                                 valid_query = True;
474                                 *num_aliases = r_o.num_aliases1;
475
476                                 for (i = 0; i < r_o.num_aliases1; i++)
477                                 {
478                                         fstrcpy(als_names[i], unistrn2(r_o.uni_als_name[i].buffer, r_o.uni_als_name[i].uni_str_len));
479                                 }
480                                 for (i = 0; i < r_o.num_als_usrs1; i++)
481                                 {
482                                         num_als_users[i] = r_o.num_als_usrs[i];
483                                 }
484                         }
485                         else if (r_o.ptr_aliases == 0 && r_o.ptr_als_usrs == 0)
486                         {
487                                 valid_query = True;
488                                 *num_aliases = 0;
489                         }
490                         else
491                         {
492                                 p = False;
493                         }
494                 }
495         }
496
497         prs_mem_free(&data   );
498         prs_mem_free(&rdata  );
499
500         return valid_query;
501 }
502
503 /****************************************************************************
504 do a SAMR Query User Groups
505 ****************************************************************************/
506 BOOL do_samr_query_usergroups(struct cli_state *cli, int t_idx, uint16 fnum, 
507                                 POLICY_HND *pol, uint32 *num_groups, DOM_GID *gid)
508 {
509         prs_struct data;
510         prs_struct rdata;
511
512         SAMR_Q_QUERY_USERGROUPS q_o;
513     BOOL valid_query = False;
514
515         /* create and send a MSRPC command with api SAMR_QUERY_USERGROUPS */
516
517         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
518         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
519
520         DEBUG(4,("SAMR Query User Groups.\n"));
521
522         if (pol == NULL || gid == NULL || num_groups == 0|| fnum == 0xffff) return False;
523
524         /* store the parameters */
525         make_samr_q_query_usergroups(&q_o, pol);
526
527         /* turn parameters into data stream */
528         samr_io_q_query_usergroups("", &q_o,  &data, 0);
529
530         /* send the data on \PIPE\ */
531         if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_QUERY_USERGROUPS, &data, &rdata))
532         {
533                 SAMR_R_QUERY_USERGROUPS r_o;
534                 BOOL p;
535
536                 /* get user info */
537                 r_o.gid = gid;
538
539                 samr_io_r_query_usergroups("", &r_o, &rdata, 0);
540                 p = rdata.offset != 0;
541                 
542                 if (p && r_o.status != 0)
543                 {
544                         /* report error code */
545                         DEBUG(0,("SAMR_R_QUERY_USERGROUPS: %s\n", get_nt_error_msg(r_o.status)));
546                         p = False;
547                 }
548
549                 if (p && r_o.ptr_0 != 0)
550                 {
551                         valid_query = True;
552                         *num_groups = r_o.num_entries;
553                 }
554
555         }
556
557         prs_mem_free(&data   );
558         prs_mem_free(&rdata  );
559
560         return valid_query;
561 }
562
563 /****************************************************************************
564 do a SAMR Query User Info
565 ****************************************************************************/
566 BOOL do_samr_query_userinfo(struct cli_state *cli, int t_idx, uint16 fnum, 
567                                 POLICY_HND *pol, uint16 switch_value, void* usr)
568 {
569         prs_struct data;
570         prs_struct rdata;
571
572         SAMR_Q_QUERY_USERINFO q_o;
573     BOOL valid_query = False;
574
575         /* create and send a MSRPC command with api SAMR_QUERY_USERINFO */
576
577         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
578         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
579
580         DEBUG(4,("SAMR Query User Info.  level: %d\n", switch_value));
581
582         if (pol == NULL || usr == NULL || switch_value == 0|| fnum == 0xffff) return False;
583
584         /* store the parameters */
585         make_samr_q_query_userinfo(&q_o, pol, switch_value);
586
587         /* turn parameters into data stream */
588         samr_io_q_query_userinfo("", &q_o,  &data, 0);
589
590         /* send the data on \PIPE\ */
591         if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_QUERY_USERINFO, &data, &rdata))
592         {
593                 SAMR_R_QUERY_USERINFO r_o;
594                 BOOL p;
595
596                 /* get user info */
597                 r_o.info.id = usr;
598
599                 samr_io_r_query_userinfo("", &r_o, &rdata, 0);
600                 p = rdata.offset != 0;
601                 
602                 if (p && r_o.status != 0)
603                 {
604                         /* report error code */
605                         DEBUG(0,("SAMR_R_QUERY_USERINFO: %s\n", get_nt_error_msg(r_o.status)));
606                         p = False;
607                 }
608
609                 if (p && r_o.switch_value != switch_value)
610                 {
611                         DEBUG(0,("SAMR_R_QUERY_USERINFO: received incorrect level %d\n",
612                                   r_o.switch_value));
613                 }
614
615                 if (p && r_o.ptr != 0)
616                 {
617                         valid_query = True;
618                 }
619         }
620
621         prs_mem_free(&data   );
622         prs_mem_free(&rdata  );
623
624         return valid_query;
625 }
626
627 /****************************************************************************
628 do a SAMR Close
629 ****************************************************************************/
630 BOOL do_samr_close(struct cli_state *cli, int t_idx, uint16 fnum, POLICY_HND *hnd)
631 {
632         prs_struct data;
633         prs_struct rdata;
634
635         SAMR_Q_CLOSE_HND q_c;
636     BOOL valid_close = False;
637
638         prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
639         prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
640
641         if (hnd == NULL) return False;
642
643         /* create and send a MSRPC command with api SAMR_CLOSE_HND */
644
645         DEBUG(4,("SAMR Close\n"));
646
647         /* store the parameters */
648         make_samr_q_close_hnd(&q_c, hnd);
649
650         /* turn parameters into data stream */
651         samr_io_q_close_hnd("", &q_c,  &data, 0);
652
653         /* send the data on \PIPE\ */
654         if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_CLOSE_HND, &data, &rdata))
655         {
656                 SAMR_R_CLOSE_HND r_c;
657                 BOOL p;
658
659                 samr_io_r_close_hnd("", &r_c, &rdata, 0);
660                 p = rdata.offset != 0;
661
662                 if (p && r_c.status != 0)
663                 {
664                         /* report error code */
665                         DEBUG(0,("SAMR_CLOSE_HND: %s\n", get_nt_error_msg(r_c.status)));
666                         p = False;
667                 }
668
669                 if (p)
670                 {
671                         /* check that the returned policy handle is all zeros */
672                         int i;
673                         valid_close = True;
674
675                         for (i = 0; i < sizeof(r_c.pol.data); i++)
676                         {
677                                 if (r_c.pol.data[i] != 0)
678                                 {
679                                         valid_close = False;
680                                         break;
681                                 }
682                         }       
683                         if (!valid_close)
684                         {
685                                 DEBUG(0,("SAMR_CLOSE_HND: non-zero handle returned\n"));
686                         }
687                 }
688         }
689
690         prs_mem_free(&data   );
691         prs_mem_free(&rdata  );
692
693         return valid_close;
694 }
695