source: vendor/current/source3/utils/net_rpc_trust.c@ 740

Last change on this file since 740 was 740, checked in by Silvan Scherrer, 12 years ago

Samba Server: update vendor to 3.6.0

File size: 18.5 KB
Line 
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
38enum trust_op {
39 TRUST_CREATE,
40 TRUST_DELETE
41};
42
43struct 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
51struct dom_data {
52 struct dom_sid *domsid;
53 char *dns_domain_name;
54 char *domain_name;
55};
56
57static 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
79static 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
105static 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 = 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
151static 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
194static 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
250static 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, true)) {
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
299static 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
365failed:
366 talloc_free(o);
367 talloc_free(trustpw);
368 return ret;
369}
370
371static 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
387static 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
406static 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
619done:
620 cli_shutdown(cli[0]);
621 cli_shutdown(cli[1]);
622 talloc_destroy(mem_ctx);
623 return success;
624}
625
626static 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
632static 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
638int 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}
Note: See TracBrowser for help on using the repository browser.