merge from 2.2 in password_ok() to ensure that we check the
[Samba/gbeck.git] / source / libsmb / cli_samr.c
blob985a0a1ecb1bdb24de66bffa06b9659ba5f0eaad
1 /*
2 Unix SMB/Netbios implementation.
3 Version 2.2
4 RPC pipe client
5 Copyright (C) Tim Potter 2000,
6 Copyright (C) Andrew Tridgell 1992-1997,2000,
7 Copyright (C) Luke Kenneth Casson Leighton 1996-1997,2000,
8 Copyright (C) Paul Ashton 1997,2000,
9 Copyright (C) Elrond 2000.
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "includes.h"
28 /* Opens a SMB connection to the SAMR pipe */
30 struct cli_state *cli_samr_initialise(struct cli_state *cli, char *system_name,
31 struct ntuser_creds *creds)
33 struct in_addr dest_ip;
34 struct nmb_name calling, called;
35 fstring dest_host;
36 extern pstring global_myname;
37 struct ntuser_creds anon;
39 /* Initialise cli_state information */
41 if (!cli_initialise(cli)) {
42 return NULL;
45 if (!creds) {
46 ZERO_STRUCT(anon);
47 anon.pwd.null_pwd = 1;
48 creds = &anon;
51 cli_init_creds(cli, creds);
53 /* Establish a SMB connection */
55 if (!resolve_srv_name(system_name, dest_host, &dest_ip)) {
56 return NULL;
59 make_nmb_name(&called, dns_to_netbios_name(dest_host), 0x20);
60 make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0);
62 if (!cli_establish_connection(cli, dest_host, &dest_ip, &calling,
63 &called, "IPC$", "IPC", False, True)) {
64 return NULL;
67 /* Open a NT session thingy */
69 if (!cli_nt_session_open(cli, PIPE_SAMR)) {
70 cli_shutdown(cli);
71 return NULL;
74 return cli;
77 /* Shut down a SMB connection to the SAMR pipe */
79 void cli_samr_shutdown(struct cli_state *cli)
81 if (cli->fd != -1) cli_ulogoff(cli);
82 cli_shutdown(cli);
85 /* Connect to SAMR database */
87 uint32 cli_samr_connect(
88 struct cli_state *cli,
89 TALLOC_CTX *mem_ctx,
90 char *srv_name,
91 uint32 access_mask,
92 POLICY_HND *connect_pol
95 prs_struct qbuf, rbuf;
96 SAMR_Q_CONNECT q;
97 SAMR_R_CONNECT r;
98 uint32 result;
100 ZERO_STRUCT(q);
101 ZERO_STRUCT(r);
103 /* Initialise parse structures */
105 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
106 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
108 /* Marshall data and send request */
110 init_samr_q_connect(&q, srv_name, access_mask);
112 if (!samr_io_q_connect("", &q, &qbuf, 0) ||
113 !rpc_api_pipe_req(cli, SAMR_CONNECT, &qbuf, &rbuf)) {
114 result = NT_STATUS_UNSUCCESSFUL;
115 goto done;
118 /* Unmarshall response */
120 if (!samr_io_r_connect("", &r, &rbuf, 0)) {
121 result = NT_STATUS_UNSUCCESSFUL;
122 goto done;
125 /* Return output parameters */
127 if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
128 *connect_pol = r.connect_pol;
131 done:
132 prs_mem_free(&qbuf);
133 prs_mem_free(&rbuf);
135 return result;
138 /* Close SAMR handle */
140 uint32 cli_samr_close(
141 struct cli_state *cli,
142 TALLOC_CTX *mem_ctx,
143 POLICY_HND *connect_pol
146 prs_struct qbuf, rbuf;
147 SAMR_Q_CLOSE_HND q;
148 SAMR_R_CLOSE_HND r;
149 uint32 result;
151 ZERO_STRUCT(q);
152 ZERO_STRUCT(r);
154 /* Initialise parse structures */
156 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
157 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
159 /* Marshall data and send request */
161 init_samr_q_close_hnd(&q, connect_pol);
163 if (!samr_io_q_close_hnd("", &q, &qbuf, 0) ||
164 !rpc_api_pipe_req(cli, SAMR_CLOSE_HND, &qbuf, &rbuf)) {
165 result = NT_STATUS_UNSUCCESSFUL;
166 goto done;
169 /* Unmarshall response */
171 if (!samr_io_r_close_hnd("", &r, &rbuf, 0)) {
172 result = NT_STATUS_UNSUCCESSFUL;
173 goto done;
176 /* Return output parameters */
178 if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
179 *connect_pol = r.pol;
182 done:
183 prs_mem_free(&qbuf);
184 prs_mem_free(&rbuf);
186 return result;
189 /* Open handle on a domain */
191 uint32 cli_samr_open_domain(
192 struct cli_state *cli,
193 TALLOC_CTX *mem_ctx,
194 POLICY_HND *connect_pol,
195 uint32 access_mask,
196 DOM_SID *domain_sid,
197 POLICY_HND *domain_pol
200 prs_struct qbuf, rbuf;
201 SAMR_Q_OPEN_DOMAIN q;
202 SAMR_R_OPEN_DOMAIN r;
203 uint32 result;
205 ZERO_STRUCT(q);
206 ZERO_STRUCT(r);
208 /* Initialise parse structures */
210 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
211 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
213 /* Marshall data and send request */
215 init_samr_q_open_domain(&q, connect_pol, access_mask, domain_sid);
217 if (!samr_io_q_open_domain("", &q, &qbuf, 0) ||
218 !rpc_api_pipe_req(cli, SAMR_OPEN_DOMAIN, &qbuf, &rbuf)) {
219 result = NT_STATUS_UNSUCCESSFUL;
220 goto done;
223 /* Unmarshall response */
225 if (!samr_io_r_open_domain("", &r, &rbuf, 0)) {
226 result = NT_STATUS_UNSUCCESSFUL;
227 goto done;
230 /* Return output parameters */
232 if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
233 *domain_pol = r.domain_pol;
236 done:
237 prs_mem_free(&qbuf);
238 prs_mem_free(&rbuf);
240 return result;
243 /* Open handle on a user */
245 uint32 cli_samr_open_user(
246 struct cli_state *cli,
247 TALLOC_CTX *mem_ctx,
248 POLICY_HND *domain_pol,
249 uint32 access_mask,
250 uint32 user_rid,
251 POLICY_HND *user_pol
254 prs_struct qbuf, rbuf;
255 SAMR_Q_OPEN_USER q;
256 SAMR_R_OPEN_USER r;
257 uint32 result;
259 ZERO_STRUCT(q);
260 ZERO_STRUCT(r);
262 /* Initialise parse structures */
264 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
265 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
267 /* Marshall data and send request */
269 init_samr_q_open_user(&q, domain_pol, access_mask, user_rid);
271 if (!samr_io_q_open_user("", &q, &qbuf, 0) ||
272 !rpc_api_pipe_req(cli, SAMR_OPEN_USER, &qbuf, &rbuf)) {
273 result = NT_STATUS_UNSUCCESSFUL;
274 goto done;
277 /* Unmarshall response */
279 if (!samr_io_r_open_user("", &r, &rbuf, 0)) {
280 result = NT_STATUS_UNSUCCESSFUL;
281 goto done;
284 /* Return output parameters */
286 if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
287 *user_pol = r.user_pol;
290 done:
291 prs_mem_free(&qbuf);
292 prs_mem_free(&rbuf);
294 return result;
297 /* Open handle on a group */
299 uint32 cli_samr_open_group(
300 struct cli_state *cli,
301 TALLOC_CTX *mem_ctx,
302 POLICY_HND *domain_pol,
303 uint32 access_mask,
304 uint32 group_rid,
305 POLICY_HND *group_pol
308 prs_struct qbuf, rbuf;
309 SAMR_Q_OPEN_GROUP q;
310 SAMR_R_OPEN_GROUP r;
311 uint32 result;
313 ZERO_STRUCT(q);
314 ZERO_STRUCT(r);
316 /* Initialise parse structures */
318 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
319 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
321 /* Marshall data and send request */
323 init_samr_q_open_group(&q, domain_pol, access_mask, group_rid);
325 if (!samr_io_q_open_group("", &q, &qbuf, 0) ||
326 !rpc_api_pipe_req(cli, SAMR_OPEN_GROUP, &qbuf, &rbuf)) {
327 result = NT_STATUS_UNSUCCESSFUL;
328 goto done;
331 /* Unmarshall response */
333 if (!samr_io_r_open_group("", &r, &rbuf, 0)) {
334 result = NT_STATUS_UNSUCCESSFUL;
335 goto done;
338 /* Return output parameters */
340 if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
341 *group_pol = r.pol;
344 done:
345 prs_mem_free(&qbuf);
346 prs_mem_free(&rbuf);
348 return result;
351 /* Query user info */
353 uint32 cli_samr_query_userinfo(
354 struct cli_state *cli,
355 TALLOC_CTX *mem_ctx,
356 POLICY_HND *user_pol,
357 uint16 switch_value,
358 SAM_USERINFO_CTR *ctr
361 prs_struct qbuf, rbuf;
362 SAMR_Q_QUERY_USERINFO q;
363 SAMR_R_QUERY_USERINFO r;
364 uint32 result;
366 ZERO_STRUCT(q);
367 ZERO_STRUCT(r);
369 /* Initialise parse structures */
371 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
372 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
374 /* Marshall data and send request */
376 init_samr_q_query_userinfo(&q, user_pol, switch_value);
378 if (!samr_io_q_query_userinfo("", &q, &qbuf, 0) ||
379 !rpc_api_pipe_req(cli, SAMR_QUERY_USERINFO, &qbuf, &rbuf)) {
380 result = NT_STATUS_UNSUCCESSFUL;
381 goto done;
384 /* Unmarshall response */
386 r.ctr = ctr;
388 if (!samr_io_r_query_userinfo("", &r, &rbuf, 0)) {
389 result = NT_STATUS_UNSUCCESSFUL;
390 goto done;
393 /* Return output parameters */
395 result = r.status;
397 done:
398 prs_mem_free(&qbuf);
399 prs_mem_free(&rbuf);
401 return result;
404 /* Query group info */
406 uint32 cli_samr_query_groupinfo(
407 struct cli_state *cli,
408 TALLOC_CTX *mem_ctx,
409 POLICY_HND *group_pol,
410 uint32 info_level,
411 GROUP_INFO_CTR *ctr
414 prs_struct qbuf, rbuf;
415 SAMR_Q_QUERY_GROUPINFO q;
416 SAMR_R_QUERY_GROUPINFO r;
417 uint32 result;
419 ZERO_STRUCT(q);
420 ZERO_STRUCT(r);
422 /* Initialise parse structures */
424 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
425 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
427 /* Marshall data and send request */
429 init_samr_q_query_groupinfo(&q, group_pol, info_level);
431 if (!samr_io_q_query_groupinfo("", &q, &qbuf, 0) ||
432 !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPINFO, &qbuf, &rbuf)) {
433 result = NT_STATUS_UNSUCCESSFUL;
434 goto done;
437 /* Unmarshall response */
439 r.ctr = ctr;
441 if (!samr_io_r_query_groupinfo("", &r, &rbuf, 0)) {
442 result = NT_STATUS_UNSUCCESSFUL;
443 goto done;
446 /* Return output parameters */
448 result = r.status;
450 done:
451 prs_mem_free(&qbuf);
452 prs_mem_free(&rbuf);
454 return result;
457 /* Query user groups */
459 uint32 cli_samr_query_usergroups(
460 struct cli_state *cli,
461 TALLOC_CTX *mem_ctx,
462 POLICY_HND *user_pol,
463 uint32 *num_groups,
464 DOM_GID **gid
467 prs_struct qbuf, rbuf;
468 SAMR_Q_QUERY_USERGROUPS q;
469 SAMR_R_QUERY_USERGROUPS r;
470 uint32 result;
472 ZERO_STRUCT(q);
473 ZERO_STRUCT(r);
475 /* Initialise parse structures */
477 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
478 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
480 /* Marshall data and send request */
482 init_samr_q_query_usergroups(&q, user_pol);
484 if (!samr_io_q_query_usergroups("", &q, &qbuf, 0) ||
485 !rpc_api_pipe_req(cli, SAMR_QUERY_USERGROUPS, &qbuf, &rbuf)) {
486 result = NT_STATUS_UNSUCCESSFUL;
487 goto done;
490 /* Unmarshall response */
492 if (!samr_io_r_query_usergroups("", &r, &rbuf, 0)) {
493 result = NT_STATUS_UNSUCCESSFUL;
494 goto done;
497 /* Return output parameters */
499 if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
500 *num_groups = r.num_entries;
501 *gid = r.gid;
504 done:
505 prs_mem_free(&qbuf);
506 prs_mem_free(&rbuf);
508 return result;
511 /* Query user groups */
513 uint32 cli_samr_query_groupmem(
514 struct cli_state *cli,
515 TALLOC_CTX *mem_ctx,
516 POLICY_HND *group_pol,
517 uint32 *num_mem,
518 uint32 **rid,
519 uint32 **attr
522 prs_struct qbuf, rbuf;
523 SAMR_Q_QUERY_GROUPMEM q;
524 SAMR_R_QUERY_GROUPMEM r;
525 uint32 result;
527 ZERO_STRUCT(q);
528 ZERO_STRUCT(r);
530 /* Initialise parse structures */
532 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
533 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
535 /* Marshall data and send request */
537 init_samr_q_query_groupmem(&q, group_pol);
539 if (!samr_io_q_query_groupmem("", &q, &qbuf, 0) ||
540 !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPMEM, &qbuf, &rbuf)) {
541 result = NT_STATUS_UNSUCCESSFUL;
542 goto done;
545 /* Unmarshall response */
547 if (!samr_io_r_query_groupmem("", &r, &rbuf, 0)) {
548 result = NT_STATUS_UNSUCCESSFUL;
549 goto done;
552 /* Return output parameters */
554 if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
555 *num_mem = r.num_entries;
556 *rid = r.rid;
557 *attr = r.attr;
560 done:
561 prs_mem_free(&qbuf);
562 prs_mem_free(&rbuf);
564 return result;
567 /* Enumerate domain groups */
569 uint32 cli_samr_enum_dom_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx,
570 POLICY_HND *pol, uint32 *start_idx,
571 uint32 size, struct acct_info **dom_groups,
572 uint32 *num_dom_groups)
574 prs_struct qbuf, rbuf;
575 SAMR_Q_ENUM_DOM_GROUPS q;
576 SAMR_R_ENUM_DOM_GROUPS r;
577 uint32 result = NT_STATUS_UNSUCCESSFUL, name_idx, i;
579 ZERO_STRUCT(q);
580 ZERO_STRUCT(r);
582 /* Initialise parse structures */
584 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
585 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
587 /* Marshall data and send request */
589 init_samr_q_enum_dom_groups(&q, pol, *start_idx, size);
591 if (!samr_io_q_enum_dom_groups("", &q, &qbuf, 0) ||
592 !rpc_api_pipe_req(cli, SAMR_ENUM_DOM_GROUPS, &qbuf, &rbuf)) {
593 goto done;
596 /* Unmarshall response */
598 if (!samr_io_r_enum_dom_groups("", &r, &rbuf, 0)) {
599 goto done;
602 /* Return output parameters */
604 result = r.status;
606 if (result != NT_STATUS_NOPROBLEMO &&
607 result != STATUS_MORE_ENTRIES) {
608 goto done;
611 *num_dom_groups = r.num_entries2;
613 if (!((*dom_groups) = (struct acct_info *)
614 talloc(mem_ctx, sizeof(struct acct_info) * *num_dom_groups))) {
615 result = NT_STATUS_UNSUCCESSFUL;
616 goto done;
619 memset(*dom_groups, 0, sizeof(struct acct_info) * *num_dom_groups);
621 name_idx = 0;
623 for (i = 0; i < *num_dom_groups; i++) {
625 (*dom_groups)[i].rid = r.sam[i].rid;
627 if (r.sam[i].hdr_name.buffer) {
628 unistr2_to_ascii((*dom_groups)[i].acct_name,
629 &r.uni_grp_name[name_idx],
630 sizeof(fstring) - 1);
631 name_idx++;
634 *start_idx = r.next_idx;
637 done:
638 prs_mem_free(&qbuf);
639 prs_mem_free(&rbuf);
641 return result;
644 /* Query alias members */
646 uint32 cli_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
647 POLICY_HND *alias_pol, uint32 *num_mem,
648 DOM_SID **sids)
650 prs_struct qbuf, rbuf;
651 SAMR_Q_QUERY_ALIASMEM q;
652 SAMR_R_QUERY_ALIASMEM r;
653 uint32 result = NT_STATUS_UNSUCCESSFUL, i;
655 ZERO_STRUCT(q);
656 ZERO_STRUCT(r);
658 /* Initialise parse structures */
660 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
661 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
663 /* Marshall data and send request */
665 init_samr_q_query_aliasmem(&q, alias_pol);
667 if (!samr_io_q_query_aliasmem("", &q, &qbuf, 0) ||
668 !rpc_api_pipe_req(cli, SAMR_QUERY_ALIASMEM, &qbuf, &rbuf)) {
669 goto done;
672 /* Unmarshall response */
674 if (!samr_io_r_query_aliasmem("", &r, &rbuf, 0)) {
675 goto done;
678 /* Return output parameters */
680 if ((result = r.status) != NT_STATUS_NOPROBLEMO) {
681 goto done;
684 *num_mem = r.num_sids;
686 if (!(*sids = talloc(mem_ctx, sizeof(DOM_SID) * *num_mem))) {
687 result = NT_STATUS_UNSUCCESSFUL;
688 goto done;
691 for (i = 0; i < *num_mem; i++) {
692 (*sids)[i] = r.sid[i].sid;
695 done:
696 prs_mem_free(&qbuf);
697 prs_mem_free(&rbuf);
699 return result;
702 /* Open handle on an alias */
704 uint32 cli_samr_open_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx,
705 POLICY_HND *domain_pol, uint32 access_mask,
706 uint32 alias_rid, POLICY_HND *alias_pol)
708 prs_struct qbuf, rbuf;
709 SAMR_Q_OPEN_ALIAS q;
710 SAMR_R_OPEN_ALIAS r;
711 uint32 result;
713 ZERO_STRUCT(q);
714 ZERO_STRUCT(r);
716 /* Initialise parse structures */
718 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
719 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
721 /* Marshall data and send request */
723 init_samr_q_open_alias(&q, domain_pol, access_mask, alias_rid);
725 if (!samr_io_q_open_alias("", &q, &qbuf, 0) ||
726 !rpc_api_pipe_req(cli, SAMR_OPEN_ALIAS, &qbuf, &rbuf)) {
727 result = NT_STATUS_UNSUCCESSFUL;
728 goto done;
731 /* Unmarshall response */
733 if (!samr_io_r_open_alias("", &r, &rbuf, 0)) {
734 result = NT_STATUS_UNSUCCESSFUL;
735 goto done;
738 /* Return output parameters */
740 if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
741 *alias_pol = r.pol;
744 done:
745 prs_mem_free(&qbuf);
746 prs_mem_free(&rbuf);
748 return result;