dbwrap_tool: Simplify dbwrap_tool_erase
[garming/samba-autobuild/.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                                      DATA_BLOB *session_key)
201 {
202         NTSTATUS status;
203         NTSTATUS result;
204
205         status = net_make_ipc_connection_ex(net_ctx, NULL, NULL, NULL,
206                                             NET_FLAGS_PDC, cli);
207         if (!NT_STATUS_IS_OK(status)) {
208                 DEBUG(0, ("Failed to connect to [%s] with error [%s]\n",
209                           net_ctx->opt_host, nt_errstr(status)));
210                 return status;
211         }
212
213         status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc, pipe_hnd);
214         if (!NT_STATUS_IS_OK(status)) {
215                 DEBUG(0, ("Failed to initialise lsa pipe with error [%s]\n",
216                           nt_errstr(status)));
217                 return status;
218         }
219
220         status = dcerpc_lsa_open_policy2((*pipe_hnd)->binding_handle,
221                                          mem_ctx,
222                                          (*pipe_hnd)->srv_name_slash,
223                                          false,
224                                          (LSA_POLICY_VIEW_LOCAL_INFORMATION |
225                                           LSA_POLICY_TRUST_ADMIN |
226                                           LSA_POLICY_CREATE_SECRET),
227                                          pol_hnd,
228                                          &result);
229         if (!NT_STATUS_IS_OK(status)) {
230                 DEBUG(0, ("Failed to open policy handle with error [%s]\n",
231                           nt_errstr(status)));
232                 return status;
233         }
234         if (!NT_STATUS_IS_OK(result)) {
235                 DEBUG(0, ("lsa_open_policy2 with error [%s]\n",
236                           nt_errstr(result)));
237                 return result;
238         }
239
240         status = get_domain_info(mem_ctx, (*pipe_hnd)->binding_handle,
241                                  pol_hnd, dom_data);
242         if (!NT_STATUS_IS_OK(status)) {
243                 DEBUG(0, ("get_domain_info failed with error [%s].\n",
244                           nt_errstr(status)));
245                 return status;
246         }
247
248         status = cli_get_session_key(mem_ctx, *pipe_hnd, session_key);
249         if (!NT_STATUS_IS_OK(status)) {
250                 DEBUG(0,("Error getting session_key of LSA pipe. Error was %s\n",
251                         nt_errstr(status)));
252                 return status;
253         }
254
255         return NT_STATUS_OK;
256 }
257
258 static bool get_trust_domain_passwords_auth_blob(TALLOC_CTX *mem_ctx,
259                                                  const char *password,
260                                                  DATA_BLOB *auth_blob)
261 {
262         struct trustDomainPasswords auth_struct;
263         struct AuthenticationInformation *auth_info_array;
264         enum ndr_err_code ndr_err;
265         size_t converted_size;
266
267         generate_random_buffer(auth_struct.confounder,
268                                sizeof(auth_struct.confounder));
269
270         auth_info_array = talloc_array(mem_ctx,
271                                        struct AuthenticationInformation, 1);
272         if (auth_info_array == NULL) {
273                 return false;
274         }
275
276         auth_info_array[0].AuthType = TRUST_AUTH_TYPE_CLEAR;
277         if (!convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, password,
278                                   strlen(password),
279                                   &auth_info_array[0].AuthInfo.clear.password,
280                                   &converted_size)) {
281                 return false;
282         }
283
284         auth_info_array[0].AuthInfo.clear.size = converted_size;
285
286         auth_struct.outgoing.count = 1;
287         auth_struct.outgoing.current.count = 1;
288         auth_struct.outgoing.current.array = auth_info_array;
289         auth_struct.outgoing.previous.count = 0;
290         auth_struct.outgoing.previous.array = NULL;
291
292         auth_struct.incoming.count = 1;
293         auth_struct.incoming.current.count = 1;
294         auth_struct.incoming.current.array = auth_info_array;
295         auth_struct.incoming.previous.count = 0;
296         auth_struct.incoming.previous.array = NULL;
297
298         ndr_err = ndr_push_struct_blob(auth_blob, mem_ctx, &auth_struct,
299                                        (ndr_push_flags_fn_t)ndr_push_trustDomainPasswords);
300         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
301                 return false;
302         }
303
304         return true;
305 }
306
307 static int parse_trust_args(TALLOC_CTX *mem_ctx, int argc, const char **argv, struct other_dom_data **_o, char **_trustpw)
308 {
309         size_t c;
310         struct other_dom_data *o = NULL;
311         char *trustpw = NULL;
312         int ret = EFAULT;
313
314         if (argc == 0) {
315                 return EINVAL;
316         }
317
318         o = talloc_zero(mem_ctx, struct other_dom_data);
319         if (o == NULL) {
320                 DEBUG(0, ("talloc_zero failed.\n"));
321                 return ENOMEM;
322         }
323
324         for (c = 0; c < argc; c++) {
325                 if (strnequal(argv[c], ARG_OTHERSERVER, sizeof(ARG_OTHERSERVER)-1)) {
326                         o->host = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERSERVER)-1);
327                         if (o->host == NULL) {
328                                 ret = ENOMEM;
329                                 goto failed;
330                         }
331                 } else if (strnequal(argv[c], ARG_OTHERUSER, sizeof(ARG_OTHERUSER)-1)) {
332                         o->user_name = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERUSER)-1);
333                         if (o->user_name == NULL) {
334                                 ret = ENOMEM;
335                                 goto failed;
336                         }
337                 } else if (strnequal(argv[c], ARG_OTHERDOMAINSID, sizeof(ARG_OTHERDOMAINSID)-1)) {
338                         o->domain_sid_str = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERDOMAINSID)-1);
339                         if (o->domain_sid_str == NULL) {
340                                 ret = ENOMEM;
341                                 goto failed;
342                         }
343                 } else if (strnequal(argv[c], ARG_OTHERDOMAIN, sizeof(ARG_OTHERDOMAIN)-1)) {
344                         o->dns_domain_name = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERDOMAIN)-1);
345                         if (o->dns_domain_name == NULL) {
346                                 ret = ENOMEM;
347                                 goto failed;
348                         }
349                 } else if (strnequal(argv[c], ARG_OTHERNETBIOSDOMAIN, sizeof(ARG_OTHERNETBIOSDOMAIN)-1)) {
350                         o->domain_name = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERNETBIOSDOMAIN)-1);
351                         if (o->domain_name == NULL) {
352                                 ret = ENOMEM;
353                                 goto failed;
354                         }
355                 } else if (strnequal(argv[c], ARG_TRUSTPW, sizeof(ARG_TRUSTPW)-1)) {
356                         trustpw = talloc_strdup(mem_ctx, argv[c] + sizeof(ARG_TRUSTPW)-1);
357                         if (trustpw == NULL) {
358                                 ret = ENOMEM;
359                                 goto failed;
360                         }
361                 } else {
362                         DEBUG(0, ("Unsupported option [%s].\n", argv[c]));
363                         ret = EINVAL;
364                         goto failed;
365                 }
366         }
367
368         *_o = o;
369         *_trustpw = trustpw;
370
371         return 0;
372
373 failed:
374         talloc_free(o);
375         talloc_free(trustpw);
376         return ret;
377 }
378
379 static void print_trust_delete_usage(void)
380 {
381         d_printf(  "%s\n"
382                    "net rpc trust delete [options]\n"
383                    "\nOptions:\n"
384                    "\totherserver=DC in other domain\n"
385                    "\totheruser=Admin user in other domain\n"
386                    "\totherdomainsid=SID of other domain\n"
387                    "\nExamples:\n"
388                    "\tnet rpc trust delete otherserver=oname otheruser=ouser -S lname -U luser\n"
389                    "\tnet rpc trust delete otherdomainsid=S-... -S lname -U luser\n"
390                    "  %s\n",
391                  _("Usage:"),
392                  _("Remove trust between two domains"));
393 }
394
395 static void print_trust_usage(void)
396 {
397         d_printf(  "%s\n"
398                    "net rpc trust create [options]\n"
399                    "\nOptions:\n"
400                    "\totherserver=DC in other domain\n"
401                    "\totheruser=Admin user in other domain\n"
402                    "\totherdomainsid=SID of other domain\n"
403                    "\tother_netbios_domain=NetBIOS/short name of other domain\n"
404                    "\totherdomain=Full/DNS name of other domain\n"
405                    "\ttrustpw=Trust password\n"
406                    "\nExamples:\n"
407                    "\tnet rpc trust create otherserver=oname otheruser=ouser -S lname -U luser\n"
408                    "\tnet rpc trust create otherdomainsid=S-... other_netbios_domain=odom otherdomain=odom.org trustpw=secret -S lname -U luser\n"
409                    "  %s\n",
410                  _("Usage:"),
411                  _("Create trust between two domains"));
412 }
413
414 static int rpc_trust_common(struct net_context *net_ctx, int argc,
415                             const char **argv, enum trust_op op)
416 {
417         TALLOC_CTX *mem_ctx;
418         NTSTATUS status;
419         int ret;
420         int success = -1;
421         struct cli_state *cli[2] = {NULL, NULL};
422         struct rpc_pipe_client *pipe_hnd[2] = {NULL, NULL};
423         DATA_BLOB session_key[2];
424         struct policy_handle pol_hnd[2];
425         struct lsa_TrustDomainInfoAuthInfoInternal authinfo;
426         DATA_BLOB auth_blob;
427         char *trust_pw = NULL;
428         struct other_dom_data *other_dom_data;
429         struct net_context *other_net_ctx = NULL;
430         struct dom_data dom_data[2];
431         void (*usage)(void);
432
433         ZERO_STRUCT(session_key);
434
435         switch (op) {
436                 case TRUST_CREATE:
437                         usage = print_trust_usage;
438                         break;
439                 case TRUST_DELETE:
440                         usage = print_trust_delete_usage;
441                         break;
442                 default:
443                         DEBUG(0, ("Unsupported trust operation.\n"));
444                         return -1;
445         }
446
447         if (net_ctx->display_usage) {
448                 usage();
449                 return 0;
450         }
451
452         mem_ctx = talloc_init("trust op");
453         if (mem_ctx == NULL) {
454                 DEBUG(0, ("talloc_init failed.\n"));
455                 return -1;
456         }
457
458         ret = parse_trust_args(mem_ctx, argc, argv, &other_dom_data, &trust_pw);
459         if (ret != 0) {
460                 if (ret == EINVAL) {
461                         usage();
462                 } else {
463                         DEBUG(0, ("Failed to parse arguments.\n"));
464                 }
465                 goto done;
466         }
467
468         if (other_dom_data->host != 0) {
469                 other_net_ctx = talloc_zero(other_dom_data, struct net_context);
470                 if (other_net_ctx == NULL) {
471                         DEBUG(0, ("talloc_zero failed.\n"));
472                         goto done;
473                 }
474
475                 other_net_ctx->opt_host = other_dom_data->host;
476                 other_net_ctx->opt_user_name = other_dom_data->user_name;
477         } else {
478                 dom_data[1].domsid = dom_sid_parse_talloc(mem_ctx,
479                                                 other_dom_data->domain_sid_str);
480                 dom_data[1].domain_name = other_dom_data->domain_name;
481                 dom_data[1].dns_domain_name = other_dom_data->dns_domain_name;
482
483                 if (dom_data[1].domsid == NULL ||
484                     (op == TRUST_CREATE &&
485                      (dom_data[1].domain_name == NULL ||
486                       dom_data[1].dns_domain_name == NULL))) {
487                         DEBUG(0, ("Missing required argument.\n"));
488                         usage();
489                         goto done;
490                 }
491         }
492
493         status = connect_and_get_info(mem_ctx, net_ctx, &cli[0], &pipe_hnd[0],
494                                       &pol_hnd[0], &dom_data[0], &session_key[0]);
495         if (!NT_STATUS_IS_OK(status)) {
496                 DEBUG(0, ("connect_and_get_info failed with error [%s]\n",
497                           nt_errstr(status)));
498                 goto done;
499         }
500
501         if (other_net_ctx != NULL) {
502                 status = connect_and_get_info(mem_ctx, other_net_ctx,
503                                               &cli[1], &pipe_hnd[1],
504                                               &pol_hnd[1], &dom_data[1],
505                                               &session_key[1]);
506                 if (!NT_STATUS_IS_OK(status)) {
507                         DEBUG(0, ("connect_and_get_info failed with error [%s]\n",
508                                   nt_errstr(status)));
509                         goto done;
510                 }
511         }
512
513         if (op == TRUST_CREATE) {
514                 if (trust_pw == NULL) {
515                         if (other_net_ctx == NULL) {
516                                 DEBUG(0, ("Missing either trustpw or otherhost.\n"));
517                                 goto done;
518                         }
519
520                         DEBUG(0, ("Using random trust password.\n"));
521                         trust_pw = trust_pw_new_value(mem_ctx,
522                                                       SEC_CHAN_DOMAIN,
523                                                       SEC_DOMAIN);
524                         if (trust_pw == NULL) {
525                                 DEBUG(0, ("generate_random_password failed.\n"));
526                                 goto done;
527                         }
528                 } else {
529                         DEBUG(0, ("Using user provided password.\n"));
530                 }
531
532                 if (!get_trust_domain_passwords_auth_blob(mem_ctx, trust_pw,
533                                                           &auth_blob)) {
534                         DEBUG(0, ("get_trust_domain_passwords_auth_blob failed\n"));
535                         goto done;
536                 }
537
538                 authinfo.auth_blob.data = (uint8_t *)talloc_memdup(
539                                                         mem_ctx,
540                                                         auth_blob.data,
541                                                         auth_blob.length);
542                 if (authinfo.auth_blob.data == NULL) {
543                         goto done;
544                 }
545                 authinfo.auth_blob.size = auth_blob.length;
546
547                 arcfour_crypt_blob(authinfo.auth_blob.data,
548                                    authinfo.auth_blob.size,
549                                    &session_key[0]);
550
551                 status = create_trust(mem_ctx, pipe_hnd[0]->binding_handle,
552                                       &pol_hnd[0],
553                                       dom_data[1].domain_name,
554                                       dom_data[1].dns_domain_name,
555                                       dom_data[1].domsid,
556                                       &authinfo);
557                 if (!NT_STATUS_IS_OK(status)) {
558                         DEBUG(0, ("create_trust failed with error [%s].\n",
559                         nt_errstr(status)));
560                         goto done;
561                 }
562
563                 if (other_net_ctx != NULL) {
564                         talloc_free(authinfo.auth_blob.data);
565                         authinfo.auth_blob.data = (uint8_t *)talloc_memdup(
566                                                                 mem_ctx,
567                                                                 auth_blob.data,
568                                                                 auth_blob.length);
569                         if (authinfo.auth_blob.data == NULL) {
570                                 goto done;
571                         }
572                         authinfo.auth_blob.size = auth_blob.length;
573
574                         arcfour_crypt_blob(authinfo.auth_blob.data,
575                                            authinfo.auth_blob.size,
576                                            &session_key[1]);
577
578                         status = create_trust(mem_ctx,
579                                               pipe_hnd[1]->binding_handle,
580                                               &pol_hnd[1],
581                                               dom_data[0].domain_name,
582                                               dom_data[0].dns_domain_name,
583                                               dom_data[0].domsid, &authinfo);
584                         if (!NT_STATUS_IS_OK(status)) {
585                                 DEBUG(0, ("create_trust failed with error [%s].\n",
586                                 nt_errstr(status)));
587                                 goto done;
588                         }
589                 }
590         } else if (op == TRUST_DELETE) {
591                 status = delete_trust(mem_ctx, pipe_hnd[0]->binding_handle,
592                                       &pol_hnd[0], dom_data[1].domsid);
593                 if (!NT_STATUS_IS_OK(status)) {
594                         DEBUG(0, ("delete_trust failed with [%s].\n",
595                                   nt_errstr(status)));
596                         goto done;
597                 }
598
599                 if (other_net_ctx != NULL) {
600                         status = delete_trust(mem_ctx,
601                                               pipe_hnd[1]->binding_handle,
602                                               &pol_hnd[1], dom_data[0].domsid);
603                         if (!NT_STATUS_IS_OK(status)) {
604                                 DEBUG(0, ("delete_trust failed with [%s].\n",
605                                           nt_errstr(status)));
606                                 goto done;
607                         }
608                 }
609         }
610
611         status = close_handle(mem_ctx, pipe_hnd[0]->binding_handle,
612                               &pol_hnd[0]);
613         if (!NT_STATUS_IS_OK(status)) {
614                 DEBUG(0, ("close_handle failed with error [%s].\n",
615                           nt_errstr(status)));
616                 goto done;
617         }
618
619         if (other_net_ctx != NULL) {
620                 status = close_handle(mem_ctx, pipe_hnd[1]->binding_handle,
621                                       &pol_hnd[1]);
622                 if (!NT_STATUS_IS_OK(status)) {
623                         DEBUG(0, ("close_handle failed with error [%s].\n",
624                                   nt_errstr(status)));
625                         goto done;
626                 }
627         }
628
629         success = 0;
630
631 done:
632         data_blob_clear_free(&session_key[0]);
633         data_blob_clear_free(&session_key[1]);
634         cli_shutdown(cli[0]);
635         cli_shutdown(cli[1]);
636         talloc_destroy(mem_ctx);
637         return success;
638 }
639
640 static int rpc_trust_create(struct net_context *net_ctx, int argc,
641                             const char **argv)
642 {
643         return rpc_trust_common(net_ctx, argc, argv, TRUST_CREATE);
644 }
645
646 static int rpc_trust_delete(struct net_context *net_ctx, int argc,
647                             const char **argv)
648 {
649         return rpc_trust_common(net_ctx, argc, argv, TRUST_DELETE);
650 }
651
652 int net_rpc_trust(struct net_context *c, int argc, const char **argv)
653 {
654         struct functable func[] = {
655                 {
656                         "create",
657                         rpc_trust_create,
658                         NET_TRANSPORT_RPC,
659                         N_("Create trusts"),
660                         N_("net rpc trust create\n"
661                            "    Create trusts")
662                 },
663                 {
664                         "delete",
665                         rpc_trust_delete,
666                         NET_TRANSPORT_RPC,
667                         N_("Remove trusts"),
668                         N_("net rpc trust delete\n"
669                            "    Remove trusts")
670                 },
671                 {NULL, NULL, 0, NULL, NULL}
672         };
673
674         return net_run_function(c, argc, argv, "net rpc trust", func);
675 }