Line data Source code
1 : /*
2 : Samba Unix/Linux SMB client library
3 : net ads commands
4 : Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
5 : Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
6 : Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
7 : Copyright (C) 2006 Gerald (Jerry) Carter (jerry@samba.org)
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "utils/net.h"
25 : #include "libsmb/namequery.h"
26 : #include "rpc_client/cli_pipe.h"
27 : #include "librpc/gen_ndr/ndr_krb5pac.h"
28 : #include "../librpc/gen_ndr/ndr_spoolss.h"
29 : #include "nsswitch/libwbclient/wbclient.h"
30 : #include "ads.h"
31 : #include "libads/cldap.h"
32 : #include "../lib/addns/dnsquery.h"
33 : #include "../libds/common/flags.h"
34 : #include "librpc/gen_ndr/libnet_join.h"
35 : #include "libnet/libnet_join.h"
36 : #include "smb_krb5.h"
37 : #include "secrets.h"
38 : #include "krb5_env.h"
39 : #include "../libcli/security/security.h"
40 : #include "libsmb/libsmb.h"
41 : #include "lib/param/loadparm.h"
42 : #include "utils/net_dns.h"
43 : #include "auth/kerberos/pac_utils.h"
44 : #include "lib/util/string_wrappers.h"
45 : #include "lib/util/util_file.h"
46 :
47 : #ifdef HAVE_JANSSON
48 : #include <jansson.h>
49 : #include "audit_logging.h" /* various JSON helpers */
50 : #include "auth/common_auth.h"
51 : #endif /* [HAVE_JANSSON] */
52 :
53 : #ifdef HAVE_ADS
54 :
55 : /* when we do not have sufficient input parameters to contact a remote domain
56 : * we always fall back to our own realm - Guenther*/
57 :
58 78 : static const char *assume_own_realm(struct net_context *c)
59 : {
60 78 : if (!c->opt_host && strequal(lp_workgroup(), c->opt_target_workgroup)) {
61 66 : return lp_realm();
62 : }
63 :
64 12 : return NULL;
65 : }
66 :
67 : #ifdef HAVE_JANSSON
68 :
69 : /*
70 : * note: JSON output deliberately bypasses gettext so as to provide the same
71 : * output irrespective of the locale.
72 : */
73 :
74 4 : static int output_json(const struct json_object *jsobj)
75 : {
76 4 : TALLOC_CTX *ctx = NULL;
77 4 : char *json = NULL;
78 :
79 4 : if (json_is_invalid(jsobj)) {
80 0 : return -1;
81 : }
82 :
83 4 : ctx = talloc_new(NULL);
84 4 : if (ctx == NULL) {
85 0 : d_fprintf(stderr, _("Out of memory\n"));
86 0 : return -1;
87 : }
88 :
89 4 : json = json_to_string(ctx, jsobj);
90 4 : if (!json) {
91 0 : d_fprintf(stderr, _("error encoding to JSON\n"));
92 0 : return -1;
93 : }
94 :
95 4 : d_printf("%s\n", json);
96 4 : TALLOC_FREE(ctx);
97 :
98 4 : return 0;
99 : }
100 :
101 2 : static int net_ads_cldap_netlogon_json
102 : (ADS_STRUCT *ads,
103 : const char *addr,
104 : const struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply)
105 : {
106 2 : struct json_object jsobj = json_new_object();
107 2 : struct json_object flagsobj = json_new_object();
108 2 : char response_type [32] = { '\0' };
109 2 : int ret = 0;
110 :
111 2 : if (json_is_invalid(&jsobj) || json_is_invalid(&flagsobj)) {
112 0 : d_fprintf(stderr, _("error setting up JSON value\n"));
113 :
114 0 : goto failure;
115 : }
116 :
117 2 : switch (reply->command) {
118 0 : case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
119 0 : strncpy(response_type,
120 : "LOGON_SAM_LOGON_USER_UNKNOWN_EX",
121 : sizeof(response_type));
122 0 : break;
123 2 : case LOGON_SAM_LOGON_RESPONSE_EX:
124 2 : strncpy(response_type, "LOGON_SAM_LOGON_RESPONSE_EX",
125 : sizeof(response_type));
126 2 : break;
127 0 : default:
128 0 : snprintf(response_type, sizeof(response_type), "0x%x",
129 0 : reply->command);
130 0 : break;
131 : }
132 :
133 2 : ret = json_add_string(&jsobj, "Information for Domain Controller",
134 : addr);
135 2 : if (ret != 0) {
136 0 : goto failure;
137 : }
138 :
139 2 : ret = json_add_string(&jsobj, "Response Type", response_type);
140 2 : if (ret != 0) {
141 0 : goto failure;
142 : }
143 :
144 2 : ret = json_add_guid(&jsobj, "GUID", &reply->domain_uuid);
145 2 : if (ret != 0) {
146 0 : goto failure;
147 : }
148 :
149 2 : ret = json_add_bool(&flagsobj, "Is a PDC",
150 2 : reply->server_type & NBT_SERVER_PDC);
151 2 : if (ret != 0) {
152 0 : goto failure;
153 : }
154 :
155 2 : ret = json_add_bool(&flagsobj, "Is a GC of the forest",
156 2 : reply->server_type & NBT_SERVER_GC);
157 2 : if (ret != 0) {
158 0 : goto failure;
159 : }
160 :
161 2 : ret = json_add_bool(&flagsobj, "Is an LDAP server",
162 2 : reply->server_type & NBT_SERVER_LDAP);
163 2 : if (ret != 0) {
164 0 : goto failure;
165 : }
166 :
167 2 : ret = json_add_bool(&flagsobj, "Supports DS",
168 2 : reply->server_type & NBT_SERVER_DS);
169 2 : if (ret != 0) {
170 0 : goto failure;
171 : }
172 :
173 2 : ret = json_add_bool(&flagsobj, "Is running a KDC",
174 2 : reply->server_type & NBT_SERVER_KDC);
175 2 : if (ret != 0) {
176 0 : goto failure;
177 : }
178 :
179 2 : ret = json_add_bool(&flagsobj, "Is running time services",
180 2 : reply->server_type & NBT_SERVER_TIMESERV);
181 2 : if (ret != 0) {
182 0 : goto failure;
183 : }
184 :
185 2 : ret = json_add_bool(&flagsobj, "Is the closest DC",
186 2 : reply->server_type & NBT_SERVER_CLOSEST);
187 2 : if (ret != 0) {
188 0 : goto failure;
189 : }
190 :
191 2 : ret = json_add_bool(&flagsobj, "Is writable",
192 2 : reply->server_type & NBT_SERVER_WRITABLE);
193 2 : if (ret != 0) {
194 0 : goto failure;
195 : }
196 :
197 2 : ret = json_add_bool(&flagsobj, "Has a hardware clock",
198 2 : reply->server_type & NBT_SERVER_GOOD_TIMESERV);
199 2 : if (ret != 0) {
200 0 : goto failure;
201 : }
202 :
203 2 : ret = json_add_bool(&flagsobj,
204 : "Is a non-domain NC serviced by LDAP server",
205 2 : reply->server_type & NBT_SERVER_NDNC);
206 2 : if (ret != 0) {
207 0 : goto failure;
208 : }
209 :
210 2 : ret = json_add_bool
211 : (&flagsobj, "Is NT6 DC that has some secrets",
212 2 : reply->server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6);
213 2 : if (ret != 0) {
214 0 : goto failure;
215 : }
216 :
217 2 : ret = json_add_bool
218 : (&flagsobj, "Is NT6 DC that has all secrets",
219 2 : reply->server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6);
220 2 : if (ret != 0) {
221 0 : goto failure;
222 : }
223 :
224 2 : ret = json_add_bool(&flagsobj, "Runs Active Directory Web Services",
225 2 : reply->server_type & NBT_SERVER_ADS_WEB_SERVICE);
226 2 : if (ret != 0) {
227 0 : goto failure;
228 : }
229 :
230 2 : ret = json_add_bool(&flagsobj, "Runs on Windows 2012 or later",
231 2 : reply->server_type & NBT_SERVER_DS_8);
232 2 : if (ret != 0) {
233 0 : goto failure;
234 : }
235 :
236 2 : ret = json_add_bool(&flagsobj, "Runs on Windows 2012R2 or later",
237 2 : reply->server_type & NBT_SERVER_DS_9);
238 2 : if (ret != 0) {
239 0 : goto failure;
240 : }
241 :
242 2 : ret = json_add_bool(&flagsobj, "Runs on Windows 2016 or later",
243 2 : reply->server_type & NBT_SERVER_DS_10);
244 2 : if (ret != 0) {
245 0 : goto failure;
246 : }
247 :
248 2 : ret = json_add_bool(&flagsobj, "Has a DNS name",
249 2 : reply->server_type & NBT_SERVER_HAS_DNS_NAME);
250 2 : if (ret != 0) {
251 0 : goto failure;
252 : }
253 :
254 2 : ret = json_add_bool(&flagsobj, "Is a default NC",
255 2 : reply->server_type & NBT_SERVER_IS_DEFAULT_NC);
256 2 : if (ret != 0) {
257 0 : goto failure;
258 : }
259 :
260 2 : ret = json_add_bool(&flagsobj, "Is the forest root",
261 2 : reply->server_type & NBT_SERVER_FOREST_ROOT);
262 2 : if (ret != 0) {
263 0 : goto failure;
264 : }
265 :
266 2 : ret = json_add_string(&jsobj, "Forest", reply->forest);
267 2 : if (ret != 0) {
268 0 : goto failure;
269 : }
270 :
271 2 : ret = json_add_string(&jsobj, "Domain", reply->dns_domain);
272 2 : if (ret != 0) {
273 0 : goto failure;
274 : }
275 :
276 2 : ret = json_add_string(&jsobj, "Domain Controller", reply->pdc_dns_name);
277 2 : if (ret != 0) {
278 0 : goto failure;
279 : }
280 :
281 :
282 2 : ret = json_add_string(&jsobj, "Pre-Win2k Domain", reply->domain_name);
283 2 : if (ret != 0) {
284 0 : goto failure;
285 : }
286 :
287 2 : ret = json_add_string(&jsobj, "Pre-Win2k Hostname", reply->pdc_name);
288 2 : if (ret != 0) {
289 0 : goto failure;
290 : }
291 :
292 2 : if (*reply->user_name) {
293 0 : ret = json_add_string(&jsobj, "User name", reply->user_name);
294 0 : if (ret != 0) {
295 0 : goto failure;
296 : }
297 : }
298 :
299 2 : ret = json_add_string(&jsobj, "Server Site Name", reply->server_site);
300 2 : if (ret != 0) {
301 0 : goto failure;
302 : }
303 :
304 2 : ret = json_add_string(&jsobj, "Client Site Name", reply->client_site);
305 2 : if (ret != 0) {
306 0 : goto failure;
307 : }
308 :
309 2 : ret = json_add_int(&jsobj, "NT Version", reply->nt_version);
310 2 : if (ret != 0) {
311 0 : goto failure;
312 : }
313 :
314 2 : ret = json_add_int(&jsobj, "LMNT Token", reply->lmnt_token);
315 2 : if (ret != 0) {
316 0 : goto failure;
317 : }
318 :
319 2 : ret = json_add_int(&jsobj, "LM20 Token", reply->lm20_token);
320 2 : if (ret != 0) {
321 0 : goto failure;
322 : }
323 :
324 2 : ret = json_add_object(&jsobj, "Flags", &flagsobj);
325 2 : if (ret != 0) {
326 0 : goto failure;
327 : }
328 :
329 2 : ret = output_json(&jsobj);
330 2 : json_free(&jsobj); /* frees flagsobj recursively */
331 :
332 2 : return ret;
333 :
334 0 : failure:
335 0 : json_free(&flagsobj);
336 0 : json_free(&jsobj);
337 :
338 0 : return ret;
339 : }
340 :
341 : #else /* [HAVE_JANSSON] */
342 :
343 : static int net_ads_cldap_netlogon_json
344 : (ADS_STRUCT *ads,
345 : const char *addr,
346 : const struct NETLOGON_SAM_LOGON_RESPONSE_EX * reply)
347 : {
348 : d_fprintf(stderr, _("JSON support not available\n"));
349 :
350 : return -1;
351 : }
352 :
353 : #endif /* [HAVE_JANSSON] */
354 :
355 : /*
356 : do a cldap netlogon query
357 : */
358 21 : static int net_ads_cldap_netlogon(struct net_context *c, ADS_STRUCT *ads)
359 : {
360 0 : char addr[INET6_ADDRSTRLEN];
361 0 : struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
362 :
363 21 : print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
364 :
365 21 : if ( !ads_cldap_netlogon_5(talloc_tos(), &ads->ldap.ss, ads->server.realm, &reply ) ) {
366 0 : d_fprintf(stderr, _("CLDAP query failed!\n"));
367 0 : return -1;
368 : }
369 :
370 21 : if (c->opt_json) {
371 2 : return net_ads_cldap_netlogon_json(ads, addr, &reply);
372 : }
373 :
374 19 : d_printf(_("Information for Domain Controller: %s\n\n"),
375 : addr);
376 :
377 19 : d_printf(_("Response Type: "));
378 19 : switch (reply.command) {
379 0 : case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
380 0 : d_printf("LOGON_SAM_LOGON_USER_UNKNOWN_EX\n");
381 0 : break;
382 19 : case LOGON_SAM_LOGON_RESPONSE_EX:
383 19 : d_printf("LOGON_SAM_LOGON_RESPONSE_EX\n");
384 19 : break;
385 0 : default:
386 0 : d_printf("0x%x\n", reply.command);
387 0 : break;
388 : }
389 :
390 19 : d_printf(_("GUID: %s\n"), GUID_string(talloc_tos(),&reply.domain_uuid));
391 :
392 19 : d_printf(_("Flags:\n"
393 : "\tIs a PDC: %s\n"
394 : "\tIs a GC of the forest: %s\n"
395 : "\tIs an LDAP server: %s\n"
396 : "\tSupports DS: %s\n"
397 : "\tIs running a KDC: %s\n"
398 : "\tIs running time services: %s\n"
399 : "\tIs the closest DC: %s\n"
400 : "\tIs writable: %s\n"
401 : "\tHas a hardware clock: %s\n"
402 : "\tIs a non-domain NC serviced by LDAP server: %s\n"
403 : "\tIs NT6 DC that has some secrets: %s\n"
404 : "\tIs NT6 DC that has all secrets: %s\n"
405 : "\tRuns Active Directory Web Services: %s\n"
406 : "\tRuns on Windows 2012 or later: %s\n"
407 : "\tRuns on Windows 2012R2 or later: %s\n"
408 : "\tRuns on Windows 2016 or later: %s\n"
409 : "\tHas a DNS name: %s\n"
410 : "\tIs a default NC: %s\n"
411 : "\tIs the forest root: %s\n"),
412 19 : (reply.server_type & NBT_SERVER_PDC) ? _("yes") : _("no"),
413 19 : (reply.server_type & NBT_SERVER_GC) ? _("yes") : _("no"),
414 19 : (reply.server_type & NBT_SERVER_LDAP) ? _("yes") : _("no"),
415 19 : (reply.server_type & NBT_SERVER_DS) ? _("yes") : _("no"),
416 19 : (reply.server_type & NBT_SERVER_KDC) ? _("yes") : _("no"),
417 19 : (reply.server_type & NBT_SERVER_TIMESERV) ? _("yes") : _("no"),
418 19 : (reply.server_type & NBT_SERVER_CLOSEST) ? _("yes") : _("no"),
419 19 : (reply.server_type & NBT_SERVER_WRITABLE) ? _("yes") : _("no"),
420 19 : (reply.server_type & NBT_SERVER_GOOD_TIMESERV) ? _("yes") : _("no"),
421 19 : (reply.server_type & NBT_SERVER_NDNC) ? _("yes") : _("no"),
422 19 : (reply.server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6) ? _("yes") : _("no"),
423 19 : (reply.server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6) ? _("yes") : _("no"),
424 19 : (reply.server_type & NBT_SERVER_ADS_WEB_SERVICE) ? _("yes") : _("no"),
425 19 : (reply.server_type & NBT_SERVER_DS_8) ? _("yes") : _("no"),
426 19 : (reply.server_type & NBT_SERVER_DS_9) ? _("yes") : _("no"),
427 19 : (reply.server_type & NBT_SERVER_DS_10) ? _("yes") : _("no"),
428 19 : (reply.server_type & NBT_SERVER_HAS_DNS_NAME) ? _("yes") : _("no"),
429 19 : (reply.server_type & NBT_SERVER_IS_DEFAULT_NC) ? _("yes") : _("no"),
430 19 : (reply.server_type & NBT_SERVER_FOREST_ROOT) ? _("yes") : _("no"));
431 :
432 :
433 19 : printf(_("Forest: %s\n"), reply.forest);
434 19 : printf(_("Domain: %s\n"), reply.dns_domain);
435 19 : printf(_("Domain Controller: %s\n"), reply.pdc_dns_name);
436 :
437 19 : printf(_("Pre-Win2k Domain: %s\n"), reply.domain_name);
438 19 : printf(_("Pre-Win2k Hostname: %s\n"), reply.pdc_name);
439 :
440 19 : if (*reply.user_name) printf(_("User name: %s\n"), reply.user_name);
441 :
442 19 : printf(_("Server Site Name: %s\n"), reply.server_site);
443 19 : printf(_("Client Site Name: %s\n"), reply.client_site);
444 :
445 19 : d_printf(_("NT Version: %d\n"), reply.nt_version);
446 19 : d_printf(_("LMNT Token: %.2x\n"), reply.lmnt_token);
447 19 : d_printf(_("LM20 Token: %.2x\n"), reply.lm20_token);
448 :
449 19 : return 0;
450 : }
451 :
452 : /*
453 : this implements the CLDAP based netlogon lookup requests
454 : for finding the domain controller of a ADS domain
455 : */
456 21 : static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
457 : {
458 21 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
459 21 : ADS_STRUCT *ads = NULL;
460 0 : ADS_STATUS status;
461 21 : int ret = -1;
462 :
463 21 : if (c->display_usage) {
464 0 : d_printf("%s\n"
465 : "net ads lookup\n"
466 : " %s",
467 : _("Usage:"),
468 : _("Find the ADS DC using CLDAP lookup.\n"));
469 0 : TALLOC_FREE(tmp_ctx);
470 0 : return -1;
471 : }
472 :
473 21 : status = ads_startup_nobind(c, false, tmp_ctx, &ads);
474 21 : if (!ADS_ERR_OK(status)) {
475 0 : d_fprintf(stderr, _("Didn't find the cldap server!\n"));
476 0 : goto out;
477 : }
478 :
479 21 : if (!ads->config.realm) {
480 0 : ads->config.realm = talloc_strdup(ads, c->opt_target_workgroup);
481 0 : if (ads->config.realm == NULL) {
482 0 : d_fprintf(stderr, _("Out of memory\n"));
483 0 : goto out;
484 : }
485 0 : ads->ldap.port = 389;
486 : }
487 :
488 21 : ret = net_ads_cldap_netlogon(c, ads);
489 21 : out:
490 21 : TALLOC_FREE(tmp_ctx);
491 21 : return ret;
492 : }
493 :
494 :
495 : #ifdef HAVE_JANSSON
496 :
497 2 : static int net_ads_info_json(ADS_STRUCT *ads)
498 : {
499 2 : int ret = 0;
500 0 : char addr[INET6_ADDRSTRLEN];
501 0 : time_t pass_time;
502 2 : struct json_object jsobj = json_new_object();
503 :
504 2 : if (json_is_invalid(&jsobj)) {
505 0 : d_fprintf(stderr, _("error setting up JSON value\n"));
506 :
507 0 : goto failure;
508 : }
509 :
510 2 : pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
511 :
512 2 : print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
513 :
514 2 : ret = json_add_string (&jsobj, "LDAP server", addr);
515 2 : if (ret != 0) {
516 0 : goto failure;
517 : }
518 :
519 2 : ret = json_add_string (&jsobj, "LDAP server name",
520 : ads->config.ldap_server_name);
521 2 : if (ret != 0) {
522 0 : goto failure;
523 : }
524 :
525 2 : ret = json_add_string (&jsobj, "Workgroup", ads->config.workgroup);
526 2 : if (ret != 0) {
527 0 : goto failure;
528 : }
529 :
530 2 : ret = json_add_string (&jsobj, "Realm", ads->config.realm);
531 2 : if (ret != 0) {
532 0 : goto failure;
533 : }
534 :
535 2 : ret = json_add_string (&jsobj, "Bind Path", ads->config.bind_path);
536 2 : if (ret != 0) {
537 0 : goto failure;
538 : }
539 :
540 2 : ret = json_add_int (&jsobj, "LDAP port", ads->ldap.port);
541 2 : if (ret != 0) {
542 0 : goto failure;
543 : }
544 :
545 2 : ret = json_add_int (&jsobj, "Server time", ads->config.current_time);
546 2 : if (ret != 0) {
547 0 : goto failure;
548 : }
549 :
550 2 : ret = json_add_string (&jsobj, "KDC server", ads->auth.kdc_server);
551 2 : if (ret != 0) {
552 0 : goto failure;
553 : }
554 :
555 2 : ret = json_add_int (&jsobj, "Server time offset",
556 2 : ads->auth.time_offset);
557 2 : if (ret != 0) {
558 0 : goto failure;
559 : }
560 :
561 2 : ret = json_add_int (&jsobj, "Last machine account password change",
562 : pass_time);
563 2 : if (ret != 0) {
564 0 : goto failure;
565 : }
566 :
567 2 : ret = output_json(&jsobj);
568 2 : failure:
569 2 : json_free(&jsobj);
570 :
571 2 : return ret;
572 : }
573 :
574 : #else /* [HAVE_JANSSON] */
575 :
576 : static int net_ads_info_json(ADS_STRUCT *ads)
577 : {
578 : d_fprintf(stderr, _("JSON support not available\n"));
579 :
580 : return -1;
581 : }
582 :
583 : #endif /* [HAVE_JANSSON] */
584 :
585 :
586 :
587 15 : static int net_ads_info(struct net_context *c, int argc, const char **argv)
588 : {
589 15 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
590 15 : ADS_STRUCT *ads = NULL;
591 0 : ADS_STATUS status;
592 0 : char addr[INET6_ADDRSTRLEN];
593 0 : time_t pass_time;
594 15 : int ret = -1;
595 :
596 15 : if (c->display_usage) {
597 0 : d_printf("%s\n"
598 : "net ads info\n"
599 : " %s",
600 : _("Usage:"),
601 : _("Display information about an Active Directory "
602 : "server.\n"));
603 0 : TALLOC_FREE(tmp_ctx);
604 0 : return -1;
605 : }
606 :
607 15 : status = ads_startup_nobind(c, false, tmp_ctx, &ads);
608 15 : if (!ADS_ERR_OK(status)) {
609 0 : d_fprintf(stderr, _("Didn't find the ldap server!\n"));
610 0 : goto out;
611 : }
612 :
613 15 : if (!ads || !ads->config.realm) {
614 0 : d_fprintf(stderr, _("Didn't find the ldap server!\n"));
615 0 : goto out;
616 : }
617 :
618 : /* Try to set the server's current time since we didn't do a full
619 : TCP LDAP session initially */
620 :
621 15 : if ( !ADS_ERR_OK(ads_current_time( ads )) ) {
622 0 : d_fprintf( stderr, _("Failed to get server's current time!\n"));
623 : }
624 :
625 15 : if (c->opt_json) {
626 2 : ret = net_ads_info_json(ads);
627 2 : goto out;
628 : }
629 :
630 13 : pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
631 :
632 13 : print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
633 :
634 13 : d_printf(_("LDAP server: %s\n"), addr);
635 13 : d_printf(_("LDAP server name: %s\n"), ads->config.ldap_server_name);
636 13 : d_printf(_("Workgroup: %s\n"), ads->config.workgroup);
637 13 : d_printf(_("Realm: %s\n"), ads->config.realm);
638 13 : d_printf(_("Bind Path: %s\n"), ads->config.bind_path);
639 13 : d_printf(_("LDAP port: %d\n"), ads->ldap.port);
640 13 : d_printf(_("Server time: %s\n"),
641 13 : http_timestring(tmp_ctx, ads->config.current_time));
642 :
643 13 : d_printf(_("KDC server: %s\n"), ads->auth.kdc_server );
644 13 : d_printf(_("Server time offset: %d\n"), ads->auth.time_offset );
645 :
646 13 : d_printf(_("Last machine account password change: %s\n"),
647 : http_timestring(tmp_ctx, pass_time));
648 :
649 13 : ret = 0;
650 15 : out:
651 15 : TALLOC_FREE(tmp_ctx);
652 15 : return ret;
653 : }
654 :
655 192 : static ADS_STATUS ads_startup_int(struct net_context *c,
656 : bool only_own_domain,
657 : uint32_t auth_flags,
658 : TALLOC_CTX *mem_ctx,
659 : ADS_STRUCT **ads_ret)
660 : {
661 192 : ADS_STRUCT *ads = NULL;
662 0 : ADS_STATUS status;
663 192 : bool need_password = false;
664 192 : bool second_time = false;
665 0 : char *cp;
666 192 : const char *realm = NULL;
667 192 : bool tried_closest_dc = false;
668 192 : enum credentials_use_kerberos krb5_state =
669 : CRED_USE_KERBEROS_DISABLED;
670 :
671 : /* lp_realm() should be handled by a command line param,
672 : However, the join requires that realm be set in smb.conf
673 : and compares our realm with the remote server's so this is
674 : ok until someone needs more flexibility */
675 :
676 192 : *ads_ret = NULL;
677 :
678 192 : retry_connect:
679 192 : if (only_own_domain) {
680 114 : realm = lp_realm();
681 : } else {
682 78 : realm = assume_own_realm(c);
683 : }
684 :
685 192 : ads = ads_init(mem_ctx,
686 : realm,
687 : c->opt_target_workgroup,
688 : c->opt_host,
689 : ADS_SASL_PLAIN);
690 192 : if (ads == NULL) {
691 0 : return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
692 : }
693 :
694 192 : if (!c->opt_user_name) {
695 0 : c->opt_user_name = "administrator";
696 : }
697 :
698 192 : if (c->opt_user_specified) {
699 156 : need_password = true;
700 : }
701 :
702 192 : retry:
703 192 : if (!c->opt_password && need_password && !c->opt_machine_pass) {
704 116 : c->opt_password = net_prompt_pass(c, c->opt_user_name);
705 116 : if (!c->opt_password) {
706 0 : TALLOC_FREE(ads);
707 0 : return ADS_ERROR(LDAP_NO_MEMORY);
708 : }
709 : }
710 :
711 192 : if (c->opt_password) {
712 156 : use_in_memory_ccache();
713 156 : ADS_TALLOC_CONST_FREE(ads->auth.password);
714 156 : ads->auth.password = talloc_strdup(ads, c->opt_password);
715 156 : if (ads->auth.password == NULL) {
716 0 : TALLOC_FREE(ads);
717 0 : return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
718 : }
719 : }
720 :
721 192 : ADS_TALLOC_CONST_FREE(ads->auth.user_name);
722 192 : ads->auth.user_name = talloc_strdup(ads, c->opt_user_name);
723 192 : if (ads->auth.user_name == NULL) {
724 0 : TALLOC_FREE(ads);
725 0 : return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
726 : }
727 :
728 192 : ads->auth.flags |= auth_flags;
729 :
730 : /* The ADS code will handle FIPS mode */
731 192 : krb5_state = cli_credentials_get_kerberos_state(c->creds);
732 192 : switch (krb5_state) {
733 0 : case CRED_USE_KERBEROS_REQUIRED:
734 0 : ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
735 0 : ads->auth.flags &= ~ADS_AUTH_ALLOW_NTLMSSP;
736 0 : break;
737 190 : case CRED_USE_KERBEROS_DESIRED:
738 190 : ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
739 190 : ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
740 190 : break;
741 2 : case CRED_USE_KERBEROS_DISABLED:
742 2 : ads->auth.flags |= ADS_AUTH_DISABLE_KERBEROS;
743 2 : ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
744 2 : break;
745 : }
746 :
747 : /*
748 : * If the username is of the form "name@realm",
749 : * extract the realm and convert to upper case.
750 : * This is only used to establish the connection.
751 : */
752 192 : if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
753 40 : *cp++ = '\0';
754 40 : ADS_TALLOC_CONST_FREE(ads->auth.realm);
755 40 : ads->auth.realm = talloc_asprintf_strupper_m(ads, "%s", cp);
756 40 : if (ads->auth.realm == NULL) {
757 0 : TALLOC_FREE(ads);
758 0 : return ADS_ERROR(LDAP_NO_MEMORY);
759 : }
760 152 : } else if (ads->auth.realm == NULL) {
761 152 : const char *c_realm = cli_credentials_get_realm(c->creds);
762 :
763 152 : if (c_realm != NULL) {
764 152 : ads->auth.realm = talloc_strdup(ads, c_realm);
765 152 : if (ads->auth.realm == NULL) {
766 0 : TALLOC_FREE(ads);
767 0 : return ADS_ERROR(LDAP_NO_MEMORY);
768 : }
769 : }
770 : }
771 :
772 192 : status = ads_connect(ads);
773 :
774 192 : if (!ADS_ERR_OK(status)) {
775 :
776 1 : if (NT_STATUS_EQUAL(ads_ntstatus(status),
777 : NT_STATUS_NO_LOGON_SERVERS)) {
778 0 : DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
779 0 : TALLOC_FREE(ads);
780 0 : return status;
781 : }
782 :
783 1 : if (!need_password && !second_time && !(auth_flags & ADS_AUTH_NO_BIND)) {
784 0 : need_password = true;
785 0 : second_time = true;
786 0 : goto retry;
787 : } else {
788 1 : TALLOC_FREE(ads);
789 1 : return status;
790 : }
791 : }
792 :
793 : /* when contacting our own domain, make sure we use the closest DC.
794 : * This is done by reconnecting to ADS because only the first call to
795 : * ads_connect will give us our own sitename */
796 :
797 191 : if ((only_own_domain || !c->opt_host) && !tried_closest_dc) {
798 :
799 179 : tried_closest_dc = true; /* avoid loop */
800 :
801 179 : if (!ads_closest_dc(ads)) {
802 :
803 0 : namecache_delete(ads->server.realm, 0x1C);
804 0 : namecache_delete(ads->server.workgroup, 0x1C);
805 :
806 0 : TALLOC_FREE(ads);
807 :
808 0 : goto retry_connect;
809 : }
810 : }
811 :
812 191 : *ads_ret = talloc_move(mem_ctx, &ads);
813 191 : return status;
814 : }
815 :
816 156 : ADS_STATUS ads_startup(struct net_context *c,
817 : bool only_own_domain,
818 : TALLOC_CTX *mem_ctx,
819 : ADS_STRUCT **ads)
820 : {
821 156 : return ads_startup_int(c, only_own_domain, 0, mem_ctx, ads);
822 : }
823 :
824 36 : ADS_STATUS ads_startup_nobind(struct net_context *c,
825 : bool only_own_domain,
826 : TALLOC_CTX *mem_ctx,
827 : ADS_STRUCT **ads)
828 : {
829 36 : return ads_startup_int(c,
830 : only_own_domain,
831 : ADS_AUTH_NO_BIND,
832 : mem_ctx,
833 : ads);
834 : }
835 :
836 : /*
837 : Check to see if connection can be made via ads.
838 : ads_startup() stores the password in opt_password if it needs to so
839 : that rpc or rap can use it without re-prompting.
840 : */
841 28 : static int net_ads_check_int(struct net_context *c,
842 : const char *realm,
843 : const char *workgroup,
844 : const char *host)
845 : {
846 28 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
847 0 : ADS_STRUCT *ads;
848 0 : ADS_STATUS status;
849 28 : int ret = -1;
850 :
851 28 : ads = ads_init(tmp_ctx, realm, workgroup, host, ADS_SASL_PLAIN);
852 28 : if (ads == NULL) {
853 0 : goto out;
854 : }
855 :
856 28 : ads->auth.flags |= ADS_AUTH_NO_BIND;
857 :
858 28 : status = ads_connect(ads);
859 28 : if ( !ADS_ERR_OK(status) ) {
860 0 : goto out;
861 : }
862 :
863 28 : ret = 0;
864 28 : out:
865 28 : TALLOC_FREE(tmp_ctx);
866 28 : return ret;
867 : }
868 :
869 20 : int net_ads_check_our_domain(struct net_context *c)
870 : {
871 20 : return net_ads_check_int(c, lp_realm(), lp_workgroup(), NULL);
872 : }
873 :
874 8 : int net_ads_check(struct net_context *c)
875 : {
876 8 : return net_ads_check_int(c, NULL, c->opt_workgroup, c->opt_host);
877 : }
878 :
879 : /*
880 : determine the netbios workgroup name for a domain
881 : */
882 0 : static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
883 : {
884 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
885 0 : ADS_STRUCT *ads = NULL;
886 0 : ADS_STATUS status;
887 0 : struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
888 0 : bool ok = false;
889 0 : int ret = -1;
890 :
891 0 : if (c->display_usage) {
892 0 : d_printf ("%s\n"
893 : "net ads workgroup\n"
894 : " %s\n",
895 : _("Usage:"),
896 : _("Print the workgroup name"));
897 0 : TALLOC_FREE(tmp_ctx);
898 0 : return -1;
899 : }
900 :
901 0 : status = ads_startup_nobind(c, false, tmp_ctx, &ads);
902 0 : if (!ADS_ERR_OK(status)) {
903 0 : d_fprintf(stderr, _("Didn't find the cldap server!\n"));
904 0 : goto out;
905 : }
906 :
907 0 : if (!ads->config.realm) {
908 0 : ads->config.realm = talloc_strdup(ads, c->opt_target_workgroup);
909 0 : if (ads->config.realm == NULL) {
910 0 : d_fprintf(stderr, _("Out of memory\n"));
911 0 : goto out;
912 : }
913 0 : ads->ldap.port = 389;
914 : }
915 :
916 0 : ok = ads_cldap_netlogon_5(tmp_ctx,
917 0 : &ads->ldap.ss, ads->server.realm, &reply);
918 0 : if (!ok) {
919 0 : d_fprintf(stderr, _("CLDAP query failed!\n"));
920 0 : goto out;
921 : }
922 :
923 0 : d_printf(_("Workgroup: %s\n"), reply.domain_name);
924 :
925 0 : ret = 0;
926 0 : out:
927 0 : TALLOC_FREE(tmp_ctx);
928 :
929 0 : return ret;
930 : }
931 :
932 :
933 :
934 0 : static bool usergrp_display(ADS_STRUCT *ads, char *field, void **values, void *data_area)
935 : {
936 0 : char **disp_fields = (char **) data_area;
937 :
938 0 : if (!field) { /* must be end of record */
939 0 : if (disp_fields[0]) {
940 0 : if (!strchr_m(disp_fields[0], '$')) {
941 0 : if (disp_fields[1])
942 0 : d_printf("%-21.21s %s\n",
943 0 : disp_fields[0], disp_fields[1]);
944 : else
945 0 : d_printf("%s\n", disp_fields[0]);
946 : }
947 : }
948 0 : SAFE_FREE(disp_fields[0]);
949 0 : SAFE_FREE(disp_fields[1]);
950 0 : return true;
951 : }
952 0 : if (!values) /* must be new field, indicate string field */
953 0 : return true;
954 0 : if (strcasecmp_m(field, "sAMAccountName") == 0) {
955 0 : disp_fields[0] = SMB_STRDUP((char *) values[0]);
956 : }
957 0 : if (strcasecmp_m(field, "description") == 0)
958 0 : disp_fields[1] = SMB_STRDUP((char *) values[0]);
959 0 : return true;
960 : }
961 :
962 0 : static int net_ads_user_usage(struct net_context *c, int argc, const char **argv)
963 : {
964 0 : return net_user_usage(c, argc, argv);
965 : }
966 :
967 4 : static int ads_user_add(struct net_context *c, int argc, const char **argv)
968 : {
969 4 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
970 4 : ADS_STRUCT *ads = NULL;
971 0 : ADS_STATUS status;
972 0 : char *upn, *userdn;
973 4 : LDAPMessage *res=NULL;
974 4 : int rc = -1;
975 4 : char *ou_str = NULL;
976 :
977 4 : if (argc < 1 || c->display_usage) {
978 0 : TALLOC_FREE(tmp_ctx);
979 0 : return net_ads_user_usage(c, argc, argv);
980 : }
981 :
982 4 : status = ads_startup(c, false, tmp_ctx, &ads);
983 4 : if (!ADS_ERR_OK(status)) {
984 0 : goto done;
985 : }
986 :
987 4 : status = ads_find_user_acct(ads, &res, argv[0]);
988 4 : if (!ADS_ERR_OK(status)) {
989 0 : d_fprintf(stderr, _("ads_user_add: %s\n"), ads_errstr(status));
990 0 : goto done;
991 : }
992 :
993 4 : if (ads_count_replies(ads, res)) {
994 0 : d_fprintf(stderr, _("ads_user_add: User %s already exists\n"),
995 : argv[0]);
996 0 : goto done;
997 : }
998 :
999 4 : if (c->opt_container) {
1000 0 : ou_str = SMB_STRDUP(c->opt_container);
1001 : } else {
1002 4 : ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
1003 : }
1004 :
1005 4 : status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment);
1006 4 : if (!ADS_ERR_OK(status)) {
1007 0 : d_fprintf(stderr, _("Could not add user %s: %s\n"), argv[0],
1008 : ads_errstr(status));
1009 0 : goto done;
1010 : }
1011 :
1012 : /* if no password is to be set, we're done */
1013 4 : if (argc == 1) {
1014 0 : d_printf(_("User %s added\n"), argv[0]);
1015 0 : rc = 0;
1016 0 : goto done;
1017 : }
1018 :
1019 : /* try setting the password */
1020 4 : upn = talloc_asprintf(tmp_ctx,
1021 : "%s@%s",
1022 : argv[0],
1023 4 : ads->config.realm);
1024 4 : if (upn == NULL) {
1025 0 : goto done;
1026 : }
1027 :
1028 4 : status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
1029 4 : ads->auth.time_offset);
1030 4 : if (ADS_ERR_OK(status)) {
1031 4 : d_printf(_("User %s added\n"), argv[0]);
1032 4 : rc = 0;
1033 4 : goto done;
1034 : }
1035 0 : TALLOC_FREE(upn);
1036 :
1037 : /* password didn't set, delete account */
1038 0 : d_fprintf(stderr, _("Could not add user %s. "
1039 : "Error setting password %s\n"),
1040 : argv[0], ads_errstr(status));
1041 :
1042 0 : ads_msgfree(ads, res);
1043 0 : res = NULL;
1044 :
1045 0 : status=ads_find_user_acct(ads, &res, argv[0]);
1046 0 : if (ADS_ERR_OK(status)) {
1047 0 : userdn = ads_get_dn(ads, tmp_ctx, res);
1048 0 : ads_del_dn(ads, userdn);
1049 0 : TALLOC_FREE(userdn);
1050 : }
1051 :
1052 0 : done:
1053 4 : ads_msgfree(ads, res);
1054 4 : SAFE_FREE(ou_str);
1055 4 : TALLOC_FREE(tmp_ctx);
1056 4 : return rc;
1057 : }
1058 :
1059 0 : static int ads_user_info(struct net_context *c, int argc, const char **argv)
1060 : {
1061 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1062 0 : ADS_STRUCT *ads = NULL;
1063 0 : ADS_STATUS status;
1064 0 : LDAPMessage *res = NULL;
1065 0 : int ret = -1;
1066 0 : wbcErr wbc_status;
1067 0 : const char *attrs[] = {"memberOf", "primaryGroupID", NULL};
1068 0 : char *searchstring = NULL;
1069 0 : char **grouplist = NULL;
1070 0 : char *primary_group = NULL;
1071 0 : char *escaped_user = NULL;
1072 0 : struct dom_sid primary_group_sid;
1073 0 : uint32_t group_rid;
1074 0 : enum wbcSidType type;
1075 :
1076 0 : if (argc < 1 || c->display_usage) {
1077 0 : TALLOC_FREE(tmp_ctx);
1078 0 : return net_ads_user_usage(c, argc, argv);
1079 : }
1080 :
1081 0 : escaped_user = escape_ldap_string(tmp_ctx, argv[0]);
1082 0 : if (!escaped_user) {
1083 0 : d_fprintf(stderr,
1084 0 : _("ads_user_info: failed to escape user %s\n"),
1085 : argv[0]);
1086 0 : goto out;
1087 : }
1088 :
1089 0 : status = ads_startup(c, false, tmp_ctx, &ads);
1090 0 : if (!ADS_ERR_OK(status)) {
1091 0 : goto out;
1092 : }
1093 :
1094 0 : searchstring = talloc_asprintf(tmp_ctx,
1095 : "(sAMAccountName=%s)",
1096 : escaped_user);
1097 0 : if (searchstring == NULL) {
1098 0 : goto out;
1099 : }
1100 :
1101 0 : status = ads_search(ads, &res, searchstring, attrs);
1102 0 : if (!ADS_ERR_OK(status)) {
1103 0 : d_fprintf(stderr, _("ads_search: %s\n"), ads_errstr(status));
1104 0 : goto out;
1105 : }
1106 :
1107 0 : if (!ads_pull_uint32(ads, res, "primaryGroupID", &group_rid)) {
1108 0 : d_fprintf(stderr, _("ads_pull_uint32 failed\n"));
1109 0 : goto out;
1110 : }
1111 :
1112 0 : status = ads_domain_sid(ads, &primary_group_sid);
1113 0 : if (!ADS_ERR_OK(status)) {
1114 0 : d_fprintf(stderr, _("ads_domain_sid: %s\n"), ads_errstr(status));
1115 0 : goto out;
1116 : }
1117 :
1118 0 : sid_append_rid(&primary_group_sid, group_rid);
1119 :
1120 0 : wbc_status = wbcLookupSid((struct wbcDomainSid *)&primary_group_sid,
1121 : NULL, /* don't look up domain */
1122 : &primary_group,
1123 : &type);
1124 0 : if (!WBC_ERROR_IS_OK(wbc_status)) {
1125 0 : d_fprintf(stderr, "wbcLookupSid: %s\n",
1126 : wbcErrorString(wbc_status));
1127 0 : goto out;
1128 : }
1129 :
1130 0 : d_printf("%s\n", primary_group);
1131 :
1132 0 : wbcFreeMemory(primary_group);
1133 :
1134 0 : grouplist = ldap_get_values((LDAP *)ads->ldap.ld,
1135 : (LDAPMessage *)res, "memberOf");
1136 :
1137 0 : if (grouplist) {
1138 : int i;
1139 : char **groupname;
1140 0 : for (i=0;grouplist[i];i++) {
1141 0 : groupname = ldap_explode_dn(grouplist[i], 1);
1142 0 : d_printf("%s\n", groupname[0]);
1143 0 : ldap_value_free(groupname);
1144 : }
1145 0 : ldap_value_free(grouplist);
1146 : }
1147 :
1148 0 : ret = 0;
1149 0 : out:
1150 0 : TALLOC_FREE(escaped_user);
1151 0 : TALLOC_FREE(searchstring);
1152 0 : ads_msgfree(ads, res);
1153 0 : TALLOC_FREE(tmp_ctx);
1154 0 : return ret;
1155 : }
1156 :
1157 4 : static int ads_user_delete(struct net_context *c, int argc, const char **argv)
1158 : {
1159 4 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1160 4 : ADS_STRUCT *ads = NULL;
1161 0 : ADS_STATUS status;
1162 4 : LDAPMessage *res = NULL;
1163 4 : char *userdn = NULL;
1164 4 : int ret = -1;
1165 :
1166 4 : if (argc < 1) {
1167 0 : TALLOC_FREE(tmp_ctx);
1168 0 : return net_ads_user_usage(c, argc, argv);
1169 : }
1170 :
1171 4 : status = ads_startup(c, false, tmp_ctx, &ads);
1172 4 : if (!ADS_ERR_OK(status)) {
1173 0 : goto out;
1174 : }
1175 :
1176 4 : status = ads_find_user_acct(ads, &res, argv[0]);
1177 4 : if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1178 0 : d_printf(_("User %s does not exist.\n"), argv[0]);
1179 0 : goto out;
1180 : }
1181 :
1182 4 : userdn = ads_get_dn(ads, tmp_ctx, res);
1183 4 : if (userdn == NULL) {
1184 0 : goto out;
1185 : }
1186 :
1187 4 : status = ads_del_dn(ads, userdn);
1188 4 : if (!ADS_ERR_OK(status)) {
1189 0 : d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
1190 : ads_errstr(status));
1191 0 : goto out;
1192 : }
1193 :
1194 4 : d_printf(_("User %s deleted\n"), argv[0]);
1195 :
1196 4 : ret = 0;
1197 4 : out:
1198 4 : ads_msgfree(ads, res);
1199 4 : TALLOC_FREE(tmp_ctx);
1200 4 : return ret;
1201 : }
1202 :
1203 8 : int net_ads_user(struct net_context *c, int argc, const char **argv)
1204 : {
1205 8 : struct functable func[] = {
1206 : {
1207 : "add",
1208 : ads_user_add,
1209 : NET_TRANSPORT_ADS,
1210 : N_("Add an AD user"),
1211 : N_("net ads user add\n"
1212 : " Add an AD user")
1213 : },
1214 : {
1215 : "info",
1216 : ads_user_info,
1217 : NET_TRANSPORT_ADS,
1218 : N_("Display information about an AD user"),
1219 : N_("net ads user info\n"
1220 : " Display information about an AD user")
1221 : },
1222 : {
1223 : "delete",
1224 : ads_user_delete,
1225 : NET_TRANSPORT_ADS,
1226 : N_("Delete an AD user"),
1227 : N_("net ads user delete\n"
1228 : " Delete an AD user")
1229 : },
1230 : {NULL, NULL, 0, NULL, NULL}
1231 : };
1232 8 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1233 8 : ADS_STRUCT *ads = NULL;
1234 0 : ADS_STATUS status;
1235 8 : const char *shortattrs[] = {"sAMAccountName", NULL};
1236 8 : const char *longattrs[] = {"sAMAccountName", "description", NULL};
1237 8 : char *disp_fields[2] = {NULL, NULL};
1238 8 : int ret = -1;
1239 :
1240 8 : if (argc > 0) {
1241 8 : TALLOC_FREE(tmp_ctx);
1242 8 : return net_run_function(c, argc, argv, "net ads user", func);
1243 : }
1244 :
1245 0 : if (c->display_usage) {
1246 0 : d_printf( "%s\n"
1247 : "net ads user\n"
1248 : " %s\n",
1249 : _("Usage:"),
1250 : _("List AD users"));
1251 0 : net_display_usage_from_functable(func);
1252 0 : TALLOC_FREE(tmp_ctx);
1253 0 : return -1;
1254 : }
1255 :
1256 0 : status = ads_startup(c, false, tmp_ctx, &ads);
1257 0 : if (!ADS_ERR_OK(status)) {
1258 0 : goto out;
1259 : }
1260 :
1261 0 : if (c->opt_long_list_entries)
1262 0 : d_printf(_("\nUser name Comment"
1263 : "\n-----------------------------\n"));
1264 :
1265 0 : status = ads_do_search_all_fn(ads,
1266 0 : ads->config.bind_path,
1267 : LDAP_SCOPE_SUBTREE,
1268 : "(objectCategory=user)",
1269 0 : c->opt_long_list_entries ?
1270 : longattrs : shortattrs,
1271 : usergrp_display,
1272 : disp_fields);
1273 0 : if (!ADS_ERR_OK(status)) {
1274 0 : goto out;
1275 : }
1276 :
1277 0 : ret = 0;
1278 0 : out:
1279 0 : TALLOC_FREE(tmp_ctx);
1280 0 : return ret;
1281 : }
1282 :
1283 0 : static int net_ads_group_usage(struct net_context *c, int argc, const char **argv)
1284 : {
1285 0 : return net_group_usage(c, argc, argv);
1286 : }
1287 :
1288 0 : static int ads_group_add(struct net_context *c, int argc, const char **argv)
1289 : {
1290 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1291 0 : ADS_STRUCT *ads = NULL;
1292 0 : ADS_STATUS status;
1293 0 : LDAPMessage *res = NULL;
1294 0 : int ret = -1;
1295 0 : char *ou_str = NULL;
1296 :
1297 0 : if (argc < 1 || c->display_usage) {
1298 0 : TALLOC_FREE(tmp_ctx);
1299 0 : return net_ads_group_usage(c, argc, argv);
1300 : }
1301 :
1302 0 : status = ads_startup(c, false, tmp_ctx, &ads);
1303 0 : if (!ADS_ERR_OK(status)) {
1304 0 : goto out;
1305 : }
1306 :
1307 0 : status = ads_find_user_acct(ads, &res, argv[0]);
1308 0 : if (!ADS_ERR_OK(status)) {
1309 0 : d_fprintf(stderr, _("ads_group_add: %s\n"), ads_errstr(status));
1310 0 : goto out;
1311 : }
1312 :
1313 0 : if (ads_count_replies(ads, res)) {
1314 0 : d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]);
1315 0 : goto out;
1316 : }
1317 :
1318 0 : if (c->opt_container) {
1319 0 : ou_str = SMB_STRDUP(c->opt_container);
1320 : } else {
1321 0 : ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
1322 : }
1323 :
1324 0 : status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
1325 0 : if (!ADS_ERR_OK(status)) {
1326 0 : d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0],
1327 : ads_errstr(status));
1328 0 : goto out;
1329 : }
1330 :
1331 0 : d_printf(_("Group %s added\n"), argv[0]);
1332 :
1333 0 : ret = 0;
1334 0 : out:
1335 0 : ads_msgfree(ads, res);
1336 0 : SAFE_FREE(ou_str);
1337 0 : TALLOC_FREE(tmp_ctx);
1338 0 : return ret;
1339 : }
1340 :
1341 0 : static int ads_group_delete(struct net_context *c, int argc, const char **argv)
1342 : {
1343 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1344 0 : ADS_STRUCT *ads = NULL;
1345 0 : ADS_STATUS status;
1346 0 : LDAPMessage *res = NULL;
1347 0 : char *groupdn = NULL;
1348 0 : int ret = -1;
1349 :
1350 0 : if (argc < 1 || c->display_usage) {
1351 0 : TALLOC_FREE(tmp_ctx);
1352 0 : return net_ads_group_usage(c, argc, argv);
1353 : }
1354 :
1355 0 : status = ads_startup(c, false, tmp_ctx, &ads);
1356 0 : if (!ADS_ERR_OK(status)) {
1357 0 : goto out;
1358 : }
1359 :
1360 0 : status = ads_find_user_acct(ads, &res, argv[0]);
1361 0 : if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1362 0 : d_printf(_("Group %s does not exist.\n"), argv[0]);
1363 0 : goto out;
1364 : }
1365 :
1366 0 : groupdn = ads_get_dn(ads, tmp_ctx, res);
1367 0 : if (groupdn == NULL) {
1368 0 : goto out;
1369 : }
1370 :
1371 0 : status = ads_del_dn(ads, groupdn);
1372 0 : if (!ADS_ERR_OK(status)) {
1373 0 : d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
1374 : ads_errstr(status));
1375 0 : goto out;
1376 : }
1377 0 : d_printf(_("Group %s deleted\n"), argv[0]);
1378 :
1379 0 : ret = 0;
1380 0 : out:
1381 0 : ads_msgfree(ads, res);
1382 0 : TALLOC_FREE(tmp_ctx);
1383 0 : return ret;
1384 : }
1385 :
1386 0 : int net_ads_group(struct net_context *c, int argc, const char **argv)
1387 : {
1388 0 : struct functable func[] = {
1389 : {
1390 : "add",
1391 : ads_group_add,
1392 : NET_TRANSPORT_ADS,
1393 : N_("Add an AD group"),
1394 : N_("net ads group add\n"
1395 : " Add an AD group")
1396 : },
1397 : {
1398 : "delete",
1399 : ads_group_delete,
1400 : NET_TRANSPORT_ADS,
1401 : N_("Delete an AD group"),
1402 : N_("net ads group delete\n"
1403 : " Delete an AD group")
1404 : },
1405 : {NULL, NULL, 0, NULL, NULL}
1406 : };
1407 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1408 0 : ADS_STRUCT *ads = NULL;
1409 0 : ADS_STATUS status;
1410 0 : const char *shortattrs[] = {"sAMAccountName", NULL};
1411 0 : const char *longattrs[] = {"sAMAccountName", "description", NULL};
1412 0 : char *disp_fields[2] = {NULL, NULL};
1413 0 : int ret = -1;
1414 :
1415 0 : if (argc >= 0) {
1416 0 : TALLOC_FREE(tmp_ctx);
1417 0 : return net_run_function(c, argc, argv, "net ads group", func);
1418 : }
1419 :
1420 0 : if (c->display_usage) {
1421 0 : d_printf( "%s\n"
1422 : "net ads group\n"
1423 : " %s\n",
1424 : _("Usage:"),
1425 : _("List AD groups"));
1426 0 : net_display_usage_from_functable(func);
1427 0 : TALLOC_FREE(tmp_ctx);
1428 0 : return -1;
1429 : }
1430 :
1431 0 : status = ads_startup(c, false, tmp_ctx, &ads);
1432 0 : if (!ADS_ERR_OK(status)) {
1433 0 : goto out;
1434 : }
1435 :
1436 0 : if (c->opt_long_list_entries)
1437 0 : d_printf(_("\nGroup name Comment"
1438 : "\n-----------------------------\n"));
1439 :
1440 0 : status = ads_do_search_all_fn(ads,
1441 0 : ads->config.bind_path,
1442 : LDAP_SCOPE_SUBTREE,
1443 : "(objectCategory=group)",
1444 0 : c->opt_long_list_entries ?
1445 : longattrs : shortattrs,
1446 : usergrp_display,
1447 : disp_fields);
1448 0 : if (!ADS_ERR_OK(status)) {
1449 0 : goto out;
1450 : }
1451 :
1452 0 : ret = 0;
1453 0 : out:
1454 0 : TALLOC_FREE(tmp_ctx);
1455 0 : return ret;
1456 : }
1457 :
1458 0 : static int net_ads_status(struct net_context *c, int argc, const char **argv)
1459 : {
1460 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1461 0 : ADS_STRUCT *ads = NULL;
1462 0 : ADS_STATUS status;
1463 0 : LDAPMessage *res = NULL;
1464 0 : int ret = -1;
1465 :
1466 0 : if (c->display_usage) {
1467 0 : d_printf( "%s\n"
1468 : "net ads status\n"
1469 : " %s\n",
1470 : _("Usage:"),
1471 : _("Display machine account details"));
1472 0 : TALLOC_FREE(tmp_ctx);
1473 0 : return -1;
1474 : }
1475 :
1476 0 : net_warn_member_options();
1477 :
1478 0 : status = ads_startup(c, true, tmp_ctx, &ads);
1479 0 : if (!ADS_ERR_OK(status)) {
1480 0 : goto out;
1481 : }
1482 :
1483 0 : status = ads_find_machine_acct(ads, &res, lp_netbios_name());
1484 0 : if (!ADS_ERR_OK(status)) {
1485 0 : d_fprintf(stderr, _("ads_find_machine_acct: %s\n"),
1486 : ads_errstr(status));
1487 0 : goto out;
1488 : }
1489 :
1490 0 : if (ads_count_replies(ads, res) == 0) {
1491 0 : d_fprintf(stderr, _("No machine account for '%s' found\n"),
1492 : lp_netbios_name());
1493 0 : goto out;
1494 : }
1495 :
1496 0 : ads_dump(ads, res);
1497 :
1498 0 : ret = 0;
1499 0 : out:
1500 0 : ads_msgfree(ads, res);
1501 0 : TALLOC_FREE(tmp_ctx);
1502 0 : return ret;
1503 : }
1504 :
1505 : /*******************************************************************
1506 : Leave an AD domain. Windows XP disables the machine account.
1507 : We'll try the same. The old code would do an LDAP delete.
1508 : That only worked using the machine creds because added the machine
1509 : with full control to the computer object's ACL.
1510 : *******************************************************************/
1511 :
1512 34 : static int net_ads_leave(struct net_context *c, int argc, const char **argv)
1513 : {
1514 34 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1515 34 : struct libnet_UnjoinCtx *r = NULL;
1516 0 : WERROR werr;
1517 34 : int ret = -1;
1518 :
1519 34 : if (c->display_usage) {
1520 0 : d_printf( "%s\n"
1521 : "net ads leave [--keep-account]\n"
1522 : " %s\n",
1523 : _("Usage:"),
1524 : _("Leave an AD domain"));
1525 0 : TALLOC_FREE(tmp_ctx);
1526 0 : return -1;
1527 : }
1528 :
1529 34 : if (!*lp_realm()) {
1530 0 : d_fprintf(stderr, _("No realm set, are we joined ?\n"));
1531 0 : TALLOC_FREE(tmp_ctx);
1532 0 : return -1;
1533 : }
1534 :
1535 34 : if (!c->opt_kerberos) {
1536 32 : use_in_memory_ccache();
1537 : }
1538 :
1539 34 : if (!c->msg_ctx) {
1540 0 : d_fprintf(stderr, _("Could not initialise message context. "
1541 : "Try running as root\n"));
1542 0 : goto done;
1543 : }
1544 :
1545 34 : werr = libnet_init_UnjoinCtx(tmp_ctx, &r);
1546 34 : if (!W_ERROR_IS_OK(werr)) {
1547 0 : d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
1548 0 : goto done;
1549 : }
1550 :
1551 34 : r->in.debug = true;
1552 34 : r->in.use_kerberos = c->opt_kerberos;
1553 34 : r->in.dc_name = c->opt_host;
1554 34 : r->in.domain_name = lp_realm();
1555 34 : r->in.admin_account = c->opt_user_name;
1556 34 : r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1557 34 : r->in.modify_config = lp_config_backend_is_registry();
1558 :
1559 : /* Try to delete it, but if that fails, disable it. The
1560 : WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1561 34 : r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1562 : WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
1563 34 : if (c->opt_keep_account) {
1564 2 : r->in.delete_machine_account = false;
1565 : } else {
1566 32 : r->in.delete_machine_account = true;
1567 : }
1568 :
1569 34 : r->in.msg_ctx = c->msg_ctx;
1570 :
1571 34 : werr = libnet_Unjoin(tmp_ctx, r);
1572 34 : if (!W_ERROR_IS_OK(werr)) {
1573 2 : d_printf(_("Failed to leave domain: %s\n"),
1574 2 : r->out.error_string ? r->out.error_string :
1575 0 : get_friendly_werror_msg(werr));
1576 2 : goto done;
1577 : }
1578 :
1579 32 : if (r->out.deleted_machine_account) {
1580 30 : d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1581 30 : r->in.machine_name, r->out.dns_domain_name);
1582 30 : ret = 0;
1583 30 : goto done;
1584 : }
1585 :
1586 : /* We couldn't delete it - see if the disable succeeded. */
1587 2 : if (r->out.disabled_machine_account) {
1588 2 : d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1589 2 : r->in.machine_name, r->out.dns_domain_name);
1590 2 : ret = 0;
1591 2 : goto done;
1592 : }
1593 :
1594 : /* Based on what we requested, we shouldn't get here, but if
1595 : we did, it means the secrets were removed, and therefore
1596 : we have left the domain */
1597 0 : d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"),
1598 0 : r->in.machine_name, r->out.dns_domain_name);
1599 :
1600 0 : ret = 0;
1601 34 : done:
1602 34 : TALLOC_FREE(tmp_ctx);
1603 34 : return ret;
1604 : }
1605 :
1606 30 : static ADS_STATUS net_ads_join_ok(struct net_context *c)
1607 : {
1608 30 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1609 30 : ADS_STRUCT *ads = NULL;
1610 0 : ADS_STATUS status;
1611 0 : fstring dc_name;
1612 0 : struct sockaddr_storage dcip;
1613 :
1614 30 : if (!secrets_init()) {
1615 0 : DEBUG(1,("Failed to initialise secrets database\n"));
1616 0 : TALLOC_FREE(tmp_ctx);
1617 0 : return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
1618 : }
1619 :
1620 30 : net_warn_member_options();
1621 :
1622 30 : net_use_krb_machine_account(c);
1623 :
1624 30 : get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
1625 :
1626 30 : status = ads_startup(c, true, tmp_ctx, &ads);
1627 30 : if (!ADS_ERR_OK(status)) {
1628 0 : goto out;
1629 : }
1630 :
1631 30 : status = ADS_ERROR_NT(NT_STATUS_OK);
1632 30 : out:
1633 30 : TALLOC_FREE(tmp_ctx);
1634 30 : return status;
1635 : }
1636 :
1637 : /*
1638 : check that an existing join is OK
1639 : */
1640 30 : int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
1641 : {
1642 0 : ADS_STATUS status;
1643 30 : use_in_memory_ccache();
1644 :
1645 30 : if (c->display_usage) {
1646 0 : d_printf( "%s\n"
1647 : "net ads testjoin\n"
1648 : " %s\n",
1649 : _("Usage:"),
1650 : _("Test if the existing join is ok"));
1651 0 : return -1;
1652 : }
1653 :
1654 30 : net_warn_member_options();
1655 :
1656 : /* Display success or failure */
1657 30 : status = net_ads_join_ok(c);
1658 30 : if (!ADS_ERR_OK(status)) {
1659 0 : fprintf(stderr, _("Join to domain is not valid: %s\n"),
1660 : get_friendly_nt_error_msg(ads_ntstatus(status)));
1661 0 : return -1;
1662 : }
1663 :
1664 30 : printf(_("Join is OK\n"));
1665 30 : return 0;
1666 : }
1667 :
1668 : /*******************************************************************
1669 : Simple config checks before beginning the join
1670 : ********************************************************************/
1671 :
1672 42 : static WERROR check_ads_config( void )
1673 : {
1674 42 : if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
1675 0 : d_printf(_("Host is not configured as a member server.\n"));
1676 0 : return WERR_INVALID_DOMAIN_ROLE;
1677 : }
1678 :
1679 42 : if (strlen(lp_netbios_name()) > 15) {
1680 0 : d_printf(_("Our netbios name can be at most 15 chars long, "
1681 : "\"%s\" is %u chars long\n"), lp_netbios_name(),
1682 0 : (unsigned int)strlen(lp_netbios_name()));
1683 0 : return WERR_INVALID_COMPUTERNAME;
1684 : }
1685 :
1686 42 : if ( lp_security() == SEC_ADS && !*lp_realm()) {
1687 0 : d_fprintf(stderr, _("realm must be set in %s for ADS "
1688 : "join to succeed.\n"), get_dyn_CONFIGFILE());
1689 0 : return WERR_INVALID_PARAMETER;
1690 : }
1691 :
1692 42 : return WERR_OK;
1693 : }
1694 :
1695 : /*******************************************************************
1696 : ********************************************************************/
1697 :
1698 0 : static int net_ads_join_usage(struct net_context *c, int argc, const char **argv)
1699 : {
1700 0 : d_printf(_("net ads join [--no-dns-updates] [options]\n"
1701 : "Valid options:\n"));
1702 0 : d_printf(_(" dnshostname=FQDN Set the dnsHostName attribute during the join.\n"
1703 : " The default is in the form netbiosname.dnsdomain\n"));
1704 0 : d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1705 : " The default UPN is in the form host/netbiosname@REALM.\n"));
1706 0 : d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1707 : " The OU string read from top to bottom without RDNs\n"
1708 : " and delimited by a '/'.\n"
1709 : " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1710 : " NB: A backslash '\\' is used as escape at multiple\n"
1711 : " levels and may need to be doubled or even\n"
1712 : " quadrupled. It is not used as a separator.\n"));
1713 0 : d_printf(_(" machinepass=PASS Set the machine password to a specific value during\n"
1714 : " the join. The default password is random.\n"));
1715 0 : d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1716 0 : d_printf(_(" osVer=string Set the operatingSystemVersion attribute during join.\n"
1717 : " NB: osName and osVer must be specified together for\n"
1718 : " either to take effect. The operatingSystemService\n"
1719 : " attribute is then also set along with the two\n"
1720 : " other attributes.\n"));
1721 0 : d_printf(_(" osServicePack=string Set the operatingSystemServicePack attribute\n"
1722 : " during the join.\n"
1723 : " NB: If not specified then by default the samba\n"
1724 : " version string is used instead.\n"));
1725 0 : return -1;
1726 : }
1727 :
1728 :
1729 42 : int net_ads_join(struct net_context *c, int argc, const char **argv)
1730 : {
1731 42 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1732 42 : struct libnet_JoinCtx *r = NULL;
1733 42 : const char *domain = lp_realm();
1734 42 : WERROR werr = WERR_NERR_SETUPNOTJOINED;
1735 42 : bool createupn = false;
1736 42 : const char *dnshostname = NULL;
1737 42 : const char *machineupn = NULL;
1738 42 : const char *machine_password = NULL;
1739 42 : const char *create_in_ou = NULL;
1740 0 : int i;
1741 42 : const char *os_name = NULL;
1742 42 : const char *os_version = NULL;
1743 42 : const char *os_servicepack = NULL;
1744 42 : bool modify_config = lp_config_backend_is_registry();
1745 42 : enum libnetjoin_JoinDomNameType domain_name_type = JoinDomNameTypeDNS;
1746 42 : int ret = -1;
1747 :
1748 42 : if (c->display_usage) {
1749 0 : TALLOC_FREE(tmp_ctx);
1750 0 : return net_ads_join_usage(c, argc, argv);
1751 : }
1752 :
1753 42 : net_warn_member_options();
1754 :
1755 42 : if (!modify_config) {
1756 42 : werr = check_ads_config();
1757 42 : if (!W_ERROR_IS_OK(werr)) {
1758 0 : d_fprintf(stderr, _("Invalid configuration. Exiting....\n"));
1759 0 : goto fail;
1760 : }
1761 : }
1762 :
1763 42 : if (!c->opt_kerberos) {
1764 30 : use_in_memory_ccache();
1765 : }
1766 :
1767 42 : werr = libnet_init_JoinCtx(tmp_ctx, &r);
1768 42 : if (!W_ERROR_IS_OK(werr)) {
1769 0 : goto fail;
1770 : }
1771 :
1772 : /* process additional command line args */
1773 :
1774 48 : for ( i=0; i<argc; i++ ) {
1775 6 : if ( !strncasecmp_m(argv[i], "dnshostname", strlen("dnshostname")) ) {
1776 2 : dnshostname = get_string_param(argv[i]);
1777 : }
1778 4 : else if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
1779 2 : createupn = true;
1780 2 : machineupn = get_string_param(argv[i]);
1781 : }
1782 2 : else if ( !strncasecmp_m(argv[i], "createcomputer", strlen("createcomputer")) ) {
1783 2 : if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
1784 0 : d_fprintf(stderr, _("Please supply a valid OU path.\n"));
1785 0 : werr = WERR_INVALID_PARAMETER;
1786 0 : goto fail;
1787 : }
1788 : }
1789 0 : else if ( !strncasecmp_m(argv[i], "osName", strlen("osName")) ) {
1790 0 : if ( (os_name = get_string_param(argv[i])) == NULL ) {
1791 0 : d_fprintf(stderr, _("Please supply a operating system name.\n"));
1792 0 : werr = WERR_INVALID_PARAMETER;
1793 0 : goto fail;
1794 : }
1795 : }
1796 0 : else if ( !strncasecmp_m(argv[i], "osVer", strlen("osVer")) ) {
1797 0 : if ( (os_version = get_string_param(argv[i])) == NULL ) {
1798 0 : d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
1799 0 : werr = WERR_INVALID_PARAMETER;
1800 0 : goto fail;
1801 : }
1802 : }
1803 0 : else if ( !strncasecmp_m(argv[i], "osServicePack", strlen("osServicePack")) ) {
1804 0 : if ( (os_servicepack = get_string_param(argv[i])) == NULL ) {
1805 0 : d_fprintf(stderr, _("Please supply a valid servicepack identifier.\n"));
1806 0 : werr = WERR_INVALID_PARAMETER;
1807 0 : goto fail;
1808 : }
1809 : }
1810 0 : else if ( !strncasecmp_m(argv[i], "machinepass", strlen("machinepass")) ) {
1811 0 : if ( (machine_password = get_string_param(argv[i])) == NULL ) {
1812 0 : d_fprintf(stderr, _("Please supply a valid password to set as trust account password.\n"));
1813 0 : werr = WERR_INVALID_PARAMETER;
1814 0 : goto fail;
1815 : }
1816 : } else {
1817 0 : domain = argv[i];
1818 0 : if (strchr(domain, '.') == NULL) {
1819 0 : domain_name_type = JoinDomNameTypeUnknown;
1820 : } else {
1821 0 : domain_name_type = JoinDomNameTypeDNS;
1822 : }
1823 : }
1824 : }
1825 :
1826 42 : if (!*domain) {
1827 0 : d_fprintf(stderr, _("Please supply a valid domain name\n"));
1828 0 : werr = WERR_INVALID_PARAMETER;
1829 0 : goto fail;
1830 : }
1831 :
1832 42 : if (!c->msg_ctx) {
1833 0 : d_fprintf(stderr, _("Could not initialise message context. "
1834 : "Try running as root\n"));
1835 0 : werr = WERR_ACCESS_DENIED;
1836 0 : goto fail;
1837 : }
1838 :
1839 : /* Do the domain join here */
1840 :
1841 42 : r->in.domain_name = domain;
1842 42 : r->in.domain_name_type = domain_name_type;
1843 42 : r->in.create_upn = createupn;
1844 42 : r->in.upn = machineupn;
1845 42 : r->in.dnshostname = dnshostname;
1846 42 : r->in.account_ou = create_in_ou;
1847 42 : r->in.os_name = os_name;
1848 42 : r->in.os_version = os_version;
1849 42 : r->in.os_servicepack = os_servicepack;
1850 42 : r->in.dc_name = c->opt_host;
1851 42 : r->in.admin_account = c->opt_user_name;
1852 42 : r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1853 42 : r->in.machine_password = machine_password;
1854 42 : r->in.debug = true;
1855 42 : r->in.use_kerberos = c->opt_kerberos;
1856 42 : r->in.modify_config = modify_config;
1857 42 : r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1858 : WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
1859 : WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
1860 42 : r->in.msg_ctx = c->msg_ctx;
1861 :
1862 42 : werr = libnet_Join(tmp_ctx, r);
1863 46 : if (W_ERROR_EQUAL(werr, WERR_NERR_DCNOTFOUND) &&
1864 4 : strequal(domain, lp_realm())) {
1865 4 : r->in.domain_name = lp_workgroup();
1866 4 : r->in.domain_name_type = JoinDomNameTypeNBT;
1867 4 : werr = libnet_Join(tmp_ctx, r);
1868 : }
1869 42 : if (!W_ERROR_IS_OK(werr)) {
1870 2 : goto fail;
1871 : }
1872 :
1873 : /* Check the short name of the domain */
1874 :
1875 40 : if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
1876 0 : d_printf(_("The workgroup in %s does not match the short\n"
1877 : "domain name obtained from the server.\n"
1878 : "Using the name [%s] from the server.\n"
1879 : "You should set \"workgroup = %s\" in %s.\n"),
1880 0 : get_dyn_CONFIGFILE(), r->out.netbios_domain_name,
1881 0 : r->out.netbios_domain_name, get_dyn_CONFIGFILE());
1882 : }
1883 :
1884 40 : d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name);
1885 :
1886 40 : if (r->out.dns_domain_name) {
1887 40 : d_printf(_("Joined '%s' to dns domain '%s'\n"), r->in.machine_name,
1888 40 : r->out.dns_domain_name);
1889 : } else {
1890 0 : d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name,
1891 0 : r->out.netbios_domain_name);
1892 : }
1893 :
1894 : /* print out informative error string in case there is one */
1895 40 : if (r->out.error_string != NULL) {
1896 0 : d_printf("%s\n", r->out.error_string);
1897 : }
1898 :
1899 : /*
1900 : * We try doing the dns update (if it was compiled in
1901 : * and if it was not disabled on the command line).
1902 : * If the dns update fails, we still consider the join
1903 : * operation as succeeded if we came this far.
1904 : */
1905 40 : if (!c->opt_no_dns_updates) {
1906 40 : net_ads_join_dns_updates(c, tmp_ctx, r);
1907 : }
1908 :
1909 40 : ret = 0;
1910 :
1911 42 : fail:
1912 42 : if (ret != 0) {
1913 : /* issue an overall failure message at the end. */
1914 2 : d_printf(_("Failed to join domain: %s\n"),
1915 2 : r && r->out.error_string ? r->out.error_string :
1916 0 : get_friendly_werror_msg(werr));
1917 : }
1918 :
1919 42 : TALLOC_FREE(tmp_ctx);
1920 :
1921 42 : return ret;
1922 : }
1923 :
1924 : /*******************************************************************
1925 : ********************************************************************/
1926 :
1927 12 : static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
1928 : {
1929 : #if defined(HAVE_KRB5)
1930 12 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1931 12 : ADS_STRUCT *ads = NULL;
1932 0 : ADS_STATUS status;
1933 0 : NTSTATUS ntstatus;
1934 12 : const char *hostname = NULL;
1935 12 : const char **addrs_list = NULL;
1936 12 : struct sockaddr_storage *addrs = NULL;
1937 12 : int num_addrs = 0;
1938 0 : int count;
1939 12 : int ret = -1;
1940 :
1941 : #ifdef DEVELOPER
1942 12 : talloc_enable_leak_report();
1943 : #endif
1944 :
1945 12 : if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
1946 0 : d_fprintf(stderr, _("Refusing DNS updates with automatic "
1947 : "detection of addresses in a clustered "
1948 : "setup.\n"));
1949 0 : c->display_usage = true;
1950 : }
1951 :
1952 12 : if (c->display_usage) {
1953 0 : d_printf( "%s\n"
1954 : "net ads dns register [hostname [IP [IP...]]] "
1955 : "[--force] [--dns-ttl TTL]\n"
1956 : " %s\n",
1957 : _("Usage:"),
1958 : _("Register hostname with DNS\n"));
1959 0 : TALLOC_FREE(tmp_ctx);
1960 0 : return -1;
1961 : }
1962 :
1963 12 : if (argc >= 1) {
1964 12 : hostname = argv[0];
1965 : }
1966 :
1967 12 : if (argc > 1) {
1968 12 : num_addrs = argc - 1;
1969 12 : addrs_list = &argv[1];
1970 0 : } else if (lp_clustering()) {
1971 0 : addrs_list = lp_cluster_addresses();
1972 0 : num_addrs = str_list_length(addrs_list);
1973 : }
1974 :
1975 12 : if (num_addrs > 0) {
1976 12 : addrs = talloc_zero_array(tmp_ctx,
1977 : struct sockaddr_storage,
1978 : num_addrs);
1979 12 : if (addrs == NULL) {
1980 0 : d_fprintf(stderr, _("Error allocating memory!\n"));
1981 0 : goto out;
1982 : }
1983 : }
1984 :
1985 26 : for (count = 0; count < num_addrs; count++) {
1986 14 : if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
1987 0 : d_fprintf(stderr, "%s '%s'.\n",
1988 : _("Cannot interpret address"),
1989 0 : addrs_list[count]);
1990 0 : goto out;
1991 : }
1992 : }
1993 :
1994 12 : status = ads_startup(c, true, tmp_ctx, &ads);
1995 12 : if ( !ADS_ERR_OK(status) ) {
1996 0 : DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1997 0 : goto out;
1998 : }
1999 :
2000 12 : ntstatus = net_update_dns_ext(c,
2001 : tmp_ctx,
2002 : ads,
2003 : hostname,
2004 : addrs,
2005 : num_addrs,
2006 : false);
2007 12 : if (!NT_STATUS_IS_OK(ntstatus)) {
2008 2 : d_fprintf( stderr, _("DNS update failed!\n") );
2009 2 : goto out;
2010 : }
2011 :
2012 10 : d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
2013 :
2014 10 : ret = 0;
2015 12 : out:
2016 12 : TALLOC_FREE(tmp_ctx);
2017 :
2018 12 : return ret;
2019 : #else
2020 : d_fprintf(stderr,
2021 : _("DNS update support not enabled at compile time!\n"));
2022 : return -1;
2023 : #endif
2024 : }
2025 :
2026 8 : static int net_ads_dns_unregister(struct net_context *c,
2027 : int argc,
2028 : const char **argv)
2029 : {
2030 : #if defined(HAVE_KRB5)
2031 8 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2032 8 : ADS_STRUCT *ads = NULL;
2033 0 : ADS_STATUS status;
2034 0 : NTSTATUS ntstatus;
2035 8 : const char *hostname = NULL;
2036 8 : int ret = -1;
2037 :
2038 : #ifdef DEVELOPER
2039 8 : talloc_enable_leak_report();
2040 : #endif
2041 :
2042 8 : if (argc != 1) {
2043 0 : c->display_usage = true;
2044 : }
2045 :
2046 8 : if (c->display_usage) {
2047 0 : d_printf( "%s\n"
2048 : "net ads dns unregister [hostname]\n"
2049 : " %s\n",
2050 : _("Usage:"),
2051 : _("Remove all IP Address entries for a given\n"
2052 : " hostname from the Active Directory server.\n"));
2053 0 : TALLOC_FREE(tmp_ctx);
2054 0 : return -1;
2055 : }
2056 :
2057 : /* Get the hostname for un-registering */
2058 8 : hostname = argv[0];
2059 :
2060 8 : status = ads_startup(c, true, tmp_ctx, &ads);
2061 8 : if ( !ADS_ERR_OK(status) ) {
2062 0 : DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
2063 0 : goto out;
2064 : }
2065 :
2066 8 : ntstatus = net_update_dns_ext(c,
2067 : tmp_ctx,
2068 : ads,
2069 : hostname,
2070 : NULL,
2071 : 0,
2072 : true);
2073 8 : if (!NT_STATUS_IS_OK(ntstatus)) {
2074 0 : d_fprintf( stderr, _("DNS update failed!\n") );
2075 0 : goto out;
2076 : }
2077 :
2078 8 : d_fprintf( stderr, _("Successfully un-registered hostname from DNS\n"));
2079 :
2080 8 : ret = 0;
2081 8 : out:
2082 8 : TALLOC_FREE(tmp_ctx);
2083 :
2084 8 : return ret;
2085 : #else
2086 : d_fprintf(stderr,
2087 : _("DNS update support not enabled at compile time!\n"));
2088 : return -1;
2089 : #endif
2090 : }
2091 :
2092 :
2093 2 : static int net_ads_dns_async(struct net_context *c, int argc, const char **argv)
2094 : {
2095 2 : size_t num_names = 0;
2096 2 : char **hostnames = NULL;
2097 2 : size_t i = 0;
2098 2 : struct samba_sockaddr *addrs = NULL;
2099 0 : NTSTATUS status;
2100 :
2101 2 : if (argc != 1 || c->display_usage) {
2102 0 : d_printf( "%s\n"
2103 : " %s\n"
2104 : " %s\n",
2105 : _("Usage:"),
2106 : _("net ads dns async <name>\n"),
2107 : _(" Async look up hostname from the DNS server\n"
2108 : " hostname\tName to look up\n"));
2109 0 : return -1;
2110 : }
2111 :
2112 2 : status = ads_dns_lookup_a(talloc_tos(),
2113 : argv[0],
2114 : &num_names,
2115 : &hostnames,
2116 : &addrs);
2117 2 : if (!NT_STATUS_IS_OK(status)) {
2118 0 : d_printf("Looking up A record for %s got error %s\n",
2119 : argv[0],
2120 : nt_errstr(status));
2121 0 : return -1;
2122 : }
2123 2 : d_printf("Async A record lookup - got %u names for %s\n",
2124 : (unsigned int)num_names,
2125 : argv[0]);
2126 4 : for (i = 0; i < num_names; i++) {
2127 0 : char addr_buf[INET6_ADDRSTRLEN];
2128 2 : print_sockaddr(addr_buf,
2129 : sizeof(addr_buf),
2130 2 : &addrs[i].u.ss);
2131 2 : d_printf("hostname[%u] = %s, IPv4addr = %s\n",
2132 : (unsigned int)i,
2133 2 : hostnames[i],
2134 : addr_buf);
2135 : }
2136 :
2137 : #if defined(HAVE_IPV6)
2138 2 : status = ads_dns_lookup_aaaa(talloc_tos(),
2139 : argv[0],
2140 : &num_names,
2141 : &hostnames,
2142 : &addrs);
2143 2 : if (!NT_STATUS_IS_OK(status)) {
2144 0 : d_printf("Looking up AAAA record for %s got error %s\n",
2145 : argv[0],
2146 : nt_errstr(status));
2147 0 : return -1;
2148 : }
2149 2 : d_printf("Async AAAA record lookup - got %u names for %s\n",
2150 : (unsigned int)num_names,
2151 : argv[0]);
2152 4 : for (i = 0; i < num_names; i++) {
2153 0 : char addr_buf[INET6_ADDRSTRLEN];
2154 2 : print_sockaddr(addr_buf,
2155 : sizeof(addr_buf),
2156 2 : &addrs[i].u.ss);
2157 2 : d_printf("hostname[%u] = %s, IPv6addr = %s\n",
2158 : (unsigned int)i,
2159 2 : hostnames[i],
2160 : addr_buf);
2161 : }
2162 : #endif
2163 2 : return 0;
2164 : }
2165 :
2166 :
2167 22 : static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
2168 : {
2169 22 : struct functable func[] = {
2170 : {
2171 : "register",
2172 : net_ads_dns_register,
2173 : NET_TRANSPORT_ADS,
2174 : N_("Add host dns entry to AD"),
2175 : N_("net ads dns register\n"
2176 : " Add host dns entry to AD")
2177 : },
2178 : {
2179 : "unregister",
2180 : net_ads_dns_unregister,
2181 : NET_TRANSPORT_ADS,
2182 : N_("Remove host dns entry from AD"),
2183 : N_("net ads dns unregister\n"
2184 : " Remove host dns entry from AD")
2185 : },
2186 : {
2187 : "async",
2188 : net_ads_dns_async,
2189 : NET_TRANSPORT_ADS,
2190 : N_("Look up host"),
2191 : N_("net ads dns async\n"
2192 : " Look up host using async DNS")
2193 : },
2194 : {NULL, NULL, 0, NULL, NULL}
2195 : };
2196 :
2197 22 : return net_run_function(c, argc, argv, "net ads dns", func);
2198 : }
2199 :
2200 : /*******************************************************************
2201 : ********************************************************************/
2202 :
2203 0 : int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
2204 : {
2205 0 : d_printf(_(
2206 : "\nnet ads printer search <printer>"
2207 : "\n\tsearch for a printer in the directory\n"
2208 : "\nnet ads printer info <printer> <server>"
2209 : "\n\tlookup info in directory for printer on server"
2210 : "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
2211 : "\nnet ads printer publish <printername>"
2212 : "\n\tpublish printer in directory"
2213 : "\n\t(note: printer name is required)\n"
2214 : "\nnet ads printer remove <printername>"
2215 : "\n\tremove printer from directory"
2216 : "\n\t(note: printer name is required)\n"));
2217 0 : return -1;
2218 : }
2219 :
2220 : /*******************************************************************
2221 : ********************************************************************/
2222 :
2223 0 : static int net_ads_printer_search(struct net_context *c,
2224 : int argc,
2225 : const char **argv)
2226 : {
2227 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2228 0 : ADS_STRUCT *ads = NULL;
2229 0 : ADS_STATUS status;
2230 0 : LDAPMessage *res = NULL;
2231 0 : int ret = -1;
2232 :
2233 0 : if (c->display_usage) {
2234 0 : d_printf( "%s\n"
2235 : "net ads printer search\n"
2236 : " %s\n",
2237 : _("Usage:"),
2238 : _("List printers in the AD"));
2239 0 : TALLOC_FREE(tmp_ctx);
2240 0 : return -1;
2241 : }
2242 :
2243 0 : status = ads_startup(c, false, tmp_ctx, &ads);
2244 0 : if (!ADS_ERR_OK(status)) {
2245 0 : goto out;
2246 : }
2247 :
2248 0 : status = ads_find_printers(ads, &res);
2249 0 : if (!ADS_ERR_OK(status)) {
2250 0 : d_fprintf(stderr, _("ads_find_printer: %s\n"),
2251 : ads_errstr(status));
2252 0 : goto out;
2253 : }
2254 :
2255 0 : if (ads_count_replies(ads, res) == 0) {
2256 0 : d_fprintf(stderr, _("No results found\n"));
2257 0 : goto out;
2258 : }
2259 :
2260 0 : ads_dump(ads, res);
2261 :
2262 0 : ret = 0;
2263 0 : out:
2264 0 : ads_msgfree(ads, res);
2265 0 : TALLOC_FREE(tmp_ctx);
2266 0 : return ret;
2267 : }
2268 :
2269 0 : static int net_ads_printer_info(struct net_context *c,
2270 : int argc,
2271 : const char **argv)
2272 : {
2273 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2274 0 : ADS_STRUCT *ads = NULL;
2275 0 : ADS_STATUS status;
2276 0 : const char *servername = NULL;
2277 0 : const char *printername = NULL;
2278 0 : LDAPMessage *res = NULL;
2279 0 : int ret = -1;
2280 :
2281 0 : if (c->display_usage) {
2282 0 : d_printf("%s\n%s",
2283 : _("Usage:"),
2284 : _("net ads printer info [printername [servername]]\n"
2285 : " Display printer info from AD\n"
2286 : " printername\tPrinter name or wildcard\n"
2287 : " servername\tName of the print server\n"));
2288 0 : TALLOC_FREE(tmp_ctx);
2289 0 : return -1;
2290 : }
2291 :
2292 0 : status = ads_startup(c, false, tmp_ctx, &ads);
2293 0 : if (!ADS_ERR_OK(status)) {
2294 0 : goto out;
2295 : }
2296 :
2297 0 : if (argc > 0) {
2298 0 : printername = argv[0];
2299 : } else {
2300 0 : printername = "*";
2301 : }
2302 :
2303 0 : if (argc > 1) {
2304 0 : servername = argv[1];
2305 : } else {
2306 0 : servername = lp_netbios_name();
2307 : }
2308 :
2309 0 : status = ads_find_printer_on_server(ads, &res, printername, servername);
2310 0 : if (!ADS_ERR_OK(status)) {
2311 0 : d_fprintf(stderr, _("Server '%s' not found: %s\n"),
2312 : servername, ads_errstr(status));
2313 0 : goto out;
2314 : }
2315 :
2316 0 : if (ads_count_replies(ads, res) == 0) {
2317 0 : d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
2318 0 : goto out;
2319 : }
2320 :
2321 0 : ads_dump(ads, res);
2322 :
2323 0 : ret = 0;
2324 0 : out:
2325 0 : ads_msgfree(ads, res);
2326 0 : TALLOC_FREE(tmp_ctx);
2327 0 : return ret;
2328 : }
2329 :
2330 0 : static int net_ads_printer_publish(struct net_context *c,
2331 : int argc,
2332 : const char **argv)
2333 : {
2334 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2335 0 : ADS_STRUCT *ads = NULL;
2336 0 : ADS_STATUS status;
2337 0 : const char *servername = NULL;
2338 0 : const char *printername = NULL;
2339 0 : struct cli_state *cli = NULL;
2340 0 : struct rpc_pipe_client *pipe_hnd = NULL;
2341 0 : struct sockaddr_storage server_ss = { 0 };
2342 0 : NTSTATUS nt_status;
2343 0 : ADS_MODLIST mods = NULL;
2344 0 : char *prt_dn = NULL;
2345 0 : char *srv_dn = NULL;
2346 0 : char **srv_cn = NULL;
2347 0 : char *srv_cn_escaped = NULL;
2348 0 : char *printername_escaped = NULL;
2349 0 : LDAPMessage *res = NULL;
2350 0 : bool ok;
2351 0 : int ret = -1;
2352 :
2353 0 : if (argc < 1 || c->display_usage) {
2354 0 : d_printf("%s\n%s",
2355 : _("Usage:"),
2356 : _("net ads printer publish <printername> [servername]\n"
2357 : " Publish printer in AD\n"
2358 : " printername\tName of the printer\n"
2359 : " servername\tName of the print server\n"));
2360 0 : TALLOC_FREE(tmp_ctx);
2361 0 : return -1;
2362 : }
2363 :
2364 0 : mods = ads_init_mods(tmp_ctx);
2365 0 : if (mods == NULL) {
2366 0 : d_fprintf(stderr, _("Out of memory\n"));
2367 0 : goto out;
2368 : }
2369 :
2370 0 : status = ads_startup(c, true, tmp_ctx, &ads);
2371 0 : if (!ADS_ERR_OK(status)) {
2372 0 : goto out;
2373 : }
2374 :
2375 0 : printername = argv[0];
2376 :
2377 0 : if (argc == 2) {
2378 0 : servername = argv[1];
2379 : } else {
2380 0 : servername = lp_netbios_name();
2381 : }
2382 :
2383 : /* Get printer data from SPOOLSS */
2384 :
2385 0 : ok = resolve_name(servername, &server_ss, 0x20, false);
2386 0 : if (!ok) {
2387 0 : d_fprintf(stderr, _("Could not find server %s\n"),
2388 : servername);
2389 0 : goto out;
2390 : }
2391 :
2392 0 : cli_credentials_set_kerberos_state(c->creds,
2393 : CRED_USE_KERBEROS_REQUIRED,
2394 : CRED_SPECIFIED);
2395 :
2396 0 : nt_status = cli_full_connection_creds(&cli, lp_netbios_name(), servername,
2397 : &server_ss, 0,
2398 : "IPC$", "IPC",
2399 : c->creds,
2400 : CLI_FULL_CONNECTION_IPC);
2401 :
2402 0 : if (NT_STATUS_IS_ERR(nt_status)) {
2403 0 : d_fprintf(stderr, _("Unable to open a connection to %s to "
2404 : "obtain data for %s\n"),
2405 : servername, printername);
2406 0 : goto out;
2407 : }
2408 :
2409 : /* Publish on AD server */
2410 :
2411 0 : ads_find_machine_acct(ads, &res, servername);
2412 :
2413 0 : if (ads_count_replies(ads, res) == 0) {
2414 0 : d_fprintf(stderr, _("Could not find machine account for server "
2415 : "%s\n"),
2416 : servername);
2417 0 : goto out;
2418 : }
2419 :
2420 0 : srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
2421 0 : srv_cn = ldap_explode_dn(srv_dn, 1);
2422 :
2423 0 : srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
2424 0 : printername_escaped = escape_rdn_val_string_alloc(printername);
2425 0 : if (!srv_cn_escaped || !printername_escaped) {
2426 0 : SAFE_FREE(srv_cn_escaped);
2427 0 : SAFE_FREE(printername_escaped);
2428 0 : d_fprintf(stderr, _("Internal error, out of memory!"));
2429 0 : goto out;
2430 : }
2431 :
2432 0 : prt_dn = talloc_asprintf(tmp_ctx,
2433 : "cn=%s-%s,%s",
2434 : srv_cn_escaped,
2435 : printername_escaped,
2436 : srv_dn);
2437 0 : if (prt_dn == NULL) {
2438 0 : SAFE_FREE(srv_cn_escaped);
2439 0 : SAFE_FREE(printername_escaped);
2440 0 : d_fprintf(stderr, _("Internal error, out of memory!"));
2441 0 : goto out;
2442 : }
2443 :
2444 0 : SAFE_FREE(srv_cn_escaped);
2445 0 : SAFE_FREE(printername_escaped);
2446 :
2447 0 : nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd);
2448 0 : if (!NT_STATUS_IS_OK(nt_status)) {
2449 0 : d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
2450 : servername);
2451 0 : goto out;
2452 : }
2453 :
2454 0 : if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd,
2455 : tmp_ctx,
2456 : &mods,
2457 : printername))) {
2458 0 : goto out;
2459 : }
2460 :
2461 0 : status = ads_add_printer_entry(ads, prt_dn, tmp_ctx, &mods);
2462 0 : if (!ADS_ERR_OK(status)) {
2463 0 : d_fprintf(stderr, "ads_publish_printer: %s\n",
2464 : ads_errstr(status));
2465 0 : goto out;
2466 : }
2467 :
2468 0 : d_printf("published printer\n");
2469 :
2470 0 : ret = 0;
2471 0 : out:
2472 0 : talloc_destroy(tmp_ctx);
2473 :
2474 0 : return ret;
2475 : }
2476 :
2477 0 : static int net_ads_printer_remove(struct net_context *c,
2478 : int argc,
2479 : const char **argv)
2480 : {
2481 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2482 0 : ADS_STRUCT *ads = NULL;
2483 0 : ADS_STATUS status;
2484 0 : const char *servername = NULL;
2485 0 : char *prt_dn = NULL;
2486 0 : LDAPMessage *res = NULL;
2487 0 : int ret = -1;
2488 :
2489 0 : if (argc < 1 || c->display_usage) {
2490 0 : d_printf("%s\n%s",
2491 : _("Usage:"),
2492 : _("net ads printer remove <printername> [servername]\n"
2493 : " Remove a printer from the AD\n"
2494 : " printername\tName of the printer\n"
2495 : " servername\tName of the print server\n"));
2496 0 : TALLOC_FREE(tmp_ctx);
2497 0 : return -1;
2498 : }
2499 :
2500 0 : status = ads_startup(c, true, tmp_ctx, &ads);
2501 0 : if (!ADS_ERR_OK(status)) {
2502 0 : goto out;
2503 : }
2504 :
2505 0 : if (argc > 1) {
2506 0 : servername = argv[1];
2507 : } else {
2508 0 : servername = lp_netbios_name();
2509 : }
2510 :
2511 0 : status = ads_find_printer_on_server(ads, &res, argv[0], servername);
2512 0 : if (!ADS_ERR_OK(status)) {
2513 0 : d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"),
2514 : ads_errstr(status));
2515 0 : goto out;
2516 : }
2517 :
2518 0 : if (ads_count_replies(ads, res) == 0) {
2519 0 : d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
2520 0 : goto out;
2521 : }
2522 :
2523 0 : prt_dn = ads_get_dn(ads, tmp_ctx, res);
2524 0 : if (prt_dn == NULL) {
2525 0 : d_fprintf(stderr, _("Out of memory\n"));
2526 0 : goto out;
2527 : }
2528 :
2529 0 : status = ads_del_dn(ads, prt_dn);
2530 0 : if (!ADS_ERR_OK(status)) {
2531 0 : d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(status));
2532 0 : goto out;
2533 : }
2534 :
2535 0 : ret = 0;
2536 0 : out:
2537 0 : ads_msgfree(ads, res);
2538 0 : TALLOC_FREE(tmp_ctx);
2539 0 : return ret;
2540 : }
2541 :
2542 0 : static int net_ads_printer(struct net_context *c, int argc, const char **argv)
2543 : {
2544 0 : struct functable func[] = {
2545 : {
2546 : "search",
2547 : net_ads_printer_search,
2548 : NET_TRANSPORT_ADS,
2549 : N_("Search for a printer"),
2550 : N_("net ads printer search\n"
2551 : " Search for a printer")
2552 : },
2553 : {
2554 : "info",
2555 : net_ads_printer_info,
2556 : NET_TRANSPORT_ADS,
2557 : N_("Display printer information"),
2558 : N_("net ads printer info\n"
2559 : " Display printer information")
2560 : },
2561 : {
2562 : "publish",
2563 : net_ads_printer_publish,
2564 : NET_TRANSPORT_ADS,
2565 : N_("Publish a printer"),
2566 : N_("net ads printer publish\n"
2567 : " Publish a printer")
2568 : },
2569 : {
2570 : "remove",
2571 : net_ads_printer_remove,
2572 : NET_TRANSPORT_ADS,
2573 : N_("Delete a printer"),
2574 : N_("net ads printer remove\n"
2575 : " Delete a printer")
2576 : },
2577 : {NULL, NULL, 0, NULL, NULL}
2578 : };
2579 :
2580 0 : return net_run_function(c, argc, argv, "net ads printer", func);
2581 : }
2582 :
2583 :
2584 4 : static int net_ads_password(struct net_context *c, int argc, const char **argv)
2585 : {
2586 4 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2587 4 : ADS_STRUCT *ads = NULL;
2588 4 : const char *auth_principal = cli_credentials_get_username(c->creds);
2589 4 : const char *auth_password = cli_credentials_get_password(c->creds);
2590 4 : const char *realm = NULL;
2591 4 : char *new_password = NULL;
2592 4 : char *chr = NULL;
2593 4 : char *prompt = NULL;
2594 4 : const char *user = NULL;
2595 4 : char pwd[256] = {0};
2596 0 : ADS_STATUS status;
2597 4 : int ret = 0;
2598 :
2599 4 : if (c->display_usage) {
2600 0 : d_printf("%s\n%s",
2601 : _("Usage:"),
2602 : _("net ads password <username>\n"
2603 : " Change password for user\n"
2604 : " username\tName of user to change password for\n"));
2605 0 : TALLOC_FREE(tmp_ctx);
2606 0 : return -1;
2607 : }
2608 :
2609 4 : if (auth_principal == NULL || auth_password == NULL) {
2610 0 : d_fprintf(stderr, _("You must supply an administrator "
2611 : "username/password\n"));
2612 0 : TALLOC_FREE(tmp_ctx);
2613 0 : return -1;
2614 : }
2615 :
2616 4 : if (argc < 1) {
2617 0 : d_fprintf(stderr, _("ERROR: You must say which username to "
2618 : "change password for\n"));
2619 0 : TALLOC_FREE(tmp_ctx);
2620 0 : return -1;
2621 : }
2622 :
2623 4 : if (strchr_m(argv[0], '@')) {
2624 4 : user = talloc_strdup(tmp_ctx, argv[0]);
2625 : } else {
2626 0 : user = talloc_asprintf(tmp_ctx, "%s@%s", argv[0], lp_realm());
2627 : }
2628 4 : if (user == NULL) {
2629 0 : d_fprintf(stderr, _("Out of memory\n"));
2630 0 : goto out;
2631 : }
2632 :
2633 4 : use_in_memory_ccache();
2634 4 : chr = strchr_m(auth_principal, '@');
2635 4 : if (chr) {
2636 4 : realm = ++chr;
2637 : } else {
2638 0 : realm = lp_realm();
2639 : }
2640 :
2641 : /* use the realm so we can eventually change passwords for users
2642 : in realms other than default */
2643 4 : ads = ads_init(tmp_ctx,
2644 : realm,
2645 : c->opt_workgroup,
2646 : c->opt_host,
2647 : ADS_SASL_PLAIN);
2648 4 : if (ads == NULL) {
2649 0 : goto out;
2650 : }
2651 :
2652 : /* we don't actually need a full connect, but it's the easy way to
2653 : fill in the KDC's address */
2654 4 : ads_connect(ads);
2655 :
2656 4 : if (!ads->config.realm) {
2657 0 : d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
2658 0 : goto out;
2659 : }
2660 :
2661 4 : if (argv[1] != NULL) {
2662 4 : new_password = talloc_strdup(tmp_ctx, argv[1]);
2663 : } else {
2664 0 : int rc;
2665 :
2666 0 : prompt = talloc_asprintf(tmp_ctx, _("Enter new password for %s:"), user);
2667 0 : if (prompt == NULL) {
2668 0 : d_fprintf(stderr, _("Out of memory\n"));
2669 0 : goto out;
2670 : }
2671 :
2672 0 : rc = samba_getpass(prompt, pwd, sizeof(pwd), false, true);
2673 0 : if (rc < 0) {
2674 0 : goto out;
2675 : }
2676 0 : new_password = talloc_strdup(tmp_ctx, pwd);
2677 0 : memset(pwd, '\0', sizeof(pwd));
2678 : }
2679 :
2680 4 : if (new_password == NULL) {
2681 0 : d_fprintf(stderr, _("Out of memory\n"));
2682 0 : goto out;
2683 : }
2684 :
2685 4 : status = kerberos_set_password(ads->auth.kdc_server,
2686 : auth_principal,
2687 : auth_password,
2688 : user,
2689 : new_password,
2690 : ads->auth.time_offset);
2691 4 : memset(new_password, '\0', strlen(new_password));
2692 4 : if (!ADS_ERR_OK(status)) {
2693 0 : d_fprintf(stderr, _("Password change failed: %s\n"),
2694 : ads_errstr(status));
2695 0 : goto out;
2696 : }
2697 :
2698 4 : d_printf(_("Password change for %s completed.\n"), user);
2699 :
2700 4 : ret = 0;
2701 4 : out:
2702 4 : TALLOC_FREE(tmp_ctx);
2703 4 : return ret;
2704 : }
2705 :
2706 4 : int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2707 : {
2708 4 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2709 4 : ADS_STRUCT *ads = NULL;
2710 4 : char *host_principal = NULL;
2711 4 : char *my_name = NULL;
2712 0 : ADS_STATUS status;
2713 4 : int ret = -1;
2714 :
2715 4 : if (c->display_usage) {
2716 0 : d_printf( "%s\n"
2717 : "net ads changetrustpw\n"
2718 : " %s\n",
2719 : _("Usage:"),
2720 : _("Change the machine account's trust password"));
2721 0 : TALLOC_FREE(tmp_ctx);
2722 0 : return -1;
2723 : }
2724 :
2725 4 : if (!secrets_init()) {
2726 0 : DEBUG(1,("Failed to initialise secrets database\n"));
2727 0 : goto out;
2728 : }
2729 :
2730 4 : net_warn_member_options();
2731 :
2732 4 : net_use_krb_machine_account(c);
2733 :
2734 4 : use_in_memory_ccache();
2735 :
2736 4 : status = ads_startup(c, true, tmp_ctx, &ads);
2737 4 : if (!ADS_ERR_OK(status)) {
2738 0 : goto out;
2739 : }
2740 :
2741 4 : my_name = talloc_asprintf_strlower_m(tmp_ctx, "%s", lp_netbios_name());
2742 4 : if (my_name == NULL) {
2743 0 : d_fprintf(stderr, _("Out of memory\n"));
2744 0 : goto out;
2745 : }
2746 :
2747 4 : host_principal = talloc_asprintf(tmp_ctx, "%s$@%s", my_name, ads->config.realm);
2748 4 : if (host_principal == NULL) {
2749 0 : d_fprintf(stderr, _("Out of memory\n"));
2750 0 : goto out;
2751 : }
2752 :
2753 4 : d_printf(_("Changing password for principal: %s\n"), host_principal);
2754 :
2755 4 : status = ads_change_trust_account_password(ads, host_principal);
2756 4 : if (!ADS_ERR_OK(status)) {
2757 0 : d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(status));
2758 0 : goto out;
2759 : }
2760 :
2761 4 : d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2762 :
2763 4 : if (USE_SYSTEM_KEYTAB) {
2764 0 : d_printf(_("Attempting to update system keytab with new password.\n"));
2765 0 : if (ads_keytab_create_default(ads)) {
2766 0 : d_printf(_("Failed to update system keytab.\n"));
2767 : }
2768 : }
2769 :
2770 4 : ret = 0;
2771 4 : out:
2772 4 : TALLOC_FREE(tmp_ctx);
2773 :
2774 4 : return ret;
2775 : }
2776 :
2777 : /*
2778 : help for net ads search
2779 : */
2780 0 : static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2781 : {
2782 0 : d_printf(_(
2783 : "\nnet ads search <expression> <attributes...>\n"
2784 : "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2785 : "The expression is a standard LDAP search expression, and the\n"
2786 : "attributes are a list of LDAP fields to show in the results.\n\n"
2787 : "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2788 : ));
2789 0 : net_common_flags_usage(c, argc, argv);
2790 0 : return -1;
2791 : }
2792 :
2793 :
2794 : /*
2795 : general ADS search function. Useful in diagnosing problems in ADS
2796 : */
2797 34 : static int net_ads_search(struct net_context *c, int argc, const char **argv)
2798 : {
2799 34 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2800 34 : ADS_STRUCT *ads = NULL;
2801 0 : ADS_STATUS status;
2802 34 : const char *ldap_exp = NULL;
2803 34 : const char **attrs = NULL;
2804 34 : LDAPMessage *res = NULL;
2805 34 : int ret = -1;
2806 :
2807 34 : if (argc < 1 || c->display_usage) {
2808 0 : TALLOC_FREE(tmp_ctx);
2809 0 : return net_ads_search_usage(c, argc, argv);
2810 : }
2811 :
2812 34 : status = ads_startup(c, false, tmp_ctx, &ads);
2813 34 : if (!ADS_ERR_OK(status)) {
2814 1 : goto out;
2815 : }
2816 :
2817 33 : ldap_exp = argv[0];
2818 33 : attrs = (argv + 1);
2819 :
2820 33 : status = ads_do_search_retry(ads,
2821 33 : ads->config.bind_path,
2822 : LDAP_SCOPE_SUBTREE,
2823 : ldap_exp,
2824 : attrs,
2825 : &res);
2826 33 : if (!ADS_ERR_OK(status)) {
2827 0 : d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2828 0 : goto out;
2829 : }
2830 :
2831 33 : d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2832 :
2833 : /* dump the results */
2834 33 : ads_dump(ads, res);
2835 :
2836 33 : ret = 0;
2837 34 : out:
2838 34 : ads_msgfree(ads, res);
2839 34 : TALLOC_FREE(tmp_ctx);
2840 34 : return ret;
2841 : }
2842 :
2843 :
2844 : /*
2845 : help for net ads search
2846 : */
2847 0 : static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2848 : {
2849 0 : d_printf(_(
2850 : "\nnet ads dn <dn> <attributes...>\n"
2851 : "\nperform a raw LDAP search on a ADS server and dump the results\n"
2852 : "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2853 : "to show in the results\n\n"
2854 : "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2855 : "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2856 : ));
2857 0 : net_common_flags_usage(c, argc, argv);
2858 0 : return -1;
2859 : }
2860 :
2861 :
2862 : /*
2863 : general ADS search function. Useful in diagnosing problems in ADS
2864 : */
2865 0 : static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2866 : {
2867 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2868 0 : ADS_STRUCT *ads = NULL;
2869 0 : ADS_STATUS status;
2870 0 : const char *dn = NULL;
2871 0 : const char **attrs = NULL;
2872 0 : LDAPMessage *res = NULL;
2873 0 : int ret = -1;
2874 :
2875 0 : if (argc < 1 || c->display_usage) {
2876 0 : TALLOC_FREE(tmp_ctx);
2877 0 : return net_ads_dn_usage(c, argc, argv);
2878 : }
2879 :
2880 0 : status = ads_startup(c, false, tmp_ctx, &ads);
2881 0 : if (!ADS_ERR_OK(status)) {
2882 0 : goto out;
2883 : }
2884 :
2885 0 : dn = argv[0];
2886 0 : attrs = (argv + 1);
2887 :
2888 0 : status = ads_do_search_all(ads,
2889 : dn,
2890 : LDAP_SCOPE_BASE,
2891 : "(objectclass=*)",
2892 : attrs,
2893 : &res);
2894 0 : if (!ADS_ERR_OK(status)) {
2895 0 : d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2896 0 : goto out;
2897 : }
2898 :
2899 0 : d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2900 :
2901 : /* dump the results */
2902 0 : ads_dump(ads, res);
2903 :
2904 0 : ret = 0;
2905 0 : out:
2906 0 : ads_msgfree(ads, res);
2907 0 : TALLOC_FREE(tmp_ctx);
2908 0 : return ret;
2909 : }
2910 :
2911 : /*
2912 : help for net ads sid search
2913 : */
2914 0 : static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2915 : {
2916 0 : d_printf(_(
2917 : "\nnet ads sid <sid> <attributes...>\n"
2918 : "\nperform a raw LDAP search on a ADS server and dump the results\n"
2919 : "The SID is in string format, and the attributes are a list of LDAP fields \n"
2920 : "to show in the results\n\n"
2921 : "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2922 : ));
2923 0 : net_common_flags_usage(c, argc, argv);
2924 0 : return -1;
2925 : }
2926 :
2927 :
2928 : /*
2929 : general ADS search function. Useful in diagnosing problems in ADS
2930 : */
2931 0 : static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2932 : {
2933 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2934 0 : ADS_STRUCT *ads = NULL;
2935 0 : ADS_STATUS status;
2936 0 : const char *sid_string = NULL;
2937 0 : const char **attrs = NULL;
2938 0 : LDAPMessage *res = NULL;
2939 0 : struct dom_sid sid = { 0 };
2940 0 : int ret = -1;
2941 :
2942 0 : if (argc < 1 || c->display_usage) {
2943 0 : TALLOC_FREE(tmp_ctx);
2944 0 : return net_ads_sid_usage(c, argc, argv);
2945 : }
2946 :
2947 0 : status = ads_startup(c, false, tmp_ctx, &ads);
2948 0 : if (!ADS_ERR_OK(status)) {
2949 0 : goto out;
2950 : }
2951 :
2952 0 : sid_string = argv[0];
2953 0 : attrs = (argv + 1);
2954 :
2955 0 : if (!string_to_sid(&sid, sid_string)) {
2956 0 : d_fprintf(stderr, _("could not convert sid\n"));
2957 0 : goto out;
2958 : }
2959 :
2960 0 : status = ads_search_retry_sid(ads, &res, &sid, attrs);
2961 0 : if (!ADS_ERR_OK(status)) {
2962 0 : d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2963 0 : goto out;
2964 : }
2965 :
2966 0 : d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2967 :
2968 : /* dump the results */
2969 0 : ads_dump(ads, res);
2970 :
2971 0 : ret = 0;
2972 0 : out:
2973 0 : ads_msgfree(ads, res);
2974 0 : TALLOC_FREE(tmp_ctx);
2975 0 : return ret;
2976 : }
2977 :
2978 0 : static int net_ads_keytab_flush(struct net_context *c,
2979 : int argc,
2980 : const char **argv)
2981 : {
2982 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2983 0 : ADS_STRUCT *ads = NULL;
2984 0 : ADS_STATUS status;
2985 0 : int ret = -1;
2986 :
2987 0 : if (c->display_usage) {
2988 0 : d_printf( "%s\n"
2989 : "net ads keytab flush\n"
2990 : " %s\n",
2991 : _("Usage:"),
2992 : _("Delete the whole keytab"));
2993 0 : TALLOC_FREE(tmp_ctx);
2994 0 : return -1;
2995 : }
2996 :
2997 0 : if (!c->opt_user_specified && c->opt_password == NULL) {
2998 0 : net_use_krb_machine_account(c);
2999 : }
3000 :
3001 0 : status = ads_startup(c, true, tmp_ctx, &ads);
3002 0 : if (!ADS_ERR_OK(status)) {
3003 0 : goto out;
3004 : }
3005 :
3006 0 : ret = ads_keytab_flush(ads);
3007 0 : out:
3008 0 : TALLOC_FREE(tmp_ctx);
3009 0 : return ret;
3010 : }
3011 :
3012 16 : static int net_ads_keytab_add(struct net_context *c,
3013 : int argc,
3014 : const char **argv,
3015 : bool update_ads)
3016 : {
3017 16 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3018 16 : ADS_STRUCT *ads = NULL;
3019 0 : ADS_STATUS status;
3020 0 : int i;
3021 16 : int ret = -1;
3022 :
3023 16 : if (c->display_usage) {
3024 0 : d_printf("%s\n%s",
3025 : _("Usage:"),
3026 : _("net ads keytab add <principal> [principal ...]\n"
3027 : " Add principals to local keytab\n"
3028 : " principal\tKerberos principal to add to "
3029 : "keytab\n"));
3030 0 : TALLOC_FREE(tmp_ctx);
3031 0 : return -1;
3032 : }
3033 :
3034 16 : net_warn_member_options();
3035 :
3036 16 : d_printf(_("Processing principals to add...\n"));
3037 :
3038 16 : if (!c->opt_user_specified && c->opt_password == NULL) {
3039 0 : net_use_krb_machine_account(c);
3040 : }
3041 :
3042 16 : status = ads_startup(c, true, tmp_ctx, &ads);
3043 16 : if (!ADS_ERR_OK(status)) {
3044 0 : goto out;
3045 : }
3046 :
3047 32 : for (ret = 0, i = 0; i < argc; i++) {
3048 16 : ret |= ads_keytab_add_entry(ads, argv[i], update_ads);
3049 : }
3050 16 : out:
3051 16 : TALLOC_FREE(tmp_ctx);
3052 16 : return ret;
3053 : }
3054 :
3055 14 : static int net_ads_keytab_add_default(struct net_context *c,
3056 : int argc,
3057 : const char **argv)
3058 : {
3059 14 : return net_ads_keytab_add(c, argc, argv, false);
3060 : }
3061 :
3062 2 : static int net_ads_keytab_add_update_ads(struct net_context *c,
3063 : int argc,
3064 : const char **argv)
3065 : {
3066 2 : return net_ads_keytab_add(c, argc, argv, true);
3067 : }
3068 :
3069 12 : static int net_ads_keytab_delete(struct net_context *c,
3070 : int argc,
3071 : const char **argv)
3072 : {
3073 12 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3074 12 : ADS_STRUCT *ads = NULL;
3075 0 : ADS_STATUS status;
3076 0 : int i;
3077 12 : int ret = -1;
3078 :
3079 12 : if (c->display_usage) {
3080 0 : d_printf("%s\n%s",
3081 : _("Usage:"),
3082 : _("net ads keytab delete <principal> [principal ...]\n"
3083 : " Remove entries for service principal, "
3084 : " from the keytab file only."
3085 : " Remove principals from local keytab\n"
3086 : " principal\tKerberos principal to remove from "
3087 : "keytab\n"));
3088 0 : TALLOC_FREE(tmp_ctx);
3089 0 : return -1;
3090 : }
3091 :
3092 12 : d_printf(_("Processing principals to delete...\n"));
3093 :
3094 12 : if (!c->opt_user_specified && c->opt_password == NULL) {
3095 0 : net_use_krb_machine_account(c);
3096 : }
3097 :
3098 12 : status = ads_startup(c, true, tmp_ctx, &ads);
3099 12 : if (!ADS_ERR_OK(status)) {
3100 0 : goto out;
3101 : }
3102 :
3103 24 : for (ret = 0, i = 0; i < argc; i++) {
3104 12 : ret |= ads_keytab_delete_entry(ads, argv[i]);
3105 : }
3106 12 : out:
3107 12 : TALLOC_FREE(tmp_ctx);
3108 12 : return ret;
3109 : }
3110 :
3111 8 : static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
3112 : {
3113 8 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3114 8 : ADS_STRUCT *ads = NULL;
3115 0 : ADS_STATUS status;
3116 8 : int ret = -1;
3117 :
3118 8 : if (c->display_usage) {
3119 0 : d_printf( "%s\n"
3120 : "net ads keytab create\n"
3121 : " %s\n",
3122 : _("Usage:"),
3123 : _("Create new default keytab"));
3124 0 : TALLOC_FREE(tmp_ctx);
3125 0 : return -1;
3126 : }
3127 :
3128 8 : net_warn_member_options();
3129 :
3130 8 : if (!c->opt_user_specified && c->opt_password == NULL) {
3131 6 : net_use_krb_machine_account(c);
3132 : }
3133 :
3134 8 : status = ads_startup(c, true, tmp_ctx, &ads);
3135 8 : if (!ADS_ERR_OK(status)) {
3136 0 : goto out;
3137 : }
3138 :
3139 8 : ret = ads_keytab_create_default(ads);
3140 8 : out:
3141 8 : TALLOC_FREE(tmp_ctx);
3142 8 : return ret;
3143 : }
3144 :
3145 42 : static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
3146 : {
3147 42 : const char *keytab = NULL;
3148 :
3149 42 : if (c->display_usage) {
3150 0 : d_printf("%s\n%s",
3151 : _("Usage:"),
3152 : _("net ads keytab list [keytab]\n"
3153 : " List a local keytab\n"
3154 : " keytab\tKeytab to list\n"));
3155 0 : return -1;
3156 : }
3157 :
3158 42 : if (argc >= 1) {
3159 2 : keytab = argv[0];
3160 : }
3161 :
3162 42 : return ads_keytab_list(keytab);
3163 : }
3164 :
3165 :
3166 78 : int net_ads_keytab(struct net_context *c, int argc, const char **argv)
3167 : {
3168 78 : struct functable func[] = {
3169 : {
3170 : "add",
3171 : net_ads_keytab_add_default,
3172 : NET_TRANSPORT_ADS,
3173 : N_("Add a service principal"),
3174 : N_("net ads keytab add\n"
3175 : " Add a service principal, updates keytab file only.")
3176 : },
3177 : {
3178 : "delete",
3179 : net_ads_keytab_delete,
3180 : NET_TRANSPORT_ADS,
3181 : N_("Delete a service principal"),
3182 : N_("net ads keytab delete\n"
3183 : " Remove entries for service principal, from the keytab file only.")
3184 : },
3185 : {
3186 : "add_update_ads",
3187 : net_ads_keytab_add_update_ads,
3188 : NET_TRANSPORT_ADS,
3189 : N_("Add a service principal"),
3190 : N_("net ads keytab add_update_ads\n"
3191 : " Add a service principal, depending on the param passed may update ADS computer object in addition to the keytab file.")
3192 : },
3193 : {
3194 : "create",
3195 : net_ads_keytab_create,
3196 : NET_TRANSPORT_ADS,
3197 : N_("Create a fresh keytab"),
3198 : N_("net ads keytab create\n"
3199 : " Create a fresh keytab or update existing one.")
3200 : },
3201 : {
3202 : "flush",
3203 : net_ads_keytab_flush,
3204 : NET_TRANSPORT_ADS,
3205 : N_("Remove all keytab entries"),
3206 : N_("net ads keytab flush\n"
3207 : " Remove all keytab entries")
3208 : },
3209 : {
3210 : "list",
3211 : net_ads_keytab_list,
3212 : NET_TRANSPORT_ADS,
3213 : N_("List a keytab"),
3214 : N_("net ads keytab list\n"
3215 : " List a keytab")
3216 : },
3217 : {NULL, NULL, 0, NULL, NULL}
3218 : };
3219 :
3220 78 : if (!USE_KERBEROS_KEYTAB) {
3221 2 : d_printf(_("\nWarning: \"kerberos method\" must be set to a "
3222 : "keytab method to use keytab functions.\n"));
3223 : }
3224 :
3225 78 : return net_run_function(c, argc, argv, "net ads keytab", func);
3226 : }
3227 :
3228 0 : static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
3229 : {
3230 0 : int ret = -1;
3231 :
3232 0 : if (c->display_usage) {
3233 0 : d_printf( "%s\n"
3234 : "net ads kerberos renew\n"
3235 : " %s\n",
3236 : _("Usage:"),
3237 : _("Renew TGT from existing credential cache"));
3238 0 : return -1;
3239 : }
3240 :
3241 0 : ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
3242 0 : if (ret) {
3243 0 : d_printf(_("failed to renew kerberos ticket: %s\n"),
3244 : error_message(ret));
3245 : }
3246 0 : return ret;
3247 : }
3248 :
3249 0 : static int net_ads_kerberos_pac_common(struct net_context *c, int argc, const char **argv,
3250 : struct PAC_DATA_CTR **pac_data_ctr)
3251 : {
3252 0 : NTSTATUS status;
3253 0 : int ret = -1;
3254 0 : const char *impersonate_princ_s = NULL;
3255 0 : const char *local_service = NULL;
3256 0 : int i;
3257 :
3258 0 : for (i=0; i<argc; i++) {
3259 0 : if (strnequal(argv[i], "impersonate", strlen("impersonate"))) {
3260 0 : impersonate_princ_s = get_string_param(argv[i]);
3261 0 : if (impersonate_princ_s == NULL) {
3262 0 : return -1;
3263 : }
3264 : }
3265 0 : if (strnequal(argv[i], "local_service", strlen("local_service"))) {
3266 0 : local_service = get_string_param(argv[i]);
3267 0 : if (local_service == NULL) {
3268 0 : return -1;
3269 : }
3270 : }
3271 : }
3272 :
3273 0 : if (local_service == NULL) {
3274 0 : local_service = talloc_asprintf(c, "%s$@%s",
3275 : lp_netbios_name(), lp_realm());
3276 0 : if (local_service == NULL) {
3277 0 : goto out;
3278 : }
3279 : }
3280 :
3281 0 : c->opt_password = net_prompt_pass(c, c->opt_user_name);
3282 :
3283 0 : status = kerberos_return_pac(c,
3284 : c->opt_user_name,
3285 : c->opt_password,
3286 : 0,
3287 : NULL,
3288 : NULL,
3289 : NULL,
3290 : true,
3291 : true,
3292 : 2592000, /* one month */
3293 : impersonate_princ_s,
3294 : local_service,
3295 : NULL,
3296 : NULL,
3297 : pac_data_ctr);
3298 0 : if (!NT_STATUS_IS_OK(status)) {
3299 0 : d_printf(_("failed to query kerberos PAC: %s\n"),
3300 : nt_errstr(status));
3301 0 : goto out;
3302 : }
3303 :
3304 0 : ret = 0;
3305 0 : out:
3306 0 : return ret;
3307 : }
3308 :
3309 0 : static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv)
3310 : {
3311 0 : struct PAC_DATA_CTR *pac_data_ctr = NULL;
3312 0 : int i, num_buffers;
3313 0 : int ret = -1;
3314 0 : enum PAC_TYPE type = 0;
3315 :
3316 0 : if (c->display_usage) {
3317 0 : d_printf( "%s\n"
3318 : "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
3319 : " %s\n",
3320 : _("Usage:"),
3321 : _("Dump the Kerberos PAC"));
3322 0 : return -1;
3323 : }
3324 :
3325 0 : for (i=0; i<argc; i++) {
3326 0 : if (strnequal(argv[i], "pac_buffer_type", strlen("pac_buffer_type"))) {
3327 0 : type = get_int_param(argv[i]);
3328 : }
3329 : }
3330 :
3331 0 : ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3332 0 : if (ret) {
3333 0 : return ret;
3334 : }
3335 :
3336 0 : if (type == 0) {
3337 :
3338 0 : char *s = NULL;
3339 :
3340 0 : s = NDR_PRINT_STRUCT_STRING(c, PAC_DATA,
3341 : pac_data_ctr->pac_data);
3342 0 : if (s != NULL) {
3343 0 : d_printf(_("The Pac: %s\n"), s);
3344 0 : talloc_free(s);
3345 : }
3346 :
3347 0 : return 0;
3348 : }
3349 :
3350 0 : num_buffers = pac_data_ctr->pac_data->num_buffers;
3351 :
3352 0 : for (i=0; i<num_buffers; i++) {
3353 :
3354 0 : char *s = NULL;
3355 :
3356 0 : if (pac_data_ctr->pac_data->buffers[i].type != type) {
3357 0 : continue;
3358 : }
3359 :
3360 0 : s = NDR_PRINT_UNION_STRING(c, PAC_INFO, type,
3361 : pac_data_ctr->pac_data->buffers[i].info);
3362 0 : if (s != NULL) {
3363 0 : d_printf(_("The Pac: %s\n"), s);
3364 0 : talloc_free(s);
3365 : }
3366 0 : break;
3367 : }
3368 :
3369 0 : return 0;
3370 : }
3371 :
3372 0 : static int net_ads_kerberos_pac_save(struct net_context *c, int argc, const char **argv)
3373 : {
3374 0 : struct PAC_DATA_CTR *pac_data_ctr = NULL;
3375 0 : char *filename = NULL;
3376 0 : int ret = -1;
3377 0 : int i;
3378 :
3379 0 : if (c->display_usage) {
3380 0 : d_printf( "%s\n"
3381 : "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
3382 : " %s\n",
3383 : _("Usage:"),
3384 : _("Save the Kerberos PAC"));
3385 0 : return -1;
3386 : }
3387 :
3388 0 : for (i=0; i<argc; i++) {
3389 0 : if (strnequal(argv[i], "filename", strlen("filename"))) {
3390 0 : filename = get_string_param(argv[i]);
3391 0 : if (filename == NULL) {
3392 0 : return -1;
3393 : }
3394 : }
3395 : }
3396 :
3397 0 : ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3398 0 : if (ret) {
3399 0 : return ret;
3400 : }
3401 :
3402 0 : if (filename == NULL) {
3403 0 : d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
3404 0 : return -1;
3405 : }
3406 :
3407 : /* save the raw format */
3408 0 : if (!file_save(filename, pac_data_ctr->pac_blob.data, pac_data_ctr->pac_blob.length)) {
3409 0 : d_printf(_("failed to save PAC in %s\n"), filename);
3410 0 : return -1;
3411 : }
3412 :
3413 0 : return 0;
3414 : }
3415 :
3416 0 : static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
3417 : {
3418 0 : struct functable func[] = {
3419 : {
3420 : "dump",
3421 : net_ads_kerberos_pac_dump,
3422 : NET_TRANSPORT_ADS,
3423 : N_("Dump Kerberos PAC"),
3424 : N_("net ads kerberos pac dump\n"
3425 : " Dump a Kerberos PAC to stdout")
3426 : },
3427 : {
3428 : "save",
3429 : net_ads_kerberos_pac_save,
3430 : NET_TRANSPORT_ADS,
3431 : N_("Save Kerberos PAC"),
3432 : N_("net ads kerberos pac save\n"
3433 : " Save a Kerberos PAC in a file")
3434 : },
3435 :
3436 : {NULL, NULL, 0, NULL, NULL}
3437 : };
3438 :
3439 0 : return net_run_function(c, argc, argv, "net ads kerberos pac", func);
3440 : }
3441 :
3442 0 : static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
3443 : {
3444 0 : int ret = -1;
3445 0 : NTSTATUS status;
3446 :
3447 0 : if (c->display_usage) {
3448 0 : d_printf( "%s\n"
3449 : "net ads kerberos kinit\n"
3450 : " %s\n",
3451 : _("Usage:"),
3452 : _("Get Ticket Granting Ticket (TGT) for the user"));
3453 0 : return -1;
3454 : }
3455 :
3456 0 : c->opt_password = net_prompt_pass(c, c->opt_user_name);
3457 :
3458 0 : ret = kerberos_kinit_password_ext(c->opt_user_name,
3459 : c->opt_password,
3460 : 0,
3461 : NULL,
3462 : NULL,
3463 : NULL,
3464 : true,
3465 : true,
3466 : 2592000, /* one month */
3467 : NULL,
3468 : NULL,
3469 : NULL,
3470 : &status);
3471 0 : if (ret) {
3472 0 : d_printf(_("failed to kinit password: %s\n"),
3473 : nt_errstr(status));
3474 : }
3475 0 : return ret;
3476 : }
3477 :
3478 0 : int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3479 : {
3480 0 : struct functable func[] = {
3481 : {
3482 : "kinit",
3483 : net_ads_kerberos_kinit,
3484 : NET_TRANSPORT_ADS,
3485 : N_("Retrieve Ticket Granting Ticket (TGT)"),
3486 : N_("net ads kerberos kinit\n"
3487 : " Receive Ticket Granting Ticket (TGT)")
3488 : },
3489 : {
3490 : "renew",
3491 : net_ads_kerberos_renew,
3492 : NET_TRANSPORT_ADS,
3493 : N_("Renew Ticket Granting Ticket from credential cache"),
3494 : N_("net ads kerberos renew\n"
3495 : " Renew Ticket Granting Ticket (TGT) from "
3496 : "credential cache")
3497 : },
3498 : {
3499 : "pac",
3500 : net_ads_kerberos_pac,
3501 : NET_TRANSPORT_ADS,
3502 : N_("Dump Kerberos PAC"),
3503 : N_("net ads kerberos pac\n"
3504 : " Dump Kerberos PAC")
3505 : },
3506 : {NULL, NULL, 0, NULL, NULL}
3507 : };
3508 :
3509 0 : return net_run_function(c, argc, argv, "net ads kerberos", func);
3510 : }
3511 :
3512 16 : static int net_ads_setspn_list(struct net_context *c,
3513 : int argc,
3514 : const char **argv)
3515 : {
3516 16 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3517 16 : ADS_STRUCT *ads = NULL;
3518 0 : ADS_STATUS status;
3519 16 : bool ok = false;
3520 16 : int ret = -1;
3521 :
3522 16 : if (c->display_usage) {
3523 0 : d_printf("%s\n%s",
3524 : _("Usage:"),
3525 : _("net ads setspn list <machinename>\n"));
3526 0 : TALLOC_FREE(tmp_ctx);
3527 0 : return -1;
3528 : }
3529 :
3530 16 : status = ads_startup(c, true, tmp_ctx, &ads);
3531 16 : if (!ADS_ERR_OK(status)) {
3532 0 : goto out;
3533 : }
3534 :
3535 16 : if (argc) {
3536 2 : ok = ads_setspn_list(ads, argv[0]);
3537 : } else {
3538 14 : ok = ads_setspn_list(ads, lp_netbios_name());
3539 : }
3540 :
3541 16 : ret = ok ? 0 : -1;
3542 16 : out:
3543 16 : TALLOC_FREE(tmp_ctx);
3544 16 : return ret;
3545 : }
3546 :
3547 6 : static int net_ads_setspn_add(struct net_context *c, int argc, const char **argv)
3548 : {
3549 6 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3550 6 : ADS_STRUCT *ads = NULL;
3551 0 : ADS_STATUS status;
3552 6 : bool ok = false;
3553 6 : int ret = -1;
3554 :
3555 6 : if (c->display_usage || argc < 1) {
3556 0 : d_printf("%s\n%s",
3557 : _("Usage:"),
3558 : _("net ads setspn add <machinename> SPN\n"));
3559 0 : TALLOC_FREE(tmp_ctx);
3560 0 : return -1;
3561 : }
3562 :
3563 6 : status = ads_startup(c, true, tmp_ctx, &ads);
3564 6 : if (!ADS_ERR_OK(status)) {
3565 0 : goto out;
3566 : }
3567 :
3568 6 : if (argc > 1) {
3569 0 : ok = ads_setspn_add(ads, argv[0], argv[1]);
3570 : } else {
3571 6 : ok = ads_setspn_add(ads, lp_netbios_name(), argv[0]);
3572 : }
3573 :
3574 6 : ret = ok ? 0 : -1;
3575 6 : out:
3576 6 : TALLOC_FREE(tmp_ctx);
3577 6 : return ret;
3578 : }
3579 :
3580 2 : static int net_ads_setspn_delete(struct net_context *c, int argc, const char **argv)
3581 : {
3582 2 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3583 2 : ADS_STRUCT *ads = NULL;
3584 0 : ADS_STATUS status;
3585 2 : bool ok = false;
3586 2 : int ret = -1;
3587 :
3588 2 : if (c->display_usage || argc < 1) {
3589 0 : d_printf("%s\n%s",
3590 : _("Usage:"),
3591 : _("net ads setspn delete <machinename> SPN\n"));
3592 0 : TALLOC_FREE(tmp_ctx);
3593 0 : return -1;
3594 : }
3595 :
3596 2 : status = ads_startup(c, true, tmp_ctx, &ads);
3597 2 : if (!ADS_ERR_OK(status)) {
3598 0 : goto out;
3599 : }
3600 :
3601 2 : if (argc > 1) {
3602 0 : ok = ads_setspn_delete(ads, argv[0], argv[1]);
3603 : } else {
3604 2 : ok = ads_setspn_delete(ads, lp_netbios_name(), argv[0]);
3605 : }
3606 :
3607 2 : ret = ok ? 0 : -1;
3608 2 : out:
3609 2 : TALLOC_FREE(tmp_ctx);
3610 2 : return ret;
3611 : }
3612 :
3613 24 : int net_ads_setspn(struct net_context *c, int argc, const char **argv)
3614 : {
3615 24 : struct functable func[] = {
3616 : {
3617 : "list",
3618 : net_ads_setspn_list,
3619 : NET_TRANSPORT_ADS,
3620 : N_("List Service Principal Names (SPN)"),
3621 : N_("net ads setspn list machine\n"
3622 : " List Service Principal Names (SPN)")
3623 : },
3624 : {
3625 : "add",
3626 : net_ads_setspn_add,
3627 : NET_TRANSPORT_ADS,
3628 : N_("Add Service Principal Names (SPN)"),
3629 : N_("net ads setspn add machine spn\n"
3630 : " Add Service Principal Names (SPN)")
3631 : },
3632 : {
3633 : "delete",
3634 : net_ads_setspn_delete,
3635 : NET_TRANSPORT_ADS,
3636 : N_("Delete Service Principal Names (SPN)"),
3637 : N_("net ads setspn delete machine spn\n"
3638 : " Delete Service Principal Names (SPN)")
3639 : },
3640 : {NULL, NULL, 0, NULL, NULL}
3641 : };
3642 :
3643 24 : return net_run_function(c, argc, argv, "net ads setspn", func);
3644 : }
3645 :
3646 0 : static int net_ads_enctype_lookup_account(struct net_context *c,
3647 : ADS_STRUCT *ads,
3648 : const char *account,
3649 : LDAPMessage **res,
3650 : const char **enctype_str)
3651 : {
3652 0 : const char *filter;
3653 0 : const char *attrs[] = {
3654 : "msDS-SupportedEncryptionTypes",
3655 : NULL
3656 : };
3657 0 : int count;
3658 0 : int ret = -1;
3659 0 : ADS_STATUS status;
3660 :
3661 0 : filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))",
3662 : account);
3663 0 : if (filter == NULL) {
3664 0 : goto done;
3665 : }
3666 :
3667 0 : status = ads_search(ads, res, filter, attrs);
3668 0 : if (!ADS_ERR_OK(status)) {
3669 0 : d_printf(_("no account found with filter: %s\n"), filter);
3670 0 : goto done;
3671 : }
3672 :
3673 0 : count = ads_count_replies(ads, *res);
3674 0 : switch (count) {
3675 0 : case 1:
3676 0 : break;
3677 0 : case 0:
3678 0 : d_printf(_("no account found with filter: %s\n"), filter);
3679 0 : goto done;
3680 0 : default:
3681 0 : d_printf(_("multiple accounts found with filter: %s\n"), filter);
3682 0 : goto done;
3683 : }
3684 :
3685 0 : if (enctype_str) {
3686 0 : *enctype_str = ads_pull_string(ads, c, *res,
3687 : "msDS-SupportedEncryptionTypes");
3688 0 : if (*enctype_str == NULL) {
3689 0 : d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
3690 0 : goto done;
3691 : }
3692 : }
3693 :
3694 0 : ret = 0;
3695 0 : done:
3696 0 : return ret;
3697 : }
3698 :
3699 0 : static void net_ads_enctype_dump_enctypes(const char *username,
3700 : const char *enctype_str)
3701 : {
3702 0 : int enctypes = atoi(enctype_str);
3703 :
3704 0 : d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
3705 : username, enctypes, enctypes);
3706 :
3707 0 : printf("[%s] 0x%08x DES-CBC-CRC\n",
3708 0 : enctypes & ENC_CRC32 ? "X" : " ",
3709 : ENC_CRC32);
3710 0 : printf("[%s] 0x%08x DES-CBC-MD5\n",
3711 0 : enctypes & ENC_RSA_MD5 ? "X" : " ",
3712 : ENC_RSA_MD5);
3713 0 : printf("[%s] 0x%08x RC4-HMAC\n",
3714 0 : enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ",
3715 : ENC_RC4_HMAC_MD5);
3716 0 : printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
3717 0 : enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ",
3718 : ENC_HMAC_SHA1_96_AES128);
3719 0 : printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
3720 0 : enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
3721 : ENC_HMAC_SHA1_96_AES256);
3722 0 : printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96-SK\n",
3723 0 : enctypes & ENC_HMAC_SHA1_96_AES256_SK ? "X" : " ",
3724 : ENC_HMAC_SHA1_96_AES256_SK);
3725 0 : printf("[%s] 0x%08x RESOURCE-SID-COMPRESSION-DISABLED\n",
3726 0 : enctypes & KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED ? "X" : " ",
3727 : KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED);
3728 0 : }
3729 :
3730 0 : static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
3731 : {
3732 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3733 0 : ADS_STATUS status;
3734 0 : ADS_STRUCT *ads = NULL;
3735 0 : LDAPMessage *res = NULL;
3736 0 : const char *str = NULL;
3737 0 : int ret = -1;
3738 :
3739 0 : if (c->display_usage || (argc < 1)) {
3740 0 : d_printf( "%s\n"
3741 : "net ads enctypes list\n"
3742 : " %s\n",
3743 : _("Usage:"),
3744 : _("List supported enctypes"));
3745 0 : TALLOC_FREE(tmp_ctx);
3746 0 : return -1;
3747 : }
3748 :
3749 0 : status = ads_startup(c, false, tmp_ctx, &ads);
3750 0 : if (!ADS_ERR_OK(status)) {
3751 0 : goto out;
3752 : }
3753 :
3754 0 : ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3755 0 : if (ret) {
3756 0 : goto out;
3757 : }
3758 :
3759 0 : net_ads_enctype_dump_enctypes(argv[0], str);
3760 :
3761 0 : ret = 0;
3762 0 : out:
3763 0 : ads_msgfree(ads, res);
3764 0 : TALLOC_FREE(tmp_ctx);
3765 0 : return ret;
3766 : }
3767 :
3768 0 : static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
3769 : {
3770 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3771 0 : int ret = -1;
3772 0 : ADS_STATUS status;
3773 0 : ADS_STRUCT *ads = NULL;
3774 0 : LDAPMessage *res = NULL;
3775 0 : const char *etype_list_str = NULL;
3776 0 : const char *dn = NULL;
3777 0 : ADS_MODLIST mods = NULL;
3778 0 : uint32_t etype_list;
3779 0 : const char *str = NULL;
3780 :
3781 0 : if (c->display_usage || argc < 1) {
3782 0 : d_printf( "%s\n"
3783 : "net ads enctypes set <sAMAccountName> [enctypes]\n"
3784 : " %s\n",
3785 : _("Usage:"),
3786 : _("Set supported enctypes"));
3787 0 : TALLOC_FREE(tmp_ctx);
3788 0 : return -1;
3789 : }
3790 :
3791 0 : status = ads_startup(c, false, tmp_ctx, &ads);
3792 0 : if (!ADS_ERR_OK(status)) {
3793 0 : goto done;
3794 : }
3795 :
3796 0 : ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3797 0 : if (ret) {
3798 0 : goto done;
3799 : }
3800 :
3801 0 : dn = ads_get_dn(ads, tmp_ctx, res);
3802 0 : if (dn == NULL) {
3803 0 : goto done;
3804 : }
3805 :
3806 0 : etype_list = 0;
3807 0 : etype_list |= ENC_RC4_HMAC_MD5;
3808 0 : etype_list |= ENC_HMAC_SHA1_96_AES128;
3809 0 : etype_list |= ENC_HMAC_SHA1_96_AES256;
3810 :
3811 0 : if (argv[1] != NULL) {
3812 0 : sscanf(argv[1], "%i", &etype_list);
3813 : }
3814 :
3815 0 : etype_list_str = talloc_asprintf(tmp_ctx, "%d", etype_list);
3816 0 : if (!etype_list_str) {
3817 0 : goto done;
3818 : }
3819 :
3820 0 : mods = ads_init_mods(tmp_ctx);
3821 0 : if (!mods) {
3822 0 : goto done;
3823 : }
3824 :
3825 0 : status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes",
3826 : etype_list_str);
3827 0 : if (!ADS_ERR_OK(status)) {
3828 0 : goto done;
3829 : }
3830 :
3831 0 : status = ads_gen_mod(ads, dn, mods);
3832 0 : if (!ADS_ERR_OK(status)) {
3833 0 : d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3834 : ads_errstr(status));
3835 0 : goto done;
3836 : }
3837 :
3838 0 : ads_msgfree(ads, res);
3839 0 : res = NULL;
3840 :
3841 0 : ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3842 0 : if (ret) {
3843 0 : goto done;
3844 : }
3845 :
3846 0 : net_ads_enctype_dump_enctypes(argv[0], str);
3847 :
3848 0 : ret = 0;
3849 0 : done:
3850 0 : ads_msgfree(ads, res);
3851 0 : TALLOC_FREE(tmp_ctx);
3852 0 : return ret;
3853 : }
3854 :
3855 0 : static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
3856 : {
3857 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3858 0 : int ret = -1;
3859 0 : ADS_STATUS status;
3860 0 : ADS_STRUCT *ads = NULL;
3861 0 : LDAPMessage *res = NULL;
3862 0 : const char *dn = NULL;
3863 0 : ADS_MODLIST mods = NULL;
3864 :
3865 0 : if (c->display_usage || argc < 1) {
3866 0 : d_printf( "%s\n"
3867 : "net ads enctypes delete <sAMAccountName>\n"
3868 : " %s\n",
3869 : _("Usage:"),
3870 : _("Delete supported enctypes"));
3871 0 : TALLOC_FREE(tmp_ctx);
3872 0 : return -1;
3873 : }
3874 :
3875 0 : status = ads_startup(c, false, tmp_ctx, &ads);
3876 0 : if (!ADS_ERR_OK(status)) {
3877 0 : goto done;
3878 : }
3879 :
3880 0 : ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3881 0 : if (ret) {
3882 0 : goto done;
3883 : }
3884 :
3885 0 : dn = ads_get_dn(ads, tmp_ctx, res);
3886 0 : if (dn == NULL) {
3887 0 : goto done;
3888 : }
3889 :
3890 0 : mods = ads_init_mods(tmp_ctx);
3891 0 : if (!mods) {
3892 0 : goto done;
3893 : }
3894 :
3895 0 : status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes", NULL);
3896 0 : if (!ADS_ERR_OK(status)) {
3897 0 : goto done;
3898 : }
3899 :
3900 0 : status = ads_gen_mod(ads, dn, mods);
3901 0 : if (!ADS_ERR_OK(status)) {
3902 0 : d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3903 : ads_errstr(status));
3904 0 : goto done;
3905 : }
3906 :
3907 0 : ret = 0;
3908 :
3909 0 : done:
3910 0 : ads_msgfree(ads, res);
3911 0 : TALLOC_FREE(tmp_ctx);
3912 0 : return ret;
3913 : }
3914 :
3915 0 : static int net_ads_enctypes(struct net_context *c, int argc, const char **argv)
3916 : {
3917 0 : struct functable func[] = {
3918 : {
3919 : "list",
3920 : net_ads_enctypes_list,
3921 : NET_TRANSPORT_ADS,
3922 : N_("List the supported encryption types"),
3923 : N_("net ads enctypes list\n"
3924 : " List the supported encryption types")
3925 : },
3926 : {
3927 : "set",
3928 : net_ads_enctypes_set,
3929 : NET_TRANSPORT_ADS,
3930 : N_("Set the supported encryption types"),
3931 : N_("net ads enctypes set\n"
3932 : " Set the supported encryption types")
3933 : },
3934 : {
3935 : "delete",
3936 : net_ads_enctypes_delete,
3937 : NET_TRANSPORT_ADS,
3938 : N_("Delete the supported encryption types"),
3939 : N_("net ads enctypes delete\n"
3940 : " Delete the supported encryption types")
3941 : },
3942 :
3943 : {NULL, NULL, 0, NULL, NULL}
3944 : };
3945 :
3946 0 : return net_run_function(c, argc, argv, "net ads enctypes", func);
3947 : }
3948 :
3949 :
3950 288 : int net_ads(struct net_context *c, int argc, const char **argv)
3951 : {
3952 288 : struct functable func[] = {
3953 : {
3954 : "info",
3955 : net_ads_info,
3956 : NET_TRANSPORT_ADS,
3957 : N_("Display details on remote ADS server"),
3958 : N_("net ads info\n"
3959 : " Display details on remote ADS server")
3960 : },
3961 : {
3962 : "join",
3963 : net_ads_join,
3964 : NET_TRANSPORT_ADS,
3965 : N_("Join the local machine to ADS realm"),
3966 : N_("net ads join\n"
3967 : " Join the local machine to ADS realm")
3968 : },
3969 : {
3970 : "testjoin",
3971 : net_ads_testjoin,
3972 : NET_TRANSPORT_ADS,
3973 : N_("Validate machine account"),
3974 : N_("net ads testjoin\n"
3975 : " Validate machine account")
3976 : },
3977 : {
3978 : "leave",
3979 : net_ads_leave,
3980 : NET_TRANSPORT_ADS,
3981 : N_("Remove the local machine from ADS"),
3982 : N_("net ads leave\n"
3983 : " Remove the local machine from ADS")
3984 : },
3985 : {
3986 : "status",
3987 : net_ads_status,
3988 : NET_TRANSPORT_ADS,
3989 : N_("Display machine account details"),
3990 : N_("net ads status\n"
3991 : " Display machine account details")
3992 : },
3993 : {
3994 : "user",
3995 : net_ads_user,
3996 : NET_TRANSPORT_ADS,
3997 : N_("List/modify users"),
3998 : N_("net ads user\n"
3999 : " List/modify users")
4000 : },
4001 : {
4002 : "group",
4003 : net_ads_group,
4004 : NET_TRANSPORT_ADS,
4005 : N_("List/modify groups"),
4006 : N_("net ads group\n"
4007 : " List/modify groups")
4008 : },
4009 : {
4010 : "dns",
4011 : net_ads_dns,
4012 : NET_TRANSPORT_ADS,
4013 : N_("Issue dynamic DNS update"),
4014 : N_("net ads dns\n"
4015 : " Issue dynamic DNS update")
4016 : },
4017 : {
4018 : "password",
4019 : net_ads_password,
4020 : NET_TRANSPORT_ADS,
4021 : N_("Change user passwords"),
4022 : N_("net ads password\n"
4023 : " Change user passwords")
4024 : },
4025 : {
4026 : "changetrustpw",
4027 : net_ads_changetrustpw,
4028 : NET_TRANSPORT_ADS,
4029 : N_("Change trust account password"),
4030 : N_("net ads changetrustpw\n"
4031 : " Change trust account password")
4032 : },
4033 : {
4034 : "printer",
4035 : net_ads_printer,
4036 : NET_TRANSPORT_ADS,
4037 : N_("List/modify printer entries"),
4038 : N_("net ads printer\n"
4039 : " List/modify printer entries")
4040 : },
4041 : {
4042 : "search",
4043 : net_ads_search,
4044 : NET_TRANSPORT_ADS,
4045 : N_("Issue LDAP search using filter"),
4046 : N_("net ads search\n"
4047 : " Issue LDAP search using filter")
4048 : },
4049 : {
4050 : "dn",
4051 : net_ads_dn,
4052 : NET_TRANSPORT_ADS,
4053 : N_("Issue LDAP search by DN"),
4054 : N_("net ads dn\n"
4055 : " Issue LDAP search by DN")
4056 : },
4057 : {
4058 : "sid",
4059 : net_ads_sid,
4060 : NET_TRANSPORT_ADS,
4061 : N_("Issue LDAP search by SID"),
4062 : N_("net ads sid\n"
4063 : " Issue LDAP search by SID")
4064 : },
4065 : {
4066 : "workgroup",
4067 : net_ads_workgroup,
4068 : NET_TRANSPORT_ADS,
4069 : N_("Display workgroup name"),
4070 : N_("net ads workgroup\n"
4071 : " Display the workgroup name")
4072 : },
4073 : {
4074 : "lookup",
4075 : net_ads_lookup,
4076 : NET_TRANSPORT_ADS,
4077 : N_("Perform CLDAP query on DC"),
4078 : N_("net ads lookup\n"
4079 : " Find the ADS DC using CLDAP lookups")
4080 : },
4081 : {
4082 : "keytab",
4083 : net_ads_keytab,
4084 : NET_TRANSPORT_ADS,
4085 : N_("Manage local keytab file"),
4086 : N_("net ads keytab\n"
4087 : " Manage local keytab file")
4088 : },
4089 : {
4090 : "setspn",
4091 : net_ads_setspn,
4092 : NET_TRANSPORT_ADS,
4093 : N_("Manage Service Principal Names (SPN)s"),
4094 : N_("net ads spnset\n"
4095 : " Manage Service Principal Names (SPN)s")
4096 : },
4097 : {
4098 : "gpo",
4099 : net_ads_gpo,
4100 : NET_TRANSPORT_ADS,
4101 : N_("Manage group policy objects"),
4102 : N_("net ads gpo\n"
4103 : " Manage group policy objects")
4104 : },
4105 : {
4106 : "kerberos",
4107 : net_ads_kerberos,
4108 : NET_TRANSPORT_ADS,
4109 : N_("Manage kerberos keytab"),
4110 : N_("net ads kerberos\n"
4111 : " Manage kerberos keytab")
4112 : },
4113 : {
4114 : "enctypes",
4115 : net_ads_enctypes,
4116 : NET_TRANSPORT_ADS,
4117 : N_("List/modify supported encryption types"),
4118 : N_("net ads enctypes\n"
4119 : " List/modify enctypes")
4120 : },
4121 : {NULL, NULL, 0, NULL, NULL}
4122 : };
4123 :
4124 288 : return net_run_function(c, argc, argv, "net ads", func);
4125 : }
4126 :
4127 : #else
4128 :
4129 0 : static int net_ads_noads(void)
4130 : {
4131 0 : d_fprintf(stderr, _("ADS support not compiled in\n"));
4132 0 : return -1;
4133 : }
4134 :
4135 0 : int net_ads_keytab(struct net_context *c, int argc, const char **argv)
4136 : {
4137 0 : return net_ads_noads();
4138 : }
4139 :
4140 0 : int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
4141 : {
4142 0 : return net_ads_noads();
4143 : }
4144 :
4145 0 : int net_ads_setspn(struct net_context *c, int argc, const char **argv)
4146 : {
4147 0 : return net_ads_noads();
4148 : }
4149 :
4150 0 : int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
4151 : {
4152 0 : return net_ads_noads();
4153 : }
4154 :
4155 0 : int net_ads_join(struct net_context *c, int argc, const char **argv)
4156 : {
4157 0 : return net_ads_noads();
4158 : }
4159 :
4160 0 : int net_ads_user(struct net_context *c, int argc, const char **argv)
4161 : {
4162 0 : return net_ads_noads();
4163 : }
4164 :
4165 0 : int net_ads_group(struct net_context *c, int argc, const char **argv)
4166 : {
4167 0 : return net_ads_noads();
4168 : }
4169 :
4170 0 : int net_ads_gpo(struct net_context *c, int argc, const char **argv)
4171 : {
4172 0 : return net_ads_noads();
4173 : }
4174 :
4175 : /* this one shouldn't display a message */
4176 0 : int net_ads_check(struct net_context *c)
4177 : {
4178 0 : return -1;
4179 : }
4180 :
4181 0 : int net_ads_check_our_domain(struct net_context *c)
4182 : {
4183 0 : return -1;
4184 : }
4185 :
4186 0 : int net_ads(struct net_context *c, int argc, const char **argv)
4187 : {
4188 0 : return net_ads_noads();
4189 : }
4190 :
4191 : #endif /* HAVE_ADS */
|