s3-auth Use the common gensec_ntlmssp_update in gensec_ntlmssp3_server
[ira/wip.git] / source3 / utils / net_rpc_trust.c
1 /*
2    Samba Unix/Linux SMB client library
3    Distributed SMB/CIFS Server Management Utility
4    Copyright (C) 2011 Sumit Bose (sbose@redhat.com)
5
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.
10
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.
15
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/>.  */
18
19
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 "../lib/crypto/crypto.h"
27 #include "../libcli/security/dom_sid.h"
28 #include "libsmb/libsmb.h"
29
30
31 #define ARG_OTHERSERVER "otherserver="
32 #define ARG_OTHERUSER "otheruser="
33 #define ARG_OTHERDOMAINSID "otherdomainsid="
34 #define ARG_OTHERDOMAIN "otherdomain="
35 #define ARG_OTHERNETBIOSDOMAIN "other_netbios_domain="
36 #define ARG_TRUSTPW "trustpw="
37
38 enum trust_op {
39         TRUST_CREATE,
40         TRUST_DELETE
41 };
42
43 struct other_dom_data {
44         char *host;
45         char *user_name;
46         char *domain_sid_str;
47         char *dns_domain_name;
48         char *domain_name;
49 };
50
51 struct dom_data {
52         struct dom_sid *domsid;
53         char *dns_domain_name;
54         char *domain_name;
55 };
56
57 static NTSTATUS close_handle(TALLOC_CTX *mem_ctx,
58                              struct dcerpc_binding_handle *bind_hnd,
59                              struct policy_handle *pol_hnd)
60 {
61         NTSTATUS status;
62         NTSTATUS result;
63
64         status = dcerpc_lsa_Close(bind_hnd, mem_ctx, pol_hnd, &result);
65         if (!NT_STATUS_IS_OK(status)) {
66                 DEBUG(0, ("dcerpc_lsa_Close failed with error [%s].\n",
67                           nt_errstr(status)));
68                 return status;
69         }
70         if (!NT_STATUS_IS_OK(result)) {
71                 DEBUG(0, ("lsa close failed with error [%s].\n",
72                           nt_errstr(result)));
73                 return result;
74         }
75
76         return NT_STATUS_OK;
77 }
78
79 static NTSTATUS delete_trust(TALLOC_CTX *mem_ctx,
80                              struct dcerpc_binding_handle *bind_hnd,
81                              struct policy_handle *pol_hnd,
82                              struct dom_sid *domsid)
83 {
84         NTSTATUS status;
85         struct lsa_DeleteTrustedDomain dr;
86
87         dr.in.handle = pol_hnd;
88         dr.in.dom_sid = domsid;
89
90         status = dcerpc_lsa_DeleteTrustedDomain_r(bind_hnd, mem_ctx, &dr);
91         if (!NT_STATUS_IS_OK(status)) {
92                 DEBUG(0, ("dcerpc_lsa_DeleteTrustedDomain_r failed with [%s]\n",
93                           nt_errstr(status)));
94                 return status;
95         }
96         if (!NT_STATUS_IS_OK(dr.out.result)) {
97                 DEBUG(0, ("DeleteTrustedDomain returned [%s]\n",
98                           nt_errstr(dr.out.result)));
99                 return dr.out.result;
100         }
101
102         return NT_STATUS_OK;
103 }
104
105 static NTSTATUS create_trust(TALLOC_CTX *mem_ctx,
106                              struct dcerpc_binding_handle *bind_hnd,
107                              struct policy_handle *pol_hnd,
108                              const char *trust_name,
109                              const char *trust_name_dns,
110                              struct dom_sid *domsid,
111                              struct lsa_TrustDomainInfoAuthInfoInternal *authinfo)
112 {
113         NTSTATUS status;
114         struct lsa_CreateTrustedDomainEx2 r;
115         struct lsa_TrustDomainInfoInfoEx trustinfo;
116         struct policy_handle trustdom_handle;
117
118         trustinfo.sid = domsid;
119         trustinfo.netbios_name.string = trust_name;
120         trustinfo.domain_name.string = trust_name_dns;
121
122         trustinfo.trust_direction = LSA_TRUST_DIRECTION_INBOUND |
123                                     LSA_TRUST_DIRECTION_OUTBOUND;
124
125         trustinfo.trust_type = LSA_TRUST_TYPE_UPLEVEL;
126
127         trustinfo.trust_attributes = LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE;
128
129         r.in.policy_handle = pol_hnd;
130         r.in.info = &trustinfo;
131         r.in.auth_info_internal = authinfo;
132         r.in.access_mask = LSA_TRUSTED_SET_POSIX | LSA_TRUSTED_SET_AUTH |
133                            LSA_TRUSTED_QUERY_DOMAIN_NAME;
134         r.out.trustdom_handle = &trustdom_handle;
135
136         status = dcerpc_lsa_CreateTrustedDomainEx2_r(bind_hnd, mem_ctx, &r);
137         if (!NT_STATUS_IS_OK(status)) {
138                 DEBUG(0, ("dcerpc_lsa_CreateTrustedDomainEx2_r failed "
139                           "with error [%s].\n", nt_errstr(status)));
140                 return status;
141         }
142         if (!NT_STATUS_IS_OK(r.out.result)) {
143                 DEBUG(0, ("CreateTrustedDomainEx2_r returned [%s].\n",
144                           nt_errstr(r.out.result)));
145                 return r.out.result;
146         }
147
148         return NT_STATUS_OK;
149 }
150
151 static NTSTATUS get_domain_info(TALLOC_CTX *mem_ctx,
152                                 struct dcerpc_binding_handle *bind_hdn,
153                                 struct policy_handle *pol_hnd,
154                                 struct dom_data *dom_data)
155 {
156         NTSTATUS status;
157         struct lsa_QueryInfoPolicy2 qr;
158
159         qr.in.handle = pol_hnd;
160         qr.in.level = LSA_POLICY_INFO_DNS;
161
162         status = dcerpc_lsa_QueryInfoPolicy2_r(bind_hdn, mem_ctx, &qr);
163         if (!NT_STATUS_IS_OK(status)) {
164                 DEBUG(0, ("dcerpc_lsa_QueryInfoPolicy2_r failed "
165                           "with error [%s].\n", nt_errstr(status)));
166                 return status;
167         }
168
169         if (!NT_STATUS_IS_OK(qr.out.result)) {
170                 DEBUG(0, ("QueryInfoPolicy2 returned [%s].\n",
171                           nt_errstr(qr.out.result)));
172                 return qr.out.result;
173         }
174
175         dom_data->domain_name = talloc_strdup(mem_ctx,
176                                               (*qr.out.info)->dns.name.string);
177         dom_data->dns_domain_name = talloc_strdup(mem_ctx,
178                                          (*qr.out.info)->dns.dns_domain.string);
179         dom_data->domsid = dom_sid_dup(mem_ctx, (*qr.out.info)->dns.sid);
180         if (dom_data->domain_name == NULL ||
181             dom_data->dns_domain_name == NULL ||
182             dom_data->domsid == NULL) {
183                 DEBUG(0, ("Copying domain data failed.\n"));
184                 return NT_STATUS_NO_MEMORY;
185         }
186
187         DEBUG(0, ("Got the following domain info [%s][%s][%s].\n",
188                   dom_data->domain_name, dom_data->dns_domain_name,
189                   sid_string_talloc(mem_ctx, dom_data->domsid)));
190
191         return NT_STATUS_OK;
192 }
193
194 static NTSTATUS connect_and_get_info(TALLOC_CTX *mem_ctx,
195                                      struct net_context *net_ctx,
196                                      struct cli_state **cli,
197                                      struct rpc_pipe_client **pipe_hnd,
198                                      struct policy_handle *pol_hnd,
199                                      struct dom_data *dom_data)
200 {
201         NTSTATUS status;
202         NTSTATUS result;
203
204         status = net_make_ipc_connection_ex(net_ctx, NULL, NULL, NULL,
205                                             NET_FLAGS_PDC, cli);
206         if (!NT_STATUS_IS_OK(status)) {
207                 DEBUG(0, ("Failed to connect to [%s] with error [%s]\n",
208                           net_ctx->opt_host, nt_errstr(status)));
209                 return status;
210         }
211
212         status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc.syntax_id, pipe_hnd);
213         if (!NT_STATUS_IS_OK(status)) {
214                 DEBUG(0, ("Failed to initialise lsa pipe with error [%s]\n",
215                           nt_errstr(status)));
216                 return status;
217         }
218
219         status = dcerpc_lsa_open_policy2((*pipe_hnd)->binding_handle,
220                                          mem_ctx,
221                                          (*pipe_hnd)->srv_name_slash,
222                                          false,
223                                          (LSA_POLICY_VIEW_LOCAL_INFORMATION |
224                                           LSA_POLICY_TRUST_ADMIN |
225                                           LSA_POLICY_CREATE_SECRET),
226                                          pol_hnd,
227                                          &result);
228         if (!NT_STATUS_IS_OK(status)) {
229                 DEBUG(0, ("Failed to open policy handle with error [%s]\n",
230                           nt_errstr(status)));
231                 return status;
232         }
233         if (!NT_STATUS_IS_OK(result)) {
234                 DEBUG(0, ("lsa_open_policy2 with error [%s]\n",
235                           nt_errstr(result)));
236                 return result;
237         }
238
239         status = get_domain_info(mem_ctx, (*pipe_hnd)->binding_handle,
240                                  pol_hnd, dom_data);
241         if (!NT_STATUS_IS_OK(status)) {
242                 DEBUG(0, ("get_domain_info failed with error [%s].\n",
243                           nt_errstr(status)));
244                 return status;
245         }
246
247         return NT_STATUS_OK;
248 }
249
250 static bool get_trust_domain_passwords_auth_blob(TALLOC_CTX *mem_ctx,
251                                                  const char *password,
252                                                  DATA_BLOB *auth_blob)
253 {
254         struct trustDomainPasswords auth_struct;
255         struct AuthenticationInformation *auth_info_array;
256         enum ndr_err_code ndr_err;
257         size_t converted_size;
258
259         generate_random_buffer(auth_struct.confounder,
260                                sizeof(auth_struct.confounder));
261
262         auth_info_array = talloc_array(mem_ctx,
263                                        struct AuthenticationInformation, 1);
264         if (auth_info_array == NULL) {
265                 return false;
266         }
267
268         auth_info_array[0].AuthType = TRUST_AUTH_TYPE_CLEAR;
269         if (!convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, password,
270                                   strlen(password),
271                                   &auth_info_array[0].AuthInfo.clear.password,
272                                   &converted_size)) {
273                 return false;
274         }
275
276         auth_info_array[0].AuthInfo.clear.size = converted_size;
277
278         auth_struct.outgoing.count = 1;
279         auth_struct.outgoing.current.count = 1;
280         auth_struct.outgoing.current.array = auth_info_array;
281         auth_struct.outgoing.previous.count = 0;
282         auth_struct.outgoing.previous.array = NULL;
283
284         auth_struct.incoming.count = 1;
285         auth_struct.incoming.current.count = 1;
286         auth_struct.incoming.current.array = auth_info_array;
287         auth_struct.incoming.previous.count = 0;
288         auth_struct.incoming.previous.array = NULL;
289
290         ndr_err = ndr_push_struct_blob(auth_blob, mem_ctx, &auth_struct,
291                                        (ndr_push_flags_fn_t)ndr_push_trustDomainPasswords);
292         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
293                 return false;
294         }
295
296         return true;
297 }
298
299 static int parse_trust_args(TALLOC_CTX *mem_ctx, int argc, const char **argv, struct other_dom_data **_o, char **_trustpw)
300 {
301         size_t c;
302         struct other_dom_data *o = NULL;
303         char *trustpw = NULL;
304         int ret = EFAULT;
305
306         if (argc == 0) {
307                 return EINVAL;
308         }
309
310         o = talloc_zero(mem_ctx, struct other_dom_data);
311         if (o == NULL) {
312                 DEBUG(0, ("talloc_zero failed.\n"));
313                 return ENOMEM;
314         }
315
316         for (c = 0; c < argc; c++) {
317                 if (strnequal(argv[c], ARG_OTHERSERVER, sizeof(ARG_OTHERSERVER)-1)) {
318                         o->host = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERSERVER)-1);
319                         if (o->host == NULL) {
320                                 ret = ENOMEM;
321                                 goto failed;
322                         }
323                 } else if (strnequal(argv[c], ARG_OTHERUSER, sizeof(ARG_OTHERUSER)-1)) {
324                         o->user_name = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERUSER)-1);
325                         if (o->user_name == NULL) {
326                                 ret = ENOMEM;
327                                 goto failed;
328                         }
329                 } else if (strnequal(argv[c], ARG_OTHERDOMAINSID, sizeof(ARG_OTHERDOMAINSID)-1)) {
330                         o->domain_sid_str = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERDOMAINSID)-1);
331                         if (o->domain_sid_str == NULL) {
332                                 ret = ENOMEM;
333                                 goto failed;
334                         }
335                 } else if (strnequal(argv[c], ARG_OTHERDOMAIN, sizeof(ARG_OTHERDOMAIN)-1)) {
336                         o->dns_domain_name = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERDOMAIN)-1);
337                         if (o->dns_domain_name == NULL) {
338                                 ret = ENOMEM;
339                                 goto failed;
340                         }
341                 } else if (strnequal(argv[c], ARG_OTHERNETBIOSDOMAIN, sizeof(ARG_OTHERNETBIOSDOMAIN)-1)) {
342                         o->domain_name = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERNETBIOSDOMAIN)-1);
343                         if (o->domain_name == NULL) {
344                                 ret = ENOMEM;
345                                 goto failed;
346                         }
347                 } else if (strnequal(argv[c], ARG_TRUSTPW, sizeof(ARG_TRUSTPW)-1)) {
348                         trustpw = talloc_strdup(mem_ctx, argv[c] + sizeof(ARG_TRUSTPW)-1);
349                         if (trustpw == NULL) {
350                                 ret = ENOMEM;
351                                 goto failed;
352                         }
353                 } else {
354                         DEBUG(0, ("Unsupported option [%s].\n", argv[c]));
355                         ret = EINVAL;
356                         goto failed;
357                 }
358         }
359
360         *_o = o;
361         *_trustpw = trustpw;
362
363         return 0;
364
365 failed:
366         talloc_free(o);
367         talloc_free(trustpw);
368         return ret;
369 }
370
371 static void print_trust_delete_usage(void)
372 {
373         d_printf(  "%s\n"
374                    "net rpc trust delete [options]\n"
375                    "\nOptions:\n"
376                    "\totherserver=DC in other domain\n"
377                    "\totheruser=Admin user in other domain\n"
378                    "\totherdomainsid=SID of other domain\n"
379                    "\nExamples:\n"
380                    "\tnet rpc trust delete otherserver=oname otheruser=ouser -S lname -U luser\n"
381                    "\tnet rpc trust delete otherdomainsid=S-... -S lname -U luser\n"
382                    "  %s\n",
383                  _("Usage:"),
384                  _("Remove trust between two domains"));
385 }
386
387 static void print_trust_usage(void)
388 {
389         d_printf(  "%s\n"
390                    "net rpc trust create [options]\n"
391                    "\nOptions:\n"
392                    "\totherserver=DC in other domain\n"
393                    "\totheruser=Admin user in other domain\n"
394                    "\totherdomainsid=SID of other domain\n"
395                    "\tother_netbios_domain=NetBIOS/short name of other domain\n"
396                    "\totherdomain=Full/DNS name of other domain\n"
397                    "\ttrustpw=Trust password\n"
398                    "\nExamples:\n"
399                    "\tnet rpc trust create otherserver=oname otheruser=ouser -S lname -U luser\n"
400                    "\tnet rpc trust create otherdomainsid=S-... other_netbios_domain=odom otherdomain=odom.org trustpw=secret -S lname -U luser\n"
401                    "  %s\n",
402                  _("Usage:"),
403                  _("Create trust between two domains"));
404 }
405
406 static int rpc_trust_common(struct net_context *net_ctx, int argc,
407                             const char **argv, enum trust_op op)
408 {
409         TALLOC_CTX *mem_ctx;
410         NTSTATUS status;
411         int ret;
412         int success = -1;
413         struct cli_state *cli[2] = {NULL, NULL};
414         struct rpc_pipe_client *pipe_hnd[2] = {NULL, NULL};
415         struct policy_handle pol_hnd[2];
416         struct lsa_TrustDomainInfoAuthInfoInternal authinfo;
417         DATA_BLOB auth_blob;
418         char *trust_pw = NULL;
419         struct other_dom_data *other_dom_data;
420         struct net_context *other_net_ctx = NULL;
421         struct dom_data dom_data[2];
422         void (*usage)(void);
423
424         switch (op) {
425                 case TRUST_CREATE:
426                         usage = print_trust_usage;
427                         break;
428                 case TRUST_DELETE:
429                         usage = print_trust_delete_usage;
430                         break;
431                 default:
432                         DEBUG(0, ("Unsupported trust operation.\n"));
433                         return -1;
434         }
435
436         if (net_ctx->display_usage) {
437                 usage();
438                 return 0;
439         }
440
441         mem_ctx = talloc_init("trust op");
442         if (mem_ctx == NULL) {
443                 DEBUG(0, ("talloc_init failed.\n"));
444                 return -1;
445         }
446
447         ret = parse_trust_args(mem_ctx, argc, argv, &other_dom_data, &trust_pw);
448         if (ret != 0) {
449                 if (ret == EINVAL) {
450                         usage();
451                 } else {
452                         DEBUG(0, ("Failed to parse arguments.\n"));
453                 }
454                 goto done;
455         }
456
457         if (other_dom_data->host != 0) {
458                 other_net_ctx = talloc_zero(other_dom_data, struct net_context);
459                 if (other_net_ctx == NULL) {
460                         DEBUG(0, ("talloc_zero failed.\n"));
461                         goto done;
462                 }
463
464                 other_net_ctx->opt_host = other_dom_data->host;
465                 other_net_ctx->opt_user_name = other_dom_data->user_name;
466         } else {
467                 dom_data[1].domsid = dom_sid_parse_talloc(mem_ctx,
468                                                 other_dom_data->domain_sid_str);
469                 dom_data[1].domain_name = other_dom_data->domain_name;
470                 dom_data[1].dns_domain_name = other_dom_data->dns_domain_name;
471
472                 if (dom_data[1].domsid == NULL ||
473                     (op == TRUST_CREATE &&
474                      (dom_data[1].domain_name == NULL ||
475                       dom_data[1].dns_domain_name == NULL))) {
476                         DEBUG(0, ("Missing required argument.\n"));
477                         usage();
478                         goto done;
479                 }
480         }
481
482         status = connect_and_get_info(mem_ctx, net_ctx, &cli[0], &pipe_hnd[0],
483                                       &pol_hnd[0], &dom_data[0]);
484         if (!NT_STATUS_IS_OK(status)) {
485                 DEBUG(0, ("connect_and_get_info failed with error [%s]\n",
486                           nt_errstr(status)));
487                 goto done;
488         }
489
490         if (other_net_ctx != NULL) {
491                 status = connect_and_get_info(mem_ctx, other_net_ctx,
492                                               &cli[1], &pipe_hnd[1],
493                                               &pol_hnd[1], &dom_data[1]);
494                 if (!NT_STATUS_IS_OK(status)) {
495                         DEBUG(0, ("connect_and_get_info failed with error [%s]\n",
496                                   nt_errstr(status)));
497                         goto done;
498                 }
499         }
500
501         if (op == TRUST_CREATE) {
502                 if (trust_pw == NULL) {
503                         if (other_net_ctx == NULL) {
504                                 DEBUG(0, ("Missing either trustpw or otherhost.\n"));
505                                 goto done;
506                         }
507
508                         DEBUG(0, ("Using random trust password.\n"));
509         /* FIXME: why only 8 characters work? Would it be possible to use a
510          * random binary password? */
511                         trust_pw = generate_random_str(mem_ctx, 8);
512                         if (trust_pw == NULL) {
513                                 DEBUG(0, ("generate_random_str failed.\n"));
514                                 goto done;
515                         }
516                 } else {
517                         DEBUG(0, ("Using user provided password.\n"));
518                 }
519
520                 if (!get_trust_domain_passwords_auth_blob(mem_ctx, trust_pw,
521                                                           &auth_blob)) {
522                         DEBUG(0, ("get_trust_domain_passwords_auth_blob failed\n"));
523                         goto done;
524                 }
525
526                 authinfo.auth_blob.data = (uint8_t *)talloc_memdup(
527                                                         mem_ctx,
528                                                         auth_blob.data,
529                                                         auth_blob.length);
530                 if (authinfo.auth_blob.data == NULL) {
531                         goto done;
532                 }
533                 authinfo.auth_blob.size = auth_blob.length;
534
535                 arcfour_crypt_blob(authinfo.auth_blob.data,
536                                    authinfo.auth_blob.size,
537                                    &cli[0]->user_session_key);
538
539                 status = create_trust(mem_ctx, pipe_hnd[0]->binding_handle,
540                                       &pol_hnd[0],
541                                       dom_data[1].domain_name,
542                                       dom_data[1].dns_domain_name,
543                                       dom_data[1].domsid,
544                                       &authinfo);
545                 if (!NT_STATUS_IS_OK(status)) {
546                         DEBUG(0, ("create_trust failed with error [%s].\n",
547                         nt_errstr(status)));
548                         goto done;
549                 }
550
551                 if (other_net_ctx != NULL) {
552                         talloc_free(authinfo.auth_blob.data);
553                         authinfo.auth_blob.data = (uint8_t *)talloc_memdup(
554                                                                 mem_ctx,
555                                                                 auth_blob.data,
556                                                                 auth_blob.length);
557                         if (authinfo.auth_blob.data == NULL) {
558                                 goto done;
559                         }
560                         authinfo.auth_blob.size = auth_blob.length;
561
562                         arcfour_crypt_blob(authinfo.auth_blob.data,
563                                            authinfo.auth_blob.size,
564                                            &cli[1]->user_session_key);
565
566                         status = create_trust(mem_ctx,
567                                               pipe_hnd[1]->binding_handle,
568                                               &pol_hnd[1],
569                                               dom_data[0].domain_name,
570                                               dom_data[0].dns_domain_name,
571                                               dom_data[0].domsid, &authinfo);
572                         if (!NT_STATUS_IS_OK(status)) {
573                                 DEBUG(0, ("create_trust failed with error [%s].\n",
574                                 nt_errstr(status)));
575                                 goto done;
576                         }
577                 }
578         } else if (op == TRUST_DELETE) {
579                 status = delete_trust(mem_ctx, pipe_hnd[0]->binding_handle,
580                                       &pol_hnd[0], dom_data[1].domsid);
581                 if (!NT_STATUS_IS_OK(status)) {
582                         DEBUG(0, ("delete_trust failed with [%s].\n",
583                                   nt_errstr(status)));
584                         goto done;
585                 }
586
587                 if (other_net_ctx != NULL) {
588                         status = delete_trust(mem_ctx,
589                                               pipe_hnd[1]->binding_handle,
590                                               &pol_hnd[1], dom_data[0].domsid);
591                         if (!NT_STATUS_IS_OK(status)) {
592                                 DEBUG(0, ("delete_trust failed with [%s].\n",
593                                           nt_errstr(status)));
594                                 goto done;
595                         }
596                 }
597         }
598
599         status = close_handle(mem_ctx, pipe_hnd[0]->binding_handle,
600                               &pol_hnd[0]);
601         if (!NT_STATUS_IS_OK(status)) {
602                 DEBUG(0, ("close_handle failed with error [%s].\n",
603                           nt_errstr(status)));
604                 goto done;
605         }
606
607         if (other_net_ctx != NULL) {
608                 status = close_handle(mem_ctx, pipe_hnd[1]->binding_handle,
609                                       &pol_hnd[1]);
610                 if (!NT_STATUS_IS_OK(status)) {
611                         DEBUG(0, ("close_handle failed with error [%s].\n",
612                                   nt_errstr(status)));
613                         goto done;
614                 }
615         }
616
617         success = 0;
618
619 done:
620         cli_shutdown(cli[0]);
621         cli_shutdown(cli[1]);
622         talloc_destroy(mem_ctx);
623         return success;
624 }
625
626 static int rpc_trust_create(struct net_context *net_ctx, int argc,
627                             const char **argv)
628 {
629         return rpc_trust_common(net_ctx, argc, argv, TRUST_CREATE);
630 }
631
632 static int rpc_trust_delete(struct net_context *net_ctx, int argc,
633                             const char **argv)
634 {
635         return rpc_trust_common(net_ctx, argc, argv, TRUST_DELETE);
636 }
637
638 int net_rpc_trust(struct net_context *c, int argc, const char **argv)
639 {
640         struct functable func[] = {
641                 {
642                         "create",
643                         rpc_trust_create,
644                         NET_TRANSPORT_RPC,
645                         N_("Create trusts"),
646                         N_("net rpc trust create\n"
647                            "    Create trusts")
648                 },
649                 {
650                         "delete",
651                         rpc_trust_delete,
652                         NET_TRANSPORT_RPC,
653                         N_("Remove trusts"),
654                         N_("net rpc trust delete\n"
655                            "    Remove trusts")
656                 },
657                 {NULL, NULL, 0, NULL, NULL}
658         };
659
660         return net_run_function(c, argc, argv, "net rpc trust", func);
661 }