2 Unix SMB/Netbios implementation.
4 NT Domain Authentication SMB / MSRPC client
5 Copyright (C) Andrew Tridgell 1994-1997
6 Copyright (C) Luke Kenneth Casson Leighton 1996-1997
7 Copyright (C) Jeremy Allison 1999.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 extern int DEBUGLEVEL;
34 /****************************************************************************
35 do a SAMR query user groups
36 ****************************************************************************/
37 BOOL get_samr_query_usergroups(struct cli_state *cli,
38 POLICY_HND *pol_open_domain, uint32 user_rid,
39 uint32 *num_groups, DOM_GID *gid)
41 POLICY_HND pol_open_user;
42 if (pol_open_domain == NULL || num_groups == NULL || gid == NULL)
45 /* send open domain (on user sid) */
46 if (!do_samr_open_user(cli,
54 /* send user groups query */
55 if (!do_samr_query_usergroups(cli,
59 DEBUG(5,("do_samr_query_usergroups: error in query user groups\n"));
62 return do_samr_close(cli, &pol_open_user);
66 /* DOES NOT COMPILE WITH THE NEW SAMR PARSE CODE. JRA. */
68 /****************************************************************************
69 do a SAMR query user info
70 ****************************************************************************/
71 BOOL get_samr_query_userinfo(struct cli_state *cli,
72 POLICY_HND *pol_open_domain,
74 uint32 user_rid, SAM_USER_INFO_21 *usr)
76 POLICY_HND pol_open_user;
77 if (pol_open_domain == NULL || usr == NULL)
80 memset((char *)usr, '\0', sizeof(*usr));
82 /* send open domain (on user sid) */
83 if (!do_samr_open_user(cli,
91 /* send user info query */
92 if (!do_samr_query_userinfo(cli,
94 info_level, (void*)usr))
96 DEBUG(5,("do_samr_query_userinfo: error in query user info, level 0x%x\n",
100 return do_samr_close(cli, &pol_open_user);
104 /****************************************************************************
105 do a SAMR change user password command
106 ****************************************************************************/
107 BOOL do_samr_chgpasswd_user(struct cli_state *cli,
108 char *srv_name, char *user_name,
109 char nt_newpass[516], uchar nt_oldhash[16],
110 char lm_newpass[516], uchar lm_oldhash[16])
114 SAMR_Q_CHGPASSWD_USER q_e;
115 SAMR_R_CHGPASSWD_USER r_e;
117 /* create and send a MSRPC command with api SAMR_CHGPASSWD_USER */
119 prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
120 prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);
122 DEBUG(4,("SAMR Change User Password. server:%s username:%s\n",
123 srv_name, user_name));
125 init_samr_q_chgpasswd_user(&q_e, srv_name, user_name,
126 nt_newpass, nt_oldhash,
127 lm_newpass, lm_oldhash);
129 /* turn parameters into data stream */
130 if(!samr_io_q_chgpasswd_user("", &q_e, &data, 0)) {
132 prs_mem_free(&rdata);
136 /* send the data on \PIPE\ */
137 if (!rpc_api_pipe_req(cli, SAMR_CHGPASSWD_USER, &data, &rdata)) {
139 prs_mem_free(&rdata);
145 if(!samr_io_r_chgpasswd_user("", &r_e, &rdata, 0)) {
146 prs_mem_free(&rdata);
150 if (r_e.status != 0) {
151 /* report error code */
152 DEBUG(0,("SAMR_R_CHGPASSWD_USER: %s\n", get_nt_error_msg(r_e.status)));
153 prs_mem_free(&rdata);
157 prs_mem_free(&rdata);
164 /* CURRENTLY THIS DOESN'T COMPILE AND IS NOT USED ANYWHERE. JRA. */
166 /****************************************************************************
167 do a SAMR unknown 0x38 command
168 ****************************************************************************/
169 BOOL do_samr_unknown_38(struct cli_state *cli, char *srv_name)
174 SAMR_Q_UNKNOWN_38 q_e;
175 SAMR_R_UNKNOWN_38 r_e;
177 /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */
179 prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
180 prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);
182 DEBUG(4,("SAMR Unknown 38 server:%s\n", srv_name));
184 init_samr_q_unknown_38(&q_e, srv_name);
186 /* turn parameters into data stream */
187 if(!samr_io_q_unknown_38("", &q_e, &data, 0)) {
189 prs_mem_free(&rdata);
193 /* send the data on \PIPE\ */
194 if (!rpc_api_pipe_req(cli, SAMR_UNKNOWN_38, &data, &rdata)) {
196 prs_mem_free(&rdata);
202 if(!samr_io_r_unknown_38("", &r_e, &rdata, 0)) {
203 prs_mem_free(&rdata);
207 if (r_e.status != 0) {
208 /* report error code */
209 DEBUG(0,("SAMR_R_UNKNOWN_38: %s\n", get_nt_error_msg(r_e.status)));
210 prs_mem_free(&rdata);
214 prs_mem_free(&rdata);
220 /****************************************************************************
221 do a SAMR unknown 0x8 command
222 ****************************************************************************/
223 BOOL do_samr_query_dom_info(struct cli_state *cli,
224 POLICY_HND *domain_pol, uint16 switch_value)
228 SAMR_Q_QUERY_DOMAIN_INFO q_e;
229 SAMR_R_QUERY_DOMAIN_INFO r_e;
231 if (domain_pol == NULL)
234 /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */
236 prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
237 prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);
239 DEBUG(4,("SAMR Unknown 8 switch:%d\n", switch_value));
241 /* store the parameters */
242 init_samr_q_query_dom_info(&q_e, domain_pol, switch_value);
244 /* turn parameters into data stream */
245 if(!samr_io_q_query_dom_info("", &q_e, &data, 0)) {
247 prs_mem_free(&rdata);
251 /* send the data on \PIPE\ */
252 if (!rpc_api_pipe_req(cli, SAMR_QUERY_DOMAIN_INFO, &data, &rdata)) {
254 prs_mem_free(&rdata);
260 if(!samr_io_r_query_dom_info("", &r_e, &rdata, 0)) {
261 prs_mem_free(&rdata);
265 if (r_e.status != 0) {
266 /* report error code */
267 DEBUG(0,("SAMR_R_QUERY_DOMAIN_INFO: %s\n", get_nt_error_msg(r_e.status)));
268 prs_mem_free(&rdata);
272 prs_mem_free(&rdata);
279 /* CURRENTLY DOESN'T COMPILE WITH THE NEW SAMR PARSE CODE. JRA */
281 /****************************************************************************
282 do a SAMR enumerate users
283 ****************************************************************************/
284 BOOL do_samr_enum_dom_users(struct cli_state *cli,
285 POLICY_HND *pol, uint16 num_entries, uint16 unk_0,
286 uint16 acb_mask, uint16 unk_1, uint32 size,
287 struct acct_info **sam,
292 SAMR_Q_ENUM_DOM_USERS q_e;
293 SAMR_R_ENUM_DOM_USERS r_e;
297 if (pol == NULL || num_sam_users == NULL)
300 /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */
302 prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
303 prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);
305 DEBUG(4,("SAMR Enum SAM DB max size:%x\n", size));
307 /* store the parameters */
308 init_samr_q_enum_dom_users(&q_e, pol,
310 acb_mask, unk_1, size);
312 /* turn parameters into data stream */
313 if(!samr_io_q_enum_dom_users("", &q_e, &data, 0)) {
315 prs_mem_free(&rdata);
319 /* send the data on \PIPE\ */
320 if (!rpc_api_pipe_req(cli, SAMR_ENUM_DOM_USERS, &data, &rdata)) {
322 prs_mem_free(&rdata);
328 if(!samr_io_r_enum_dom_users("", &r_e, &rdata, 0)) {
329 prs_mem_free(&rdata);
333 if (r_e.status != 0) {
334 /* report error code */
335 DEBUG(0,("SAMR_R_ENUM_DOM_USERS: %s\n", get_nt_error_msg(r_e.status)));
336 prs_mem_free(&rdata);
340 *num_sam_users = r_e.num_entries2;
341 if (*num_sam_users > MAX_SAM_ENTRIES) {
342 *num_sam_users = MAX_SAM_ENTRIES;
343 DEBUG(2,("do_samr_enum_dom_users: sam user entries limited to %d\n",
347 *sam = (struct acct_info*) malloc(sizeof(struct acct_info) * (*num_sam_users));
352 for (i = 0; i < *num_sam_users; i++) {
353 (*sam)[i].smb_userid = r_e.sam[i].rid;
354 if (r_e.sam[i].hdr_name.buffer) {
355 char *acct_name = dos_unistrn2(r_e.uni_acct_name[name_idx].buffer,
356 r_e.uni_acct_name[name_idx].uni_str_len);
357 fstrcpy((*sam)[i].acct_name, acct_name);
360 memset((char *)(*sam)[i].acct_name, '\0', sizeof((*sam)[i].acct_name));
363 DEBUG(5,("do_samr_enum_dom_users: idx: %4d rid: %8x acct: %s\n",
364 i, (*sam)[i].smb_userid, (*sam)[i].acct_name));
367 prs_mem_free(&rdata );
373 /****************************************************************************
375 ****************************************************************************/
376 BOOL do_samr_connect(struct cli_state *cli,
377 char *srv_name, uint32 unknown_0,
378 POLICY_HND *connect_pol)
385 if (srv_name == NULL || connect_pol == NULL)
388 /* create and send a MSRPC command with api SAMR_CONNECT */
390 prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
391 prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);
393 DEBUG(4,("SAMR Open Policy server:%s undoc value:%x\n",
394 srv_name, unknown_0));
396 /* store the parameters */
397 init_samr_q_connect(&q_o, srv_name, unknown_0);
399 /* turn parameters into data stream */
400 if(!samr_io_q_connect("", &q_o, &data, 0)) {
402 prs_mem_free(&rdata);
406 /* send the data on \PIPE\ */
407 if (!rpc_api_pipe_req(cli, SAMR_CONNECT, &data, &rdata)) {
409 prs_mem_free(&rdata);
415 if(!samr_io_r_connect("", &r_o, &rdata, 0)) {
416 prs_mem_free(&rdata);
420 if (r_o.status != 0) {
421 /* report error code */
422 DEBUG(0,("SAMR_R_CONNECT: %s\n", get_nt_error_msg(r_o.status)));
423 prs_mem_free(&rdata);
427 memcpy(connect_pol, &r_o.connect_pol, sizeof(r_o.connect_pol));
429 prs_mem_free(&rdata);
434 /****************************************************************************
436 ****************************************************************************/
437 BOOL do_samr_open_user(struct cli_state *cli,
438 POLICY_HND *pol, uint32 unk_0, uint32 rid,
439 POLICY_HND *user_pol)
443 SAMR_Q_OPEN_USER q_o;
444 SAMR_R_OPEN_USER r_o;
446 if (pol == NULL || user_pol == NULL)
449 /* create and send a MSRPC command with api SAMR_OPEN_USER */
451 prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
452 prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);
454 DEBUG(4,("SAMR Open User. unk_0: %08x RID:%x\n",
457 /* store the parameters */
458 init_samr_q_open_user(&q_o, pol, unk_0, rid);
460 /* turn parameters into data stream */
461 if(!samr_io_q_open_user("", &q_o, &data, 0)) {
463 prs_mem_free(&rdata);
467 /* send the data on \PIPE\ */
468 if (!rpc_api_pipe_req(cli, SAMR_OPEN_USER, &data, &rdata)) {
470 prs_mem_free(&rdata);
476 if(!samr_io_r_open_user("", &r_o, &rdata, 0)) {
477 prs_mem_free(&rdata);
481 if (r_o.status != 0) {
482 /* report error code */
483 DEBUG(0,("SAMR_R_OPEN_USER: %s\n", get_nt_error_msg(r_o.status)));
484 prs_mem_free(&rdata);
488 memcpy(user_pol, &r_o.user_pol, sizeof(r_o.user_pol));
490 prs_mem_free(&rdata);
495 /****************************************************************************
496 do a SAMR Open Domain
497 ****************************************************************************/
498 BOOL do_samr_open_domain(struct cli_state *cli,
499 POLICY_HND *connect_pol, uint32 rid, DOM_SID *sid,
500 POLICY_HND *domain_pol)
505 SAMR_Q_OPEN_DOMAIN q_o;
506 SAMR_R_OPEN_DOMAIN r_o;
508 if (connect_pol == NULL || sid == NULL || domain_pol == NULL)
511 /* create and send a MSRPC command with api SAMR_OPEN_DOMAIN */
513 prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
514 prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);
516 sid_to_string(sid_str, sid);
517 DEBUG(4,("SAMR Open Domain. SID:%s RID:%x\n", sid_str, rid));
519 /* store the parameters */
520 init_samr_q_open_domain(&q_o, connect_pol, rid, sid);
522 /* turn parameters into data stream */
523 if(!samr_io_q_open_domain("", &q_o, &data, 0)) {
525 prs_mem_free(&rdata);
529 /* send the data on \PIPE\ */
530 if (!rpc_api_pipe_req(cli, SAMR_OPEN_DOMAIN, &data, &rdata)) {
532 prs_mem_free(&rdata);
538 if(!samr_io_r_open_domain("", &r_o, &rdata, 0)) {
539 prs_mem_free(&rdata);
543 if (r_o.status != 0) {
544 /* report error code */
545 DEBUG(0,("SAMR_R_OPEN_DOMAIN: %s\n", get_nt_error_msg(r_o.status)));
546 prs_mem_free(&rdata);
550 memcpy(domain_pol, &r_o.domain_pol, sizeof(r_o.domain_pol));
552 prs_mem_free(&rdata);
559 /* CURRENTLY DOES NOT COMPILE AND IS NOT USED ANYWHERE. JRA. */
561 /****************************************************************************
562 do a SAMR Query Unknown 12
563 ****************************************************************************/
564 BOOL do_samr_query_unknown_12(struct cli_state *cli,
565 POLICY_HND *pol, uint32 rid, uint32 num_gids, uint32 *gids,
567 fstring als_names [MAX_LOOKUP_SIDS],
568 uint32 num_als_users[MAX_LOOKUP_SIDS])
572 SAMR_Q_LOOKUP_RIDS q_o;
573 SAMR_R_LOOKUP_RIDS r_o;
575 if (pol == NULL || rid == 0 || num_gids == 0 || gids == NULL ||
576 num_aliases == NULL || als_names == NULL || num_als_users == NULL )
579 /* create and send a MSRPC command with api SAMR_UNKNOWN_12 */
581 prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
582 prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);
584 DEBUG(4,("SAMR Query Unknown 12.\n"));
586 /* store the parameters */
587 init_samr_q_lookup_rids(&q_o, pol, rid, num_gids, gids);
589 /* turn parameters into data stream */
590 if(!samr_io_q_lookup_rids("", &q_o, &data, 0)) {
592 prs_mem_free(&rdata);
596 /* send the data on \PIPE\ */
597 if (!rpc_api_pipe_req(cli, SAMR_LOOKUP_RIDS, &data, &rdata)) {
599 prs_mem_free(&rdata);
605 if(!samr_io_r_lookup_rids("", &r_o, &rdata, 0)) {
606 prs_mem_free(&rdata);
610 if (r_o.status != 0) {
611 /* report error code */
612 DEBUG(0,("SAMR_R_UNKNOWN_12: %s\n", get_nt_error_msg(r_o.status)));
613 prs_mem_free(&rdata);
617 if (r_o.ptr_aliases != 0 && r_o.ptr_als_usrs != 0 &&
618 r_o.num_als_usrs1 == r_o.num_aliases1) {
621 *num_aliases = r_o.num_aliases1;
623 for (i = 0; i < r_o.num_aliases1; i++) {
624 fstrcpy(als_names[i], dos_unistrn2(r_o.uni_als_name[i].buffer,
625 r_o.uni_als_name[i].uni_str_len));
627 for (i = 0; i < r_o.num_als_usrs1; i++) {
628 num_als_users[i] = r_o.num_als_usrs[i];
630 } else if (r_o.ptr_aliases == 0 && r_o.ptr_als_usrs == 0) {
633 prs_mem_free(&rdata);
637 prs_mem_free(&rdata);
643 /****************************************************************************
644 do a SAMR Query User Groups
645 ****************************************************************************/
646 BOOL do_samr_query_usergroups(struct cli_state *cli,
647 POLICY_HND *pol, uint32 *num_groups, DOM_GID *gid)
651 SAMR_Q_QUERY_USERGROUPS q_o;
652 SAMR_R_QUERY_USERGROUPS r_o;
654 if (pol == NULL || gid == NULL || num_groups == 0)
657 /* create and send a MSRPC command with api SAMR_QUERY_USERGROUPS */
659 prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
660 prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);
662 DEBUG(4,("SAMR Query User Groups.\n"));
664 /* store the parameters */
665 init_samr_q_query_usergroups(&q_o, pol);
667 /* turn parameters into data stream */
668 if(!samr_io_q_query_usergroups("", &q_o, &data, 0)) {
670 prs_mem_free(&rdata);
674 /* send the data on \PIPE\ */
675 if (!rpc_api_pipe_req(cli, SAMR_QUERY_USERGROUPS, &data, &rdata)) {
677 prs_mem_free(&rdata);
686 if(!samr_io_r_query_usergroups("", &r_o, &rdata, 0)) {
687 prs_mem_free(&rdata);
691 if (r_o.status != 0) {
692 /* report error code */
693 DEBUG(0,("SAMR_R_QUERY_USERGROUPS: %s\n", get_nt_error_msg(r_o.status)));
694 prs_mem_free(&rdata);
698 *num_groups = r_o.num_entries;
700 prs_mem_free(&rdata);
707 /* CURRENTLY DOES NOT COMPILE WITH THE NEW SAMR PARSE CODE. JRA */
709 /****************************************************************************
710 do a SAMR Query User Info
711 ****************************************************************************/
712 BOOL do_samr_query_userinfo(struct cli_state *cli,
713 POLICY_HND *pol, uint16 switch_value, void* usr)
717 SAMR_Q_QUERY_USERINFO q_o;
718 SAMR_R_QUERY_USERINFO r_o;
720 if (pol == NULL || usr == NULL || switch_value == 0)
723 /* create and send a MSRPC command with api SAMR_QUERY_USERINFO */
725 prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
726 prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);
728 DEBUG(4,("SAMR Query User Info. level: %d\n", switch_value));
730 /* store the parameters */
731 init_samr_q_query_userinfo(&q_o, pol, switch_value);
733 /* turn parameters into data stream */
734 if(!samr_io_q_query_userinfo("", &q_o, &data, 0)) {
736 prs_mem_free(&rdata);
740 /* send the data on \PIPE\ */
741 if (!rpc_api_pipe_req(cli, SAMR_QUERY_USERINFO, &data, &rdata)) {
743 prs_mem_free(&rdata);
752 if(!samr_io_r_query_userinfo("", &r_o, &rdata, 0)) {
753 prs_mem_free(&rdata);
757 if (r_o.status != 0) {
758 /* report error code */
759 DEBUG(0,("SAMR_R_QUERY_USERINFO: %s\n", get_nt_error_msg(r_o.status)));
760 prs_mem_free(&rdata);
764 if (r_o.switch_value != switch_value) {
765 DEBUG(0,("SAMR_R_QUERY_USERINFO: received incorrect level %d\n",
767 prs_mem_free(&rdata);
772 prs_mem_free(&rdata);
776 prs_mem_free(&rdata);
783 /****************************************************************************
785 ****************************************************************************/
786 BOOL do_samr_close(struct cli_state *cli, POLICY_HND *hnd)
790 SAMR_Q_CLOSE_HND q_c;
791 SAMR_R_CLOSE_HND r_c;
796 prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
797 prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);
799 /* create and send a MSRPC command with api SAMR_CLOSE_HND */
801 DEBUG(4,("SAMR Close\n"));
803 /* store the parameters */
804 init_samr_q_close_hnd(&q_c, hnd);
806 /* turn parameters into data stream */
807 if(!samr_io_q_close_hnd("", &q_c, &data, 0)) {
809 prs_mem_free(&rdata);
813 /* send the data on \PIPE\ */
814 if (!rpc_api_pipe_req(cli, SAMR_CLOSE_HND, &data, &rdata)) {
816 prs_mem_free(&rdata);
822 if(!samr_io_r_close_hnd("", &r_c, &rdata, 0)) {
823 prs_mem_free(&rdata);
827 if (r_c.status != 0) {
828 /* report error code */
829 DEBUG(0,("SAMR_CLOSE_HND: %s\n", get_nt_error_msg(r_c.status)));
830 prs_mem_free(&rdata);
834 /* check that the returned policy handle is all zeros */
836 if (IVAL(&r_c.pol.data1,0) || IVAL(&r_c.pol.data2,0) || SVAL(&r_c.pol.data3,0) ||
837 SVAL(&r_c.pol.data4,0) || IVAL(r_c.pol.data5,0) || IVAL(r_c.pol.data5,4) ) {
838 DEBUG(0,("SAMR_CLOSE_HND: non-zero handle returned\n"));
839 prs_mem_free(&rdata);
843 prs_mem_free(&rdata);