s3:util:net_registry: registry_value_cmp() uses NUMERIC_CMP()
[samba.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 "../libcli/security/dom_sid.h"
27 #include "libsmb/libsmb.h"
28
29 #include "lib/crypto/gnutls_helpers.h"
30 #include <gnutls/gnutls.h>
31 #include <gnutls/crypto.h>
32
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="
39
40 enum trust_op {
41         TRUST_CREATE,
42         TRUST_DELETE
43 };
44
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;
51 };
52
53 struct dom_data {
54         struct dom_sid *domsid;
55         char *dns_domain_name;
56         char *domain_name;
57 };
58
59 static NTSTATUS close_handle(TALLOC_CTX *mem_ctx,
60                              struct dcerpc_binding_handle *bind_hnd,
61                              struct policy_handle *pol_hnd)
62 {
63         NTSTATUS status;
64         NTSTATUS result;
65
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;
71         }
72         if (!NT_STATUS_IS_OK(result)) {
73                 DEBUG(0, ("lsa close failed with error [%s].\n",
74                           nt_errstr(result)));
75                 return result;
76         }
77
78         return NT_STATUS_OK;
79 }
80
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)
85 {
86         NTSTATUS status;
87         struct lsa_DeleteTrustedDomain dr;
88
89         dr.in.handle = pol_hnd;
90         dr.in.dom_sid = domsid;
91
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;
97         }
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;
102         }
103
104         return NT_STATUS_OK;
105 }
106
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)
114 {
115         NTSTATUS status;
116         struct lsa_CreateTrustedDomainEx2 r;
117         struct lsa_TrustDomainInfoInfoEx trustinfo;
118         struct policy_handle trustdom_handle;
119         bool is_nt4 = trust_name_dns == NULL;
120
121         if (!is_nt4) {
122                 fprintf(stdout, "Creating AD trust\n");
123                 trustinfo.trust_type = LSA_TRUST_TYPE_UPLEVEL;
124                 trustinfo.trust_attributes = LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE;
125         } else {
126                 fprintf(stdout, "Creating NT4 trust\n");
127                 trustinfo.trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
128                 trustinfo.trust_attributes = 0;
129                 trust_name_dns = trust_name;
130         }
131
132         trustinfo.sid = domsid;
133         trustinfo.netbios_name.string = trust_name;
134         trustinfo.domain_name.string = trust_name_dns;
135
136         trustinfo.trust_direction = LSA_TRUST_DIRECTION_INBOUND |
137                                     LSA_TRUST_DIRECTION_OUTBOUND;
138
139         r.in.policy_handle = pol_hnd;
140         r.in.info = &trustinfo;
141         r.in.auth_info_internal = authinfo;
142         r.in.access_mask = LSA_TRUSTED_SET_POSIX | LSA_TRUSTED_SET_AUTH |
143                            LSA_TRUSTED_QUERY_DOMAIN_NAME;
144         r.out.trustdom_handle = &trustdom_handle;
145
146         status = dcerpc_lsa_CreateTrustedDomainEx2_r(bind_hnd, mem_ctx, &r);
147         if (!NT_STATUS_IS_OK(status)) {
148                 DEBUG(0, ("dcerpc_lsa_CreateTrustedDomainEx2_r failed "
149                           "with error [%s].\n", nt_errstr(status)));
150                 return status;
151         }
152         if (!NT_STATUS_IS_OK(r.out.result)) {
153                 DEBUG(0, ("CreateTrustedDomainEx2_r returned [%s].\n",
154                           nt_errstr(r.out.result)));
155                 return r.out.result;
156         }
157
158         return NT_STATUS_OK;
159 }
160
161 static NTSTATUS get_domain_info(TALLOC_CTX *mem_ctx,
162                                 struct dcerpc_binding_handle *bind_hdn,
163                                 struct policy_handle *pol_hnd,
164                                 struct dom_data *dom_data)
165 {
166         NTSTATUS status;
167         struct lsa_QueryInfoPolicy2 qr;
168         struct dom_sid_buf buf;
169
170         qr.in.handle = pol_hnd;
171         qr.in.level = LSA_POLICY_INFO_DNS;
172
173         status = dcerpc_lsa_QueryInfoPolicy2_r(bind_hdn, mem_ctx, &qr);
174         if (!NT_STATUS_IS_OK(status)) {
175                 DEBUG(0, ("dcerpc_lsa_QueryInfoPolicy2_r failed "
176                           "with error [%s].\n", nt_errstr(status)));
177                 return status;
178         }
179
180         if (!NT_STATUS_IS_OK(qr.out.result)) {
181                 DEBUG(0, ("QueryInfoPolicy2 returned [%s].\n",
182                           nt_errstr(qr.out.result)));
183                 return qr.out.result;
184         }
185
186         dom_data->domain_name = talloc_strdup(mem_ctx,
187                                               (*qr.out.info)->dns.name.string);
188         dom_data->dns_domain_name = talloc_strdup(mem_ctx,
189                                          (*qr.out.info)->dns.dns_domain.string);
190         dom_data->domsid = dom_sid_dup(mem_ctx, (*qr.out.info)->dns.sid);
191         if (dom_data->domain_name == NULL ||
192             dom_data->dns_domain_name == NULL ||
193             dom_data->domsid == NULL) {
194                 DEBUG(0, ("Copying domain data failed.\n"));
195                 return NT_STATUS_NO_MEMORY;
196         }
197
198         DEBUG(0, ("Got the following domain info [%s][%s][%s].\n",
199                   dom_data->domain_name, dom_data->dns_domain_name,
200                   dom_sid_str_buf(dom_data->domsid, &buf)));
201
202         return NT_STATUS_OK;
203 }
204
205 static NTSTATUS connect_and_get_info(TALLOC_CTX *mem_ctx,
206                                      struct net_context *net_ctx,
207                                      struct cli_state **cli,
208                                      struct rpc_pipe_client **pipe_hnd,
209                                      struct policy_handle *pol_hnd,
210                                      struct dom_data *dom_data,
211                                      DATA_BLOB *session_key)
212 {
213         NTSTATUS status;
214         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
215         uint32_t out_version = 0;
216         union lsa_revision_info out_revision_info = {
217                 .info1 = {
218                         .revision = 0,
219                 },
220         };
221
222         status = net_make_ipc_connection_ex(net_ctx, NULL, NULL, NULL,
223                                             NET_FLAGS_PDC, cli);
224         if (!NT_STATUS_IS_OK(status)) {
225                 DEBUG(0, ("Failed to connect to [%s] with error [%s]\n",
226                           net_ctx->opt_host, nt_errstr(status)));
227                 return status;
228         }
229
230         status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc, pipe_hnd);
231         if (!NT_STATUS_IS_OK(status)) {
232                 DEBUG(0, ("Failed to initialise lsa pipe with error [%s]\n",
233                           nt_errstr(status)));
234                 return status;
235         }
236
237         status = dcerpc_lsa_open_policy_fallback(
238                 (*pipe_hnd)->binding_handle,
239                 mem_ctx,
240                 (*pipe_hnd)->srv_name_slash,
241                 false,
242                 LSA_POLICY_VIEW_LOCAL_INFORMATION |
243                 LSA_POLICY_TRUST_ADMIN |
244                 LSA_POLICY_CREATE_SECRET,
245                 &out_version,
246                 &out_revision_info,
247                 pol_hnd,
248                 &result);
249         if (any_nt_status_not_ok(status, result, &status)) {
250                 DBG_ERR("Failed to open policy handle: %s\n",
251                         nt_errstr(result));
252                 return status;
253         }
254
255         status = get_domain_info(mem_ctx, (*pipe_hnd)->binding_handle,
256                                  pol_hnd, dom_data);
257         if (!NT_STATUS_IS_OK(status)) {
258                 DEBUG(0, ("get_domain_info failed with error [%s].\n",
259                           nt_errstr(status)));
260                 return status;
261         }
262
263         status = cli_get_session_key(mem_ctx, *pipe_hnd, session_key);
264         if (!NT_STATUS_IS_OK(status)) {
265                 DEBUG(0,("Error getting session_key of LSA pipe. Error was %s\n",
266                         nt_errstr(status)));
267                 return status;
268         }
269
270         return NT_STATUS_OK;
271 }
272
273 static bool get_trust_domain_passwords_auth_blob(TALLOC_CTX *mem_ctx,
274                                                  const char *password,
275                                                  DATA_BLOB *auth_blob)
276 {
277         struct trustDomainPasswords auth_struct;
278         struct AuthenticationInformation *auth_info_array;
279         enum ndr_err_code ndr_err;
280         size_t converted_size;
281
282         generate_random_buffer(auth_struct.confounder,
283                                sizeof(auth_struct.confounder));
284
285         auth_info_array = talloc_array(mem_ctx,
286                                        struct AuthenticationInformation, 1);
287         if (auth_info_array == NULL) {
288                 return false;
289         }
290
291         auth_info_array[0].AuthType = TRUST_AUTH_TYPE_CLEAR;
292         if (!convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16, password,
293                                   strlen(password),
294                                   &auth_info_array[0].AuthInfo.clear.password,
295                                   &converted_size)) {
296                 return false;
297         }
298
299         auth_info_array[0].AuthInfo.clear.size = converted_size;
300
301         auth_struct.outgoing.count = 1;
302         auth_struct.outgoing.current.count = 1;
303         auth_struct.outgoing.current.array = auth_info_array;
304         auth_struct.outgoing.previous.count = 0;
305         auth_struct.outgoing.previous.array = NULL;
306
307         auth_struct.incoming.count = 1;
308         auth_struct.incoming.current.count = 1;
309         auth_struct.incoming.current.array = auth_info_array;
310         auth_struct.incoming.previous.count = 0;
311         auth_struct.incoming.previous.array = NULL;
312
313         ndr_err = ndr_push_struct_blob(auth_blob, mem_ctx, &auth_struct,
314                                        (ndr_push_flags_fn_t)ndr_push_trustDomainPasswords);
315         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
316                 return false;
317         }
318
319         return true;
320 }
321
322 static int parse_trust_args(TALLOC_CTX *mem_ctx, int argc, const char **argv, struct other_dom_data **_o, char **_trustpw)
323 {
324         size_t c;
325         struct other_dom_data *o = NULL;
326         char *trustpw = NULL;
327         int ret = EFAULT;
328
329         if (argc == 0) {
330                 return EINVAL;
331         }
332
333         o = talloc_zero(mem_ctx, struct other_dom_data);
334         if (o == NULL) {
335                 DEBUG(0, ("talloc_zero failed.\n"));
336                 return ENOMEM;
337         }
338
339         for (c = 0; c < argc; c++) {
340                 if (strnequal(argv[c], ARG_OTHERSERVER, sizeof(ARG_OTHERSERVER)-1)) {
341                         o->host = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERSERVER)-1);
342                         if (o->host == NULL) {
343                                 ret = ENOMEM;
344                                 goto failed;
345                         }
346                 } else if (strnequal(argv[c], ARG_OTHERUSER, sizeof(ARG_OTHERUSER)-1)) {
347                         o->user_name = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERUSER)-1);
348                         if (o->user_name == NULL) {
349                                 ret = ENOMEM;
350                                 goto failed;
351                         }
352                 } else if (strnequal(argv[c], ARG_OTHERDOMAINSID, sizeof(ARG_OTHERDOMAINSID)-1)) {
353                         o->domain_sid_str = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERDOMAINSID)-1);
354                         if (o->domain_sid_str == NULL) {
355                                 ret = ENOMEM;
356                                 goto failed;
357                         }
358                 } else if (strnequal(argv[c], ARG_OTHERDOMAIN, sizeof(ARG_OTHERDOMAIN)-1)) {
359                         o->dns_domain_name = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERDOMAIN)-1);
360                         if (o->dns_domain_name == NULL) {
361                                 ret = ENOMEM;
362                                 goto failed;
363                         }
364                 } else if (strnequal(argv[c], ARG_OTHERNETBIOSDOMAIN, sizeof(ARG_OTHERNETBIOSDOMAIN)-1)) {
365                         o->domain_name = talloc_strdup(o, argv[c] + sizeof(ARG_OTHERNETBIOSDOMAIN)-1);
366                         if (o->domain_name == NULL) {
367                                 ret = ENOMEM;
368                                 goto failed;
369                         }
370                 } else if (strnequal(argv[c], ARG_TRUSTPW, sizeof(ARG_TRUSTPW)-1)) {
371                         trustpw = talloc_strdup(mem_ctx, argv[c] + sizeof(ARG_TRUSTPW)-1);
372                         if (trustpw == NULL) {
373                                 ret = ENOMEM;
374                                 goto failed;
375                         }
376                 } else {
377                         DEBUG(0, ("Unsupported option [%s].\n", argv[c]));
378                         ret = EINVAL;
379                         goto failed;
380                 }
381         }
382
383         *_o = o;
384         *_trustpw = trustpw;
385
386         return 0;
387
388 failed:
389         talloc_free(o);
390         talloc_free(trustpw);
391         return ret;
392 }
393
394 static void print_trust_delete_usage(void)
395 {
396         d_printf(  "%s\n"
397                    "net rpc trust delete [options]\n"
398                    "\nOptions:\n"
399                    "\totherserver=DC in other domain\n"
400                    "\totheruser=Admin user in other domain\n"
401                    "\totherdomainsid=SID of other domain\n"
402                    "\nExamples:\n"
403                    "\tnet rpc trust delete otherserver=oname otheruser=ouser -S lname -U luser\n"
404                    "\tnet rpc trust delete otherdomainsid=S-... -S lname -U luser\n"
405                    "  %s\n",
406                  _("Usage:"),
407                  _("Remove trust between two domains"));
408 }
409
410 static void print_trust_usage(void)
411 {
412         d_printf(  "%s\n"
413                    "net rpc trust create [options]\n"
414                    "\nOptions:\n"
415                    "\totherserver=DC in other domain\n"
416                    "\totheruser=Admin user in other domain\n"
417                    "\totherdomainsid=SID of other domain\n"
418                    "\tother_netbios_domain=NetBIOS/short name of other domain\n"
419                    "\totherdomain=Full/DNS name of other domain (if not used, create an NT4 trust)\n"
420                    "\ttrustpw=Trust password\n"
421                    "\nExamples:\n"
422                    "\tnet rpc trust create otherserver=oname otheruser=ouser -S lname -U luser\n"
423                    "\tnet rpc trust create otherdomainsid=S-... other_netbios_domain=odom otherdomain=odom.org trustpw=secret -S lname -U luser\n"
424                    "  %s\n",
425                  _("Usage:"),
426                  _("Create trust between two domains"));
427 }
428
429 static int rpc_trust_common(struct net_context *net_ctx, int argc,
430                             const char **argv, enum trust_op op)
431 {
432         TALLOC_CTX *mem_ctx;
433         NTSTATUS status;
434         int ret;
435         int success = -1;
436         struct cli_state *cli[2] = {NULL, NULL};
437         struct rpc_pipe_client *pipe_hnd[2] = {NULL, NULL};
438         DATA_BLOB session_key[2];
439         struct policy_handle pol_hnd[2];
440         struct lsa_TrustDomainInfoAuthInfoInternal authinfo;
441         DATA_BLOB auth_blob;
442         char *trust_pw = NULL;
443         struct other_dom_data *other_dom_data;
444         struct net_context *other_net_ctx = NULL;
445         struct dom_data dom_data[2];
446         void (*usage)(void);
447
448         ZERO_STRUCT(session_key);
449
450         switch (op) {
451                 case TRUST_CREATE:
452                         usage = print_trust_usage;
453                         break;
454                 case TRUST_DELETE:
455                         usage = print_trust_delete_usage;
456                         break;
457                 default:
458                         DEBUG(0, ("Unsupported trust operation.\n"));
459                         return -1;
460         }
461
462         if (net_ctx->display_usage) {
463                 usage();
464                 return 0;
465         }
466
467         mem_ctx = talloc_init("trust op");
468         if (mem_ctx == NULL) {
469                 DEBUG(0, ("talloc_init failed.\n"));
470                 return -1;
471         }
472
473         ret = parse_trust_args(mem_ctx, argc, argv, &other_dom_data, &trust_pw);
474         if (ret != 0) {
475                 if (ret == EINVAL) {
476                         usage();
477                 } else {
478                         DEBUG(0, ("Failed to parse arguments.\n"));
479                 }
480                 goto done;
481         }
482
483         if (other_dom_data->host != 0) {
484                 other_net_ctx = talloc_zero(other_dom_data, struct net_context);
485                 if (other_net_ctx == NULL) {
486                         DEBUG(0, ("talloc_zero failed.\n"));
487                         goto done;
488                 }
489
490                 other_net_ctx->opt_host = other_dom_data->host;
491                 other_net_ctx->creds = cli_credentials_init(other_net_ctx);
492                 cli_credentials_parse_string(other_net_ctx->creds,
493                                              other_dom_data->user_name,
494                                              CRED_SPECIFIED);
495         } else {
496                 dom_data[1].domsid = dom_sid_parse_talloc(mem_ctx,
497                                                 other_dom_data->domain_sid_str);
498                 dom_data[1].domain_name = other_dom_data->domain_name;
499                 dom_data[1].dns_domain_name = other_dom_data->dns_domain_name;
500
501                 if (dom_data[1].dns_domain_name == NULL) {
502                         fprintf(stdout, "No DNS domain name passed, "
503                                 "assuming NT4 trust!\n");
504                 }
505
506                 if (dom_data[1].domsid == NULL ||
507                     (op == TRUST_CREATE &&
508                      (dom_data[1].domain_name == NULL))) {
509                         DEBUG(0, ("Missing required argument.\n"));
510                         usage();
511                         goto done;
512                 }
513         }
514
515         status = connect_and_get_info(mem_ctx, net_ctx, &cli[0], &pipe_hnd[0],
516                                       &pol_hnd[0], &dom_data[0], &session_key[0]);
517         if (!NT_STATUS_IS_OK(status)) {
518                 DEBUG(0, ("connect_and_get_info failed with error [%s]\n",
519                           nt_errstr(status)));
520                 goto done;
521         }
522
523         if (other_net_ctx != NULL) {
524                 status = connect_and_get_info(mem_ctx, other_net_ctx,
525                                               &cli[1], &pipe_hnd[1],
526                                               &pol_hnd[1], &dom_data[1],
527                                               &session_key[1]);
528                 if (!NT_STATUS_IS_OK(status)) {
529                         DEBUG(0, ("connect_and_get_info failed with error [%s]\n",
530                                   nt_errstr(status)));
531                         goto done;
532                 }
533         }
534
535         if (op == TRUST_CREATE) {
536                 gnutls_cipher_hd_t cipher_hnd = NULL;
537                 gnutls_datum_t enc_session_key = {
538                         .data = session_key[0].data,
539                         .size = session_key[0].length,
540                 };
541                 int rc;
542
543                 if (trust_pw == NULL) {
544                         if (other_net_ctx == NULL) {
545                                 DEBUG(0, ("Missing either trustpw or otherhost.\n"));
546                                 goto done;
547                         }
548
549                         DEBUG(0, ("Using random trust password.\n"));
550                         trust_pw = trust_pw_new_value(mem_ctx,
551                                                       SEC_CHAN_DOMAIN,
552                                                       SEC_DOMAIN);
553                         if (trust_pw == NULL) {
554                                 DEBUG(0, ("generate_random_password failed.\n"));
555                                 goto done;
556                         }
557                 } else {
558                         DEBUG(0, ("Using user provided password.\n"));
559                 }
560
561                 if (!get_trust_domain_passwords_auth_blob(mem_ctx, trust_pw,
562                                                           &auth_blob)) {
563                         DEBUG(0, ("get_trust_domain_passwords_auth_blob failed\n"));
564                         goto done;
565                 }
566
567                 authinfo.auth_blob.data = (uint8_t *)talloc_memdup(
568                                                         mem_ctx,
569                                                         auth_blob.data,
570                                                         auth_blob.length);
571                 if (authinfo.auth_blob.data == NULL) {
572                         goto done;
573                 }
574                 authinfo.auth_blob.size = auth_blob.length;
575
576                 rc = gnutls_cipher_init(&cipher_hnd,
577                                         GNUTLS_CIPHER_ARCFOUR_128,
578                                         &enc_session_key,
579                                         NULL);
580                 if (rc < 0) {
581                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
582                         goto done;
583                 }
584                 rc = gnutls_cipher_encrypt(cipher_hnd,
585                                            authinfo.auth_blob.data,
586                                            authinfo.auth_blob.size);
587                 gnutls_cipher_deinit(cipher_hnd);
588                 if (rc < 0) {
589                         status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
590                         goto done;
591                 }
592
593                 status = create_trust(mem_ctx, pipe_hnd[0]->binding_handle,
594                                       &pol_hnd[0],
595                                       dom_data[1].domain_name,
596                                       dom_data[1].dns_domain_name,
597                                       dom_data[1].domsid,
598                                       &authinfo);
599                 if (!NT_STATUS_IS_OK(status)) {
600                         DEBUG(0, ("create_trust failed with error [%s].\n",
601                         nt_errstr(status)));
602                         goto done;
603                 }
604
605                 if (other_net_ctx != NULL) {
606                         talloc_free(authinfo.auth_blob.data);
607                         authinfo.auth_blob.data = (uint8_t *)talloc_memdup(
608                                                                 mem_ctx,
609                                                                 auth_blob.data,
610                                                                 auth_blob.length);
611                         if (authinfo.auth_blob.data == NULL) {
612                                 goto done;
613                         }
614                         authinfo.auth_blob.size = auth_blob.length;
615
616                         enc_session_key = (gnutls_datum_t) {
617                                 .data = session_key[1].data,
618                                 .size = session_key[1].length,
619                         };
620
621                         rc = gnutls_cipher_init(&cipher_hnd,
622                                                 GNUTLS_CIPHER_ARCFOUR_128,
623                                                 &enc_session_key,
624                                                 NULL);
625                         if (rc < 0) {
626                                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
627                                 goto done;
628                         }
629                         rc = gnutls_cipher_encrypt(cipher_hnd,
630                                                    authinfo.auth_blob.data,
631                                                    authinfo.auth_blob.size);
632                         gnutls_cipher_deinit(cipher_hnd);
633                         if (rc < 0) {
634                                 status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
635                                 goto done;
636                         }
637
638                         status = create_trust(mem_ctx,
639                                               pipe_hnd[1]->binding_handle,
640                                               &pol_hnd[1],
641                                               dom_data[0].domain_name,
642                                               dom_data[0].dns_domain_name,
643                                               dom_data[0].domsid, &authinfo);
644                         if (!NT_STATUS_IS_OK(status)) {
645                                 DEBUG(0, ("create_trust failed with error [%s].\n",
646                                 nt_errstr(status)));
647                                 goto done;
648                         }
649                 }
650         } else if (op == TRUST_DELETE) {
651                 status = delete_trust(mem_ctx, pipe_hnd[0]->binding_handle,
652                                       &pol_hnd[0], dom_data[1].domsid);
653                 if (!NT_STATUS_IS_OK(status)) {
654                         DEBUG(0, ("delete_trust failed with [%s].\n",
655                                   nt_errstr(status)));
656                         goto done;
657                 }
658
659                 if (other_net_ctx != NULL) {
660                         status = delete_trust(mem_ctx,
661                                               pipe_hnd[1]->binding_handle,
662                                               &pol_hnd[1], dom_data[0].domsid);
663                         if (!NT_STATUS_IS_OK(status)) {
664                                 DEBUG(0, ("delete_trust failed with [%s].\n",
665                                           nt_errstr(status)));
666                                 goto done;
667                         }
668                 }
669         }
670
671         status = close_handle(mem_ctx, pipe_hnd[0]->binding_handle,
672                               &pol_hnd[0]);
673         if (!NT_STATUS_IS_OK(status)) {
674                 DEBUG(0, ("close_handle failed with error [%s].\n",
675                           nt_errstr(status)));
676                 goto done;
677         }
678
679         if (other_net_ctx != NULL) {
680                 status = close_handle(mem_ctx, pipe_hnd[1]->binding_handle,
681                                       &pol_hnd[1]);
682                 if (!NT_STATUS_IS_OK(status)) {
683                         DEBUG(0, ("close_handle failed with error [%s].\n",
684                                   nt_errstr(status)));
685                         goto done;
686                 }
687         }
688
689         success = 0;
690
691 done:
692         data_blob_clear_free(&session_key[0]);
693         data_blob_clear_free(&session_key[1]);
694         cli_shutdown(cli[0]);
695         cli_shutdown(cli[1]);
696         talloc_destroy(mem_ctx);
697         return success;
698 }
699
700 static int rpc_trust_create(struct net_context *net_ctx, int argc,
701                             const char **argv)
702 {
703         return rpc_trust_common(net_ctx, argc, argv, TRUST_CREATE);
704 }
705
706 static int rpc_trust_delete(struct net_context *net_ctx, int argc,
707                             const char **argv)
708 {
709         return rpc_trust_common(net_ctx, argc, argv, TRUST_DELETE);
710 }
711
712 int net_rpc_trust(struct net_context *c, int argc, const char **argv)
713 {
714         struct functable func[] = {
715                 {
716                         "create",
717                         rpc_trust_create,
718                         NET_TRANSPORT_RPC,
719                         N_("Create trusts"),
720                         N_("net rpc trust create\n"
721                            "    Create trusts")
722                 },
723                 {
724                         "delete",
725                         rpc_trust_delete,
726                         NET_TRANSPORT_RPC,
727                         N_("Remove trusts"),
728                         N_("net rpc trust delete\n"
729                            "    Remove trusts")
730                 },
731                 {NULL, NULL, 0, NULL, NULL}
732         };
733
734         return net_run_function(c, argc, argv, "net rpc trust", func);
735 }