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