CVE-2020-25719 kdc: Avoid races and multiple DB lookups in s4u2self check
[Samba.git] / source3 / utils / net_rpc_trust.c
blob9cfce005e5602199f3f38018351fd27ff54ec5e9
1 /*
2 Samba Unix/Linux SMB client library
3 Distributed SMB/CIFS Server Management Utility
4 Copyright (C) 2011 Sumit Bose (sbose@redhat.com)
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 #include "includes.h"
21 #include "utils/net.h"
22 #include "rpc_client/cli_pipe.h"
23 #include "rpc_client/cli_lsarpc.h"
24 #include "librpc/gen_ndr/ndr_drsblobs.h"
25 #include "../librpc/gen_ndr/ndr_lsa_c.h"
26 #include "../libcli/security/dom_sid.h"
27 #include "libsmb/libsmb.h"
29 #include "lib/crypto/gnutls_helpers.h"
30 #include <gnutls/gnutls.h>
31 #include <gnutls/crypto.h>
33 #define ARG_OTHERSERVER "otherserver="
34 #define ARG_OTHERUSER "otheruser="
35 #define ARG_OTHERDOMAINSID "otherdomainsid="
36 #define ARG_OTHERDOMAIN "otherdomain="
37 #define ARG_OTHERNETBIOSDOMAIN "other_netbios_domain="
38 #define ARG_TRUSTPW "trustpw="
40 enum trust_op {
41 TRUST_CREATE,
42 TRUST_DELETE
45 struct other_dom_data {
46 char *host;
47 char *user_name;
48 char *domain_sid_str;
49 char *dns_domain_name;
50 char *domain_name;
53 struct dom_data {
54 struct dom_sid *domsid;
55 char *dns_domain_name;
56 char *domain_name;
59 static NTSTATUS close_handle(TALLOC_CTX *mem_ctx,
60 struct dcerpc_binding_handle *bind_hnd,
61 struct policy_handle *pol_hnd)
63 NTSTATUS status;
64 NTSTATUS result;
66 status = dcerpc_lsa_Close(bind_hnd, mem_ctx, pol_hnd, &result);
67 if (!NT_STATUS_IS_OK(status)) {
68 DEBUG(0, ("dcerpc_lsa_Close failed with error [%s].\n",
69 nt_errstr(status)));
70 return status;
72 if (!NT_STATUS_IS_OK(result)) {
73 DEBUG(0, ("lsa close failed with error [%s].\n",
74 nt_errstr(result)));
75 return result;
78 return NT_STATUS_OK;
81 static NTSTATUS delete_trust(TALLOC_CTX *mem_ctx,
82 struct dcerpc_binding_handle *bind_hnd,
83 struct policy_handle *pol_hnd,
84 struct dom_sid *domsid)
86 NTSTATUS status;
87 struct lsa_DeleteTrustedDomain dr;
89 dr.in.handle = pol_hnd;
90 dr.in.dom_sid = domsid;
92 status = dcerpc_lsa_DeleteTrustedDomain_r(bind_hnd, mem_ctx, &dr);
93 if (!NT_STATUS_IS_OK(status)) {
94 DEBUG(0, ("dcerpc_lsa_DeleteTrustedDomain_r failed with [%s]\n",
95 nt_errstr(status)));
96 return status;
98 if (!NT_STATUS_IS_OK(dr.out.result)) {
99 DEBUG(0, ("DeleteTrustedDomain returned [%s]\n",
100 nt_errstr(dr.out.result)));
101 return dr.out.result;
104 return NT_STATUS_OK;
107 static NTSTATUS create_trust(TALLOC_CTX *mem_ctx,
108 struct dcerpc_binding_handle *bind_hnd,
109 struct policy_handle *pol_hnd,
110 const char *trust_name,
111 const char *trust_name_dns,
112 struct dom_sid *domsid,
113 struct lsa_TrustDomainInfoAuthInfoInternal *authinfo)
115 NTSTATUS status;
116 struct lsa_CreateTrustedDomainEx2 r;
117 struct lsa_TrustDomainInfoInfoEx trustinfo;
118 struct policy_handle trustdom_handle;
120 trustinfo.sid = domsid;
121 trustinfo.netbios_name.string = trust_name;
122 trustinfo.domain_name.string = trust_name_dns;
124 trustinfo.trust_direction = LSA_TRUST_DIRECTION_INBOUND |
125 LSA_TRUST_DIRECTION_OUTBOUND;
127 trustinfo.trust_type = LSA_TRUST_TYPE_UPLEVEL;
129 trustinfo.trust_attributes = LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE;
131 r.in.policy_handle = pol_hnd;
132 r.in.info = &trustinfo;
133 r.in.auth_info_internal = authinfo;
134 r.in.access_mask = LSA_TRUSTED_SET_POSIX | LSA_TRUSTED_SET_AUTH |
135 LSA_TRUSTED_QUERY_DOMAIN_NAME;
136 r.out.trustdom_handle = &trustdom_handle;
138 status = dcerpc_lsa_CreateTrustedDomainEx2_r(bind_hnd, mem_ctx, &r);
139 if (!NT_STATUS_IS_OK(status)) {
140 DEBUG(0, ("dcerpc_lsa_CreateTrustedDomainEx2_r failed "
141 "with error [%s].\n", nt_errstr(status)));
142 return status;
144 if (!NT_STATUS_IS_OK(r.out.result)) {
145 DEBUG(0, ("CreateTrustedDomainEx2_r returned [%s].\n",
146 nt_errstr(r.out.result)));
147 return r.out.result;
150 return NT_STATUS_OK;
153 static NTSTATUS get_domain_info(TALLOC_CTX *mem_ctx,
154 struct dcerpc_binding_handle *bind_hdn,
155 struct policy_handle *pol_hnd,
156 struct dom_data *dom_data)
158 NTSTATUS status;
159 struct lsa_QueryInfoPolicy2 qr;
160 struct dom_sid_buf buf;
162 qr.in.handle = pol_hnd;
163 qr.in.level = LSA_POLICY_INFO_DNS;
165 status = dcerpc_lsa_QueryInfoPolicy2_r(bind_hdn, mem_ctx, &qr);
166 if (!NT_STATUS_IS_OK(status)) {
167 DEBUG(0, ("dcerpc_lsa_QueryInfoPolicy2_r failed "
168 "with error [%s].\n", nt_errstr(status)));
169 return status;
172 if (!NT_STATUS_IS_OK(qr.out.result)) {
173 DEBUG(0, ("QueryInfoPolicy2 returned [%s].\n",
174 nt_errstr(qr.out.result)));
175 return qr.out.result;
178 dom_data->domain_name = talloc_strdup(mem_ctx,
179 (*qr.out.info)->dns.name.string);
180 dom_data->dns_domain_name = talloc_strdup(mem_ctx,
181 (*qr.out.info)->dns.dns_domain.string);
182 dom_data->domsid = dom_sid_dup(mem_ctx, (*qr.out.info)->dns.sid);
183 if (dom_data->domain_name == NULL ||
184 dom_data->dns_domain_name == NULL ||
185 dom_data->domsid == NULL) {
186 DEBUG(0, ("Copying domain data failed.\n"));
187 return NT_STATUS_NO_MEMORY;
190 DEBUG(0, ("Got the following domain info [%s][%s][%s].\n",
191 dom_data->domain_name, dom_data->dns_domain_name,
192 dom_sid_str_buf(dom_data->domsid, &buf)));
194 return NT_STATUS_OK;
197 static NTSTATUS connect_and_get_info(TALLOC_CTX *mem_ctx,
198 struct net_context *net_ctx,
199 struct cli_state **cli,
200 struct rpc_pipe_client **pipe_hnd,
201 struct policy_handle *pol_hnd,
202 struct dom_data *dom_data,
203 DATA_BLOB *session_key)
205 NTSTATUS status;
206 NTSTATUS result;
208 status = net_make_ipc_connection_ex(net_ctx, NULL, NULL, NULL,
209 NET_FLAGS_PDC, cli);
210 if (!NT_STATUS_IS_OK(status)) {
211 DEBUG(0, ("Failed to connect to [%s] with error [%s]\n",
212 net_ctx->opt_host, nt_errstr(status)));
213 return status;
216 status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc, pipe_hnd);
217 if (!NT_STATUS_IS_OK(status)) {
218 DEBUG(0, ("Failed to initialise lsa pipe with error [%s]\n",
219 nt_errstr(status)));
220 return status;
223 status = dcerpc_lsa_open_policy2((*pipe_hnd)->binding_handle,
224 mem_ctx,
225 (*pipe_hnd)->srv_name_slash,
226 false,
227 (LSA_POLICY_VIEW_LOCAL_INFORMATION |
228 LSA_POLICY_TRUST_ADMIN |
229 LSA_POLICY_CREATE_SECRET),
230 pol_hnd,
231 &result);
232 if (!NT_STATUS_IS_OK(status)) {
233 DEBUG(0, ("Failed to open policy handle with error [%s]\n",
234 nt_errstr(status)));
235 return status;
237 if (!NT_STATUS_IS_OK(result)) {
238 DEBUG(0, ("lsa_open_policy2 with error [%s]\n",
239 nt_errstr(result)));
240 return result;
243 status = get_domain_info(mem_ctx, (*pipe_hnd)->binding_handle,
244 pol_hnd, dom_data);
245 if (!NT_STATUS_IS_OK(status)) {
246 DEBUG(0, ("get_domain_info failed with error [%s].\n",
247 nt_errstr(status)));
248 return status;
251 status = cli_get_session_key(mem_ctx, *pipe_hnd, session_key);
252 if (!NT_STATUS_IS_OK(status)) {
253 DEBUG(0,("Error getting session_key of LSA pipe. Error was %s\n",
254 nt_errstr(status)));
255 return status;
258 return NT_STATUS_OK;
261 static bool get_trust_domain_passwords_auth_blob(TALLOC_CTX *mem_ctx,
262 const char *password,
263 DATA_BLOB *auth_blob)
265 struct trustDomainPasswords auth_struct;
266 struct AuthenticationInformation *auth_info_array;
267 enum ndr_err_code ndr_err;
268 size_t converted_size;
270 generate_random_buffer(auth_struct.confounder,
271 sizeof(auth_struct.confounder));
273 auth_info_array = talloc_array(mem_ctx,
274 struct AuthenticationInformation, 1);
275 if (auth_info_array == NULL) {
276 return false;
279 auth_info_array[0].AuthType = TRUST_AUTH_TYPE_CLEAR;
280 if (!convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, password,
281 strlen(password),
282 &auth_info_array[0].AuthInfo.clear.password,
283 &converted_size)) {
284 return false;
287 auth_info_array[0].AuthInfo.clear.size = converted_size;
289 auth_struct.outgoing.count = 1;
290 auth_struct.outgoing.current.count = 1;
291 auth_struct.outgoing.current.array = auth_info_array;
292 auth_struct.outgoing.previous.count = 0;
293 auth_struct.outgoing.previous.array = NULL;
295 auth_struct.incoming.count = 1;
296 auth_struct.incoming.current.count = 1;
297 auth_struct.incoming.current.array = auth_info_array;
298 auth_struct.incoming.previous.count = 0;
299 auth_struct.incoming.previous.array = NULL;
301 ndr_err = ndr_push_struct_blob(auth_blob, mem_ctx, &auth_struct,
302 (ndr_push_flags_fn_t)ndr_push_trustDomainPasswords);
303 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
304 return false;
307 return true;
310 static int parse_trust_args(TALLOC_CTX *mem_ctx, int argc, const char **argv, struct other_dom_data **_o, char **_trustpw)
312 size_t c;
313 struct other_dom_data *o = NULL;
314 char *trustpw = NULL;
315 int ret = EFAULT;
317 if (argc == 0) {
318 return EINVAL;
321 o = talloc_zero(mem_ctx, struct other_dom_data);
322 if (o == NULL) {
323 DEBUG(0, ("talloc_zero failed.\n"));
324 return ENOMEM;
327 for (c = 0; c < argc; c++) {
328 if (strnequal(argv[c], ARG_OTHERSERVER, sizeof(ARG_OTHERSERVER)-1)) {
329 o->host = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERSERVER)-1);
330 if (o->host == NULL) {
331 ret = ENOMEM;
332 goto failed;
334 } else if (strnequal(argv[c], ARG_OTHERUSER, sizeof(ARG_OTHERUSER)-1)) {
335 o->user_name = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERUSER)-1);
336 if (o->user_name == NULL) {
337 ret = ENOMEM;
338 goto failed;
340 } else if (strnequal(argv[c], ARG_OTHERDOMAINSID, sizeof(ARG_OTHERDOMAINSID)-1)) {
341 o->domain_sid_str = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERDOMAINSID)-1);
342 if (o->domain_sid_str == NULL) {
343 ret = ENOMEM;
344 goto failed;
346 } else if (strnequal(argv[c], ARG_OTHERDOMAIN, sizeof(ARG_OTHERDOMAIN)-1)) {
347 o->dns_domain_name = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERDOMAIN)-1);
348 if (o->dns_domain_name == NULL) {
349 ret = ENOMEM;
350 goto failed;
352 } else if (strnequal(argv[c], ARG_OTHERNETBIOSDOMAIN, sizeof(ARG_OTHERNETBIOSDOMAIN)-1)) {
353 o->domain_name = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERNETBIOSDOMAIN)-1);
354 if (o->domain_name == NULL) {
355 ret = ENOMEM;
356 goto failed;
358 } else if (strnequal(argv[c], ARG_TRUSTPW, sizeof(ARG_TRUSTPW)-1)) {
359 trustpw = talloc_strdup(mem_ctx, argv[c] + sizeof(ARG_TRUSTPW)-1);
360 if (trustpw == NULL) {
361 ret = ENOMEM;
362 goto failed;
364 } else {
365 DEBUG(0, ("Unsupported option [%s].\n", argv[c]));
366 ret = EINVAL;
367 goto failed;
371 *_o = o;
372 *_trustpw = trustpw;
374 return 0;
376 failed:
377 talloc_free(o);
378 talloc_free(trustpw);
379 return ret;
382 static void print_trust_delete_usage(void)
384 d_printf( "%s\n"
385 "net rpc trust delete [options]\n"
386 "\nOptions:\n"
387 "\totherserver=DC in other domain\n"
388 "\totheruser=Admin user in other domain\n"
389 "\totherdomainsid=SID of other domain\n"
390 "\nExamples:\n"
391 "\tnet rpc trust delete otherserver=oname otheruser=ouser -S lname -U luser\n"
392 "\tnet rpc trust delete otherdomainsid=S-... -S lname -U luser\n"
393 " %s\n",
394 _("Usage:"),
395 _("Remove trust between two domains"));
398 static void print_trust_usage(void)
400 d_printf( "%s\n"
401 "net rpc trust create [options]\n"
402 "\nOptions:\n"
403 "\totherserver=DC in other domain\n"
404 "\totheruser=Admin user in other domain\n"
405 "\totherdomainsid=SID of other domain\n"
406 "\tother_netbios_domain=NetBIOS/short name of other domain\n"
407 "\totherdomain=Full/DNS name of other domain\n"
408 "\ttrustpw=Trust password\n"
409 "\nExamples:\n"
410 "\tnet rpc trust create otherserver=oname otheruser=ouser -S lname -U luser\n"
411 "\tnet rpc trust create otherdomainsid=S-... other_netbios_domain=odom otherdomain=odom.org trustpw=secret -S lname -U luser\n"
412 " %s\n",
413 _("Usage:"),
414 _("Create trust between two domains"));
417 static int rpc_trust_common(struct net_context *net_ctx, int argc,
418 const char **argv, enum trust_op op)
420 TALLOC_CTX *mem_ctx;
421 NTSTATUS status;
422 int ret;
423 int success = -1;
424 struct cli_state *cli[2] = {NULL, NULL};
425 struct rpc_pipe_client *pipe_hnd[2] = {NULL, NULL};
426 DATA_BLOB session_key[2];
427 struct policy_handle pol_hnd[2];
428 struct lsa_TrustDomainInfoAuthInfoInternal authinfo;
429 DATA_BLOB auth_blob;
430 char *trust_pw = NULL;
431 struct other_dom_data *other_dom_data;
432 struct net_context *other_net_ctx = NULL;
433 struct dom_data dom_data[2];
434 void (*usage)(void);
436 ZERO_STRUCT(session_key);
438 switch (op) {
439 case TRUST_CREATE:
440 usage = print_trust_usage;
441 break;
442 case TRUST_DELETE:
443 usage = print_trust_delete_usage;
444 break;
445 default:
446 DEBUG(0, ("Unsupported trust operation.\n"));
447 return -1;
450 if (net_ctx->display_usage) {
451 usage();
452 return 0;
455 mem_ctx = talloc_init("trust op");
456 if (mem_ctx == NULL) {
457 DEBUG(0, ("talloc_init failed.\n"));
458 return -1;
461 ret = parse_trust_args(mem_ctx, argc, argv, &other_dom_data, &trust_pw);
462 if (ret != 0) {
463 if (ret == EINVAL) {
464 usage();
465 } else {
466 DEBUG(0, ("Failed to parse arguments.\n"));
468 goto done;
471 if (other_dom_data->host != 0) {
472 other_net_ctx = talloc_zero(other_dom_data, struct net_context);
473 if (other_net_ctx == NULL) {
474 DEBUG(0, ("talloc_zero failed.\n"));
475 goto done;
478 other_net_ctx->opt_host = other_dom_data->host;
479 other_net_ctx->opt_user_name = other_dom_data->user_name;
480 other_net_ctx->opt_user_specified = true;
481 } else {
482 dom_data[1].domsid = dom_sid_parse_talloc(mem_ctx,
483 other_dom_data->domain_sid_str);
484 dom_data[1].domain_name = other_dom_data->domain_name;
485 dom_data[1].dns_domain_name = other_dom_data->dns_domain_name;
487 if (dom_data[1].domsid == NULL ||
488 (op == TRUST_CREATE &&
489 (dom_data[1].domain_name == NULL ||
490 dom_data[1].dns_domain_name == NULL))) {
491 DEBUG(0, ("Missing required argument.\n"));
492 usage();
493 goto done;
497 status = connect_and_get_info(mem_ctx, net_ctx, &cli[0], &pipe_hnd[0],
498 &pol_hnd[0], &dom_data[0], &session_key[0]);
499 if (!NT_STATUS_IS_OK(status)) {
500 DEBUG(0, ("connect_and_get_info failed with error [%s]\n",
501 nt_errstr(status)));
502 goto done;
505 if (other_net_ctx != NULL) {
506 status = connect_and_get_info(mem_ctx, other_net_ctx,
507 &cli[1], &pipe_hnd[1],
508 &pol_hnd[1], &dom_data[1],
509 &session_key[1]);
510 if (!NT_STATUS_IS_OK(status)) {
511 DEBUG(0, ("connect_and_get_info failed with error [%s]\n",
512 nt_errstr(status)));
513 goto done;
517 if (op == TRUST_CREATE) {
518 gnutls_cipher_hd_t cipher_hnd = NULL;
519 gnutls_datum_t enc_session_key = {
520 .data = session_key[0].data,
521 .size = session_key[0].length,
523 int rc;
525 if (trust_pw == NULL) {
526 if (other_net_ctx == NULL) {
527 DEBUG(0, ("Missing either trustpw or otherhost.\n"));
528 goto done;
531 DEBUG(0, ("Using random trust password.\n"));
532 trust_pw = trust_pw_new_value(mem_ctx,
533 SEC_CHAN_DOMAIN,
534 SEC_DOMAIN);
535 if (trust_pw == NULL) {
536 DEBUG(0, ("generate_random_password failed.\n"));
537 goto done;
539 } else {
540 DEBUG(0, ("Using user provided password.\n"));
543 if (!get_trust_domain_passwords_auth_blob(mem_ctx, trust_pw,
544 &auth_blob)) {
545 DEBUG(0, ("get_trust_domain_passwords_auth_blob failed\n"));
546 goto done;
549 authinfo.auth_blob.data = (uint8_t *)talloc_memdup(
550 mem_ctx,
551 auth_blob.data,
552 auth_blob.length);
553 if (authinfo.auth_blob.data == NULL) {
554 goto done;
556 authinfo.auth_blob.size = auth_blob.length;
558 rc = gnutls_cipher_init(&cipher_hnd,
559 GNUTLS_CIPHER_ARCFOUR_128,
560 &enc_session_key,
561 NULL);
562 if (rc < 0) {
563 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
564 goto done;
566 rc = gnutls_cipher_encrypt(cipher_hnd,
567 authinfo.auth_blob.data,
568 authinfo.auth_blob.size);
569 gnutls_cipher_deinit(cipher_hnd);
570 if (rc < 0) {
571 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
572 goto done;
575 status = create_trust(mem_ctx, pipe_hnd[0]->binding_handle,
576 &pol_hnd[0],
577 dom_data[1].domain_name,
578 dom_data[1].dns_domain_name,
579 dom_data[1].domsid,
580 &authinfo);
581 if (!NT_STATUS_IS_OK(status)) {
582 DEBUG(0, ("create_trust failed with error [%s].\n",
583 nt_errstr(status)));
584 goto done;
587 if (other_net_ctx != NULL) {
588 talloc_free(authinfo.auth_blob.data);
589 authinfo.auth_blob.data = (uint8_t *)talloc_memdup(
590 mem_ctx,
591 auth_blob.data,
592 auth_blob.length);
593 if (authinfo.auth_blob.data == NULL) {
594 goto done;
596 authinfo.auth_blob.size = auth_blob.length;
598 enc_session_key = (gnutls_datum_t) {
599 .data = session_key[1].data,
600 .size = session_key[1].length,
603 rc = gnutls_cipher_init(&cipher_hnd,
604 GNUTLS_CIPHER_ARCFOUR_128,
605 &enc_session_key,
606 NULL);
607 if (rc < 0) {
608 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
609 goto done;
611 rc = gnutls_cipher_encrypt(cipher_hnd,
612 authinfo.auth_blob.data,
613 authinfo.auth_blob.size);
614 gnutls_cipher_deinit(cipher_hnd);
615 if (rc < 0) {
616 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
617 goto done;
620 status = create_trust(mem_ctx,
621 pipe_hnd[1]->binding_handle,
622 &pol_hnd[1],
623 dom_data[0].domain_name,
624 dom_data[0].dns_domain_name,
625 dom_data[0].domsid, &authinfo);
626 if (!NT_STATUS_IS_OK(status)) {
627 DEBUG(0, ("create_trust failed with error [%s].\n",
628 nt_errstr(status)));
629 goto done;
632 } else if (op == TRUST_DELETE) {
633 status = delete_trust(mem_ctx, pipe_hnd[0]->binding_handle,
634 &pol_hnd[0], dom_data[1].domsid);
635 if (!NT_STATUS_IS_OK(status)) {
636 DEBUG(0, ("delete_trust failed with [%s].\n",
637 nt_errstr(status)));
638 goto done;
641 if (other_net_ctx != NULL) {
642 status = delete_trust(mem_ctx,
643 pipe_hnd[1]->binding_handle,
644 &pol_hnd[1], dom_data[0].domsid);
645 if (!NT_STATUS_IS_OK(status)) {
646 DEBUG(0, ("delete_trust failed with [%s].\n",
647 nt_errstr(status)));
648 goto done;
653 status = close_handle(mem_ctx, pipe_hnd[0]->binding_handle,
654 &pol_hnd[0]);
655 if (!NT_STATUS_IS_OK(status)) {
656 DEBUG(0, ("close_handle failed with error [%s].\n",
657 nt_errstr(status)));
658 goto done;
661 if (other_net_ctx != NULL) {
662 status = close_handle(mem_ctx, pipe_hnd[1]->binding_handle,
663 &pol_hnd[1]);
664 if (!NT_STATUS_IS_OK(status)) {
665 DEBUG(0, ("close_handle failed with error [%s].\n",
666 nt_errstr(status)));
667 goto done;
671 success = 0;
673 done:
674 data_blob_clear_free(&session_key[0]);
675 data_blob_clear_free(&session_key[1]);
676 cli_shutdown(cli[0]);
677 cli_shutdown(cli[1]);
678 talloc_destroy(mem_ctx);
679 return success;
682 static int rpc_trust_create(struct net_context *net_ctx, int argc,
683 const char **argv)
685 return rpc_trust_common(net_ctx, argc, argv, TRUST_CREATE);
688 static int rpc_trust_delete(struct net_context *net_ctx, int argc,
689 const char **argv)
691 return rpc_trust_common(net_ctx, argc, argv, TRUST_DELETE);
694 int net_rpc_trust(struct net_context *c, int argc, const char **argv)
696 struct functable func[] = {
698 "create",
699 rpc_trust_create,
700 NET_TRANSPORT_RPC,
701 N_("Create trusts"),
702 N_("net rpc trust create\n"
703 " Create trusts")
706 "delete",
707 rpc_trust_delete,
708 NET_TRANSPORT_RPC,
709 N_("Remove trusts"),
710 N_("net rpc trust delete\n"
711 " Remove trusts")
713 {NULL, NULL, 0, NULL, NULL}
716 return net_run_function(c, argc, argv, "net rpc trust", func);