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 
close_handle(TALLOC_CTX * mem_ctx,struct dcerpc_binding_handle * bind_hnd,struct policy_handle * pol_hnd)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 
delete_trust(TALLOC_CTX * mem_ctx,struct dcerpc_binding_handle * bind_hnd,struct policy_handle * pol_hnd,struct dom_sid * domsid)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 
create_trust(TALLOC_CTX * mem_ctx,struct dcerpc_binding_handle * bind_hnd,struct policy_handle * pol_hnd,const char * trust_name,const char * trust_name_dns,struct dom_sid * domsid,struct lsa_TrustDomainInfoAuthInfoInternal * authinfo)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 
120 	trustinfo.sid = domsid;
121 	trustinfo.netbios_name.string = trust_name;
122 	trustinfo.domain_name.string = trust_name_dns;
123 
124 	trustinfo.trust_direction = LSA_TRUST_DIRECTION_INBOUND |
125 				    LSA_TRUST_DIRECTION_OUTBOUND;
126 
127 	trustinfo.trust_type = LSA_TRUST_TYPE_UPLEVEL;
128 
129 	trustinfo.trust_attributes = LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE;
130 
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;
137 
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;
143 	}
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;
148 	}
149 
150 	return NT_STATUS_OK;
151 }
152 
get_domain_info(TALLOC_CTX * mem_ctx,struct dcerpc_binding_handle * bind_hdn,struct policy_handle * pol_hnd,struct dom_data * dom_data)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)
157 {
158 	NTSTATUS status;
159 	struct lsa_QueryInfoPolicy2 qr;
160 	struct dom_sid_buf buf;
161 
162 	qr.in.handle = pol_hnd;
163 	qr.in.level = LSA_POLICY_INFO_DNS;
164 
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;
170 	}
171 
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;
176 	}
177 
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;
188 	}
189 
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)));
193 
194 	return NT_STATUS_OK;
195 }
196 
connect_and_get_info(TALLOC_CTX * mem_ctx,struct net_context * net_ctx,struct cli_state ** cli,struct rpc_pipe_client ** pipe_hnd,struct policy_handle * pol_hnd,struct dom_data * dom_data,DATA_BLOB * session_key)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)
204 {
205 	NTSTATUS status;
206 	NTSTATUS result;
207 
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;
214 	}
215 
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;
221 	}
222 
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;
236 	}
237 	if (!NT_STATUS_IS_OK(result)) {
238 		DEBUG(0, ("lsa_open_policy2 with error [%s]\n",
239 			  nt_errstr(result)));
240 		return result;
241 	}
242 
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;
249 	}
250 
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;
256 	}
257 
258 	return NT_STATUS_OK;
259 }
260 
get_trust_domain_passwords_auth_blob(TALLOC_CTX * mem_ctx,const char * password,DATA_BLOB * auth_blob)261 static bool get_trust_domain_passwords_auth_blob(TALLOC_CTX *mem_ctx,
262 						 const char *password,
263 						 DATA_BLOB *auth_blob)
264 {
265 	struct trustDomainPasswords auth_struct;
266 	struct AuthenticationInformation *auth_info_array;
267 	enum ndr_err_code ndr_err;
268 	size_t converted_size;
269 
270 	generate_random_buffer(auth_struct.confounder,
271 			       sizeof(auth_struct.confounder));
272 
273 	auth_info_array = talloc_array(mem_ctx,
274 				       struct AuthenticationInformation, 1);
275 	if (auth_info_array == NULL) {
276 		return false;
277 	}
278 
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;
285 	}
286 
287 	auth_info_array[0].AuthInfo.clear.size = converted_size;
288 
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;
294 
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;
300 
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;
305 	}
306 
307 	return true;
308 }
309 
parse_trust_args(TALLOC_CTX * mem_ctx,int argc,const char ** argv,struct other_dom_data ** _o,char ** _trustpw)310 static int parse_trust_args(TALLOC_CTX *mem_ctx, int argc, const char **argv, struct other_dom_data **_o, char **_trustpw)
311 {
312 	size_t c;
313 	struct other_dom_data *o = NULL;
314 	char *trustpw = NULL;
315 	int ret = EFAULT;
316 
317 	if (argc == 0) {
318 		return EINVAL;
319 	}
320 
321 	o = talloc_zero(mem_ctx, struct other_dom_data);
322 	if (o == NULL) {
323 		DEBUG(0, ("talloc_zero failed.\n"));
324 		return ENOMEM;
325 	}
326 
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;
333 			}
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;
339 			}
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;
345 			}
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;
351 			}
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;
357 			}
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;
363 			}
364 		} else {
365 			DEBUG(0, ("Unsupported option [%s].\n", argv[c]));
366 			ret = EINVAL;
367 			goto failed;
368 		}
369 	}
370 
371 	*_o = o;
372 	*_trustpw = trustpw;
373 
374 	return 0;
375 
376 failed:
377 	talloc_free(o);
378 	talloc_free(trustpw);
379 	return ret;
380 }
381 
print_trust_delete_usage(void)382 static void print_trust_delete_usage(void)
383 {
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"));
396 }
397 
print_trust_usage(void)398 static void print_trust_usage(void)
399 {
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"));
415 }
416 
rpc_trust_common(struct net_context * net_ctx,int argc,const char ** argv,enum trust_op op)417 static int rpc_trust_common(struct net_context *net_ctx, int argc,
418 			    const char **argv, enum trust_op op)
419 {
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);
435 
436 	ZERO_STRUCT(session_key);
437 
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;
448 	}
449 
450 	if (net_ctx->display_usage) {
451 		usage();
452 		return 0;
453 	}
454 
455 	mem_ctx = talloc_init("trust op");
456 	if (mem_ctx == NULL) {
457 		DEBUG(0, ("talloc_init failed.\n"));
458 		return -1;
459 	}
460 
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"));
467 		}
468 		goto done;
469 	}
470 
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;
476 		}
477 
478 		other_net_ctx->opt_host = other_dom_data->host;
479 		other_net_ctx->opt_user_name = other_dom_data->user_name;
480 	} else {
481 		dom_data[1].domsid = dom_sid_parse_talloc(mem_ctx,
482 						other_dom_data->domain_sid_str);
483 		dom_data[1].domain_name = other_dom_data->domain_name;
484 		dom_data[1].dns_domain_name = other_dom_data->dns_domain_name;
485 
486 		if (dom_data[1].domsid == NULL ||
487 		    (op == TRUST_CREATE &&
488 		     (dom_data[1].domain_name == NULL ||
489 		      dom_data[1].dns_domain_name == NULL))) {
490 			DEBUG(0, ("Missing required argument.\n"));
491 			usage();
492 			goto done;
493 		}
494 	}
495 
496 	status = connect_and_get_info(mem_ctx, net_ctx, &cli[0], &pipe_hnd[0],
497 				      &pol_hnd[0], &dom_data[0], &session_key[0]);
498 	if (!NT_STATUS_IS_OK(status)) {
499 		DEBUG(0, ("connect_and_get_info failed with error [%s]\n",
500 			  nt_errstr(status)));
501 		goto done;
502 	}
503 
504 	if (other_net_ctx != NULL) {
505 		status = connect_and_get_info(mem_ctx, other_net_ctx,
506 					      &cli[1], &pipe_hnd[1],
507 					      &pol_hnd[1], &dom_data[1],
508 					      &session_key[1]);
509 		if (!NT_STATUS_IS_OK(status)) {
510 			DEBUG(0, ("connect_and_get_info failed with error [%s]\n",
511 				  nt_errstr(status)));
512 			goto done;
513 		}
514 	}
515 
516 	if (op == TRUST_CREATE) {
517 		gnutls_cipher_hd_t cipher_hnd = NULL;
518 		gnutls_datum_t enc_session_key = {
519 			.data = session_key[0].data,
520 			.size = session_key[0].length,
521 		};
522 		int rc;
523 
524 		if (trust_pw == NULL) {
525 			if (other_net_ctx == NULL) {
526 				DEBUG(0, ("Missing either trustpw or otherhost.\n"));
527 				goto done;
528 			}
529 
530 			DEBUG(0, ("Using random trust password.\n"));
531 			trust_pw = trust_pw_new_value(mem_ctx,
532 						      SEC_CHAN_DOMAIN,
533 						      SEC_DOMAIN);
534 			if (trust_pw == NULL) {
535 				DEBUG(0, ("generate_random_password failed.\n"));
536 				goto done;
537 			}
538 		} else {
539 			DEBUG(0, ("Using user provided password.\n"));
540 		}
541 
542 		if (!get_trust_domain_passwords_auth_blob(mem_ctx, trust_pw,
543 							  &auth_blob)) {
544 			DEBUG(0, ("get_trust_domain_passwords_auth_blob failed\n"));
545 			goto done;
546 		}
547 
548 		authinfo.auth_blob.data = (uint8_t *)talloc_memdup(
549 							mem_ctx,
550 							auth_blob.data,
551 							auth_blob.length);
552 		if (authinfo.auth_blob.data == NULL) {
553 			goto done;
554 		}
555 		authinfo.auth_blob.size = auth_blob.length;
556 
557 		rc = gnutls_cipher_init(&cipher_hnd,
558 					GNUTLS_CIPHER_ARCFOUR_128,
559 					&enc_session_key,
560 					NULL);
561 		if (rc < 0) {
562 			status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
563 			goto done;
564 		}
565 		rc = gnutls_cipher_encrypt(cipher_hnd,
566 					   authinfo.auth_blob.data,
567 					   authinfo.auth_blob.size);
568 		gnutls_cipher_deinit(cipher_hnd);
569 		if (rc < 0) {
570 			status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
571 			goto done;
572 		}
573 
574 		status = create_trust(mem_ctx, pipe_hnd[0]->binding_handle,
575 				      &pol_hnd[0],
576 				      dom_data[1].domain_name,
577 				      dom_data[1].dns_domain_name,
578 				      dom_data[1].domsid,
579 				      &authinfo);
580 		if (!NT_STATUS_IS_OK(status)) {
581 			DEBUG(0, ("create_trust failed with error [%s].\n",
582 			nt_errstr(status)));
583 			goto done;
584 		}
585 
586 		if (other_net_ctx != NULL) {
587 			talloc_free(authinfo.auth_blob.data);
588 			authinfo.auth_blob.data = (uint8_t *)talloc_memdup(
589 								mem_ctx,
590 								auth_blob.data,
591 								auth_blob.length);
592 			if (authinfo.auth_blob.data == NULL) {
593 				goto done;
594 			}
595 			authinfo.auth_blob.size = auth_blob.length;
596 
597 			enc_session_key = (gnutls_datum_t) {
598 				.data = session_key[1].data,
599 				.size = session_key[1].length,
600 			};
601 
602 			rc = gnutls_cipher_init(&cipher_hnd,
603 						GNUTLS_CIPHER_ARCFOUR_128,
604 						&enc_session_key,
605 						NULL);
606 			if (rc < 0) {
607 				status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
608 				goto done;
609 			}
610 			rc = gnutls_cipher_encrypt(cipher_hnd,
611 						   authinfo.auth_blob.data,
612 						   authinfo.auth_blob.size);
613 			gnutls_cipher_deinit(cipher_hnd);
614 			if (rc < 0) {
615 				status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
616 				goto done;
617 			}
618 
619 			status = create_trust(mem_ctx,
620 					      pipe_hnd[1]->binding_handle,
621 					      &pol_hnd[1],
622 					      dom_data[0].domain_name,
623 					      dom_data[0].dns_domain_name,
624 					      dom_data[0].domsid, &authinfo);
625 			if (!NT_STATUS_IS_OK(status)) {
626 				DEBUG(0, ("create_trust failed with error [%s].\n",
627 				nt_errstr(status)));
628 				goto done;
629 			}
630 		}
631 	} else if (op == TRUST_DELETE) {
632 		status = delete_trust(mem_ctx, pipe_hnd[0]->binding_handle,
633 				      &pol_hnd[0], dom_data[1].domsid);
634 		if (!NT_STATUS_IS_OK(status)) {
635 			DEBUG(0, ("delete_trust failed with [%s].\n",
636 				  nt_errstr(status)));
637 			goto done;
638 		}
639 
640 		if (other_net_ctx != NULL) {
641 			status = delete_trust(mem_ctx,
642 					      pipe_hnd[1]->binding_handle,
643 					      &pol_hnd[1], dom_data[0].domsid);
644 			if (!NT_STATUS_IS_OK(status)) {
645 				DEBUG(0, ("delete_trust failed with [%s].\n",
646 					  nt_errstr(status)));
647 				goto done;
648 			}
649 		}
650 	}
651 
652 	status = close_handle(mem_ctx, pipe_hnd[0]->binding_handle,
653 			      &pol_hnd[0]);
654 	if (!NT_STATUS_IS_OK(status)) {
655 		DEBUG(0, ("close_handle failed with error [%s].\n",
656 			  nt_errstr(status)));
657 		goto done;
658 	}
659 
660 	if (other_net_ctx != NULL) {
661 		status = close_handle(mem_ctx, pipe_hnd[1]->binding_handle,
662 				      &pol_hnd[1]);
663 		if (!NT_STATUS_IS_OK(status)) {
664 			DEBUG(0, ("close_handle failed with error [%s].\n",
665 				  nt_errstr(status)));
666 			goto done;
667 		}
668 	}
669 
670 	success = 0;
671 
672 done:
673 	data_blob_clear_free(&session_key[0]);
674 	data_blob_clear_free(&session_key[1]);
675 	cli_shutdown(cli[0]);
676 	cli_shutdown(cli[1]);
677 	talloc_destroy(mem_ctx);
678 	return success;
679 }
680 
rpc_trust_create(struct net_context * net_ctx,int argc,const char ** argv)681 static int rpc_trust_create(struct net_context *net_ctx, int argc,
682 			    const char **argv)
683 {
684 	return rpc_trust_common(net_ctx, argc, argv, TRUST_CREATE);
685 }
686 
rpc_trust_delete(struct net_context * net_ctx,int argc,const char ** argv)687 static int rpc_trust_delete(struct net_context *net_ctx, int argc,
688 			    const char **argv)
689 {
690 	return rpc_trust_common(net_ctx, argc, argv, TRUST_DELETE);
691 }
692 
net_rpc_trust(struct net_context * c,int argc,const char ** argv)693 int net_rpc_trust(struct net_context *c, int argc, const char **argv)
694 {
695 	struct functable func[] = {
696 		{
697 			"create",
698 			rpc_trust_create,
699 			NET_TRANSPORT_RPC,
700 			N_("Create trusts"),
701 			N_("net rpc trust create\n"
702 			   "    Create trusts")
703 		},
704 		{
705 			"delete",
706 			rpc_trust_delete,
707 			NET_TRANSPORT_RPC,
708 			N_("Remove trusts"),
709 			N_("net rpc trust delete\n"
710 			   "    Remove trusts")
711 		},
712 		{NULL, NULL, 0, NULL, NULL}
713 	};
714 
715 	return net_run_function(c, argc, argv, "net rpc trust", func);
716 }
717