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 : TALLOC_FREE(escaped_user);
1144 0 : TALLOC_FREE(searchstring);
1145 0 : ads_msgfree(ads, res);
1146 0 : TALLOC_FREE(tmp_ctx);
1147 0 : return ret;
1148 : }
1149 :
1150 4 : static int ads_user_delete(struct net_context *c, int argc, const char **argv)
1151 : {
1152 4 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1153 4 : ADS_STRUCT *ads = NULL;
1154 0 : ADS_STATUS status;
1155 4 : LDAPMessage *res = NULL;
1156 4 : char *userdn = NULL;
1157 4 : int ret = -1;
1158 :
1159 4 : if (argc < 1) {
1160 0 : TALLOC_FREE(tmp_ctx);
1161 0 : return net_ads_user_usage(c, argc, argv);
1162 : }
1163 :
1164 4 : status = ads_startup(c, false, tmp_ctx, &ads);
1165 4 : if (!ADS_ERR_OK(status)) {
1166 0 : goto out;
1167 : }
1168 :
1169 4 : status = ads_find_user_acct(ads, &res, argv[0]);
1170 4 : if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1171 0 : d_printf(_("User %s does not exist.\n"), argv[0]);
1172 0 : goto out;
1173 : }
1174 :
1175 4 : userdn = ads_get_dn(ads, tmp_ctx, res);
1176 4 : if (userdn == NULL) {
1177 0 : goto out;
1178 : }
1179 :
1180 4 : status = ads_del_dn(ads, userdn);
1181 4 : if (!ADS_ERR_OK(status)) {
1182 0 : d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
1183 : ads_errstr(status));
1184 0 : goto out;
1185 : }
1186 :
1187 4 : d_printf(_("User %s deleted\n"), argv[0]);
1188 :
1189 4 : ret = 0;
1190 4 : out:
1191 4 : ads_msgfree(ads, res);
1192 4 : TALLOC_FREE(tmp_ctx);
1193 4 : return ret;
1194 : }
1195 :
1196 8 : int net_ads_user(struct net_context *c, int argc, const char **argv)
1197 : {
1198 8 : struct functable func[] = {
1199 : {
1200 : "add",
1201 : ads_user_add,
1202 : NET_TRANSPORT_ADS,
1203 : N_("Add an AD user"),
1204 : N_("net ads user add\n"
1205 : " Add an AD user")
1206 : },
1207 : {
1208 : "info",
1209 : ads_user_info,
1210 : NET_TRANSPORT_ADS,
1211 : N_("Display information about an AD user"),
1212 : N_("net ads user info\n"
1213 : " Display information about an AD user")
1214 : },
1215 : {
1216 : "delete",
1217 : ads_user_delete,
1218 : NET_TRANSPORT_ADS,
1219 : N_("Delete an AD user"),
1220 : N_("net ads user delete\n"
1221 : " Delete an AD user")
1222 : },
1223 : {NULL, NULL, 0, NULL, NULL}
1224 : };
1225 8 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1226 8 : ADS_STRUCT *ads = NULL;
1227 0 : ADS_STATUS status;
1228 8 : const char *shortattrs[] = {"sAMAccountName", NULL};
1229 8 : const char *longattrs[] = {"sAMAccountName", "description", NULL};
1230 8 : char *disp_fields[2] = {NULL, NULL};
1231 8 : int ret = -1;
1232 :
1233 8 : if (argc > 0) {
1234 8 : TALLOC_FREE(tmp_ctx);
1235 8 : return net_run_function(c, argc, argv, "net ads user", func);
1236 : }
1237 :
1238 0 : if (c->display_usage) {
1239 0 : d_printf( "%s\n"
1240 : "net ads user\n"
1241 : " %s\n",
1242 : _("Usage:"),
1243 : _("List AD users"));
1244 0 : net_display_usage_from_functable(func);
1245 0 : TALLOC_FREE(tmp_ctx);
1246 0 : return -1;
1247 : }
1248 :
1249 0 : status = ads_startup(c, false, tmp_ctx, &ads);
1250 0 : if (!ADS_ERR_OK(status)) {
1251 0 : goto out;
1252 : }
1253 :
1254 0 : if (c->opt_long_list_entries)
1255 0 : d_printf(_("\nUser name Comment"
1256 : "\n-----------------------------\n"));
1257 :
1258 0 : status = ads_do_search_all_fn(ads,
1259 0 : ads->config.bind_path,
1260 : LDAP_SCOPE_SUBTREE,
1261 : "(objectCategory=user)",
1262 0 : c->opt_long_list_entries ?
1263 : longattrs : shortattrs,
1264 : usergrp_display,
1265 : disp_fields);
1266 0 : if (!ADS_ERR_OK(status)) {
1267 0 : goto out;
1268 : }
1269 :
1270 0 : ret = 0;
1271 0 : out:
1272 0 : TALLOC_FREE(tmp_ctx);
1273 0 : return ret;
1274 : }
1275 :
1276 0 : static int net_ads_group_usage(struct net_context *c, int argc, const char **argv)
1277 : {
1278 0 : return net_group_usage(c, argc, argv);
1279 : }
1280 :
1281 0 : static int ads_group_add(struct net_context *c, int argc, const char **argv)
1282 : {
1283 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1284 0 : ADS_STRUCT *ads = NULL;
1285 0 : ADS_STATUS status;
1286 0 : LDAPMessage *res = NULL;
1287 0 : int ret = -1;
1288 0 : char *ou_str = NULL;
1289 :
1290 0 : if (argc < 1 || c->display_usage) {
1291 0 : TALLOC_FREE(tmp_ctx);
1292 0 : return net_ads_group_usage(c, argc, argv);
1293 : }
1294 :
1295 0 : status = ads_startup(c, false, tmp_ctx, &ads);
1296 0 : if (!ADS_ERR_OK(status)) {
1297 0 : goto out;
1298 : }
1299 :
1300 0 : status = ads_find_user_acct(ads, &res, argv[0]);
1301 0 : if (!ADS_ERR_OK(status)) {
1302 0 : d_fprintf(stderr, _("ads_group_add: %s\n"), ads_errstr(status));
1303 0 : goto out;
1304 : }
1305 :
1306 0 : if (ads_count_replies(ads, res)) {
1307 0 : d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]);
1308 0 : goto out;
1309 : }
1310 :
1311 0 : if (c->opt_container) {
1312 0 : ou_str = SMB_STRDUP(c->opt_container);
1313 : } else {
1314 0 : ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
1315 : }
1316 :
1317 0 : status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
1318 0 : if (!ADS_ERR_OK(status)) {
1319 0 : d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0],
1320 : ads_errstr(status));
1321 0 : goto out;
1322 : }
1323 :
1324 0 : d_printf(_("Group %s added\n"), argv[0]);
1325 :
1326 0 : ret = 0;
1327 0 : out:
1328 0 : ads_msgfree(ads, res);
1329 0 : SAFE_FREE(ou_str);
1330 0 : TALLOC_FREE(tmp_ctx);
1331 0 : return ret;
1332 : }
1333 :
1334 0 : static int ads_group_delete(struct net_context *c, int argc, const char **argv)
1335 : {
1336 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1337 0 : ADS_STRUCT *ads = NULL;
1338 0 : ADS_STATUS status;
1339 0 : LDAPMessage *res = NULL;
1340 0 : char *groupdn = NULL;
1341 0 : int ret = -1;
1342 :
1343 0 : if (argc < 1 || c->display_usage) {
1344 0 : TALLOC_FREE(tmp_ctx);
1345 0 : return net_ads_group_usage(c, argc, argv);
1346 : }
1347 :
1348 0 : status = ads_startup(c, false, tmp_ctx, &ads);
1349 0 : if (!ADS_ERR_OK(status)) {
1350 0 : goto out;
1351 : }
1352 :
1353 0 : status = ads_find_user_acct(ads, &res, argv[0]);
1354 0 : if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1355 0 : d_printf(_("Group %s does not exist.\n"), argv[0]);
1356 0 : goto out;
1357 : }
1358 :
1359 0 : groupdn = ads_get_dn(ads, tmp_ctx, res);
1360 0 : if (groupdn == NULL) {
1361 0 : goto out;
1362 : }
1363 :
1364 0 : status = ads_del_dn(ads, groupdn);
1365 0 : if (!ADS_ERR_OK(status)) {
1366 0 : d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
1367 : ads_errstr(status));
1368 0 : goto out;
1369 : }
1370 0 : d_printf(_("Group %s deleted\n"), argv[0]);
1371 :
1372 0 : ret = 0;
1373 0 : out:
1374 0 : ads_msgfree(ads, res);
1375 0 : TALLOC_FREE(tmp_ctx);
1376 0 : return ret;
1377 : }
1378 :
1379 0 : int net_ads_group(struct net_context *c, int argc, const char **argv)
1380 : {
1381 0 : struct functable func[] = {
1382 : {
1383 : "add",
1384 : ads_group_add,
1385 : NET_TRANSPORT_ADS,
1386 : N_("Add an AD group"),
1387 : N_("net ads group add\n"
1388 : " Add an AD group")
1389 : },
1390 : {
1391 : "delete",
1392 : ads_group_delete,
1393 : NET_TRANSPORT_ADS,
1394 : N_("Delete an AD group"),
1395 : N_("net ads group delete\n"
1396 : " Delete an AD group")
1397 : },
1398 : {NULL, NULL, 0, NULL, NULL}
1399 : };
1400 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1401 0 : ADS_STRUCT *ads = NULL;
1402 0 : ADS_STATUS status;
1403 0 : const char *shortattrs[] = {"sAMAccountName", NULL};
1404 0 : const char *longattrs[] = {"sAMAccountName", "description", NULL};
1405 0 : char *disp_fields[2] = {NULL, NULL};
1406 0 : int ret = -1;
1407 :
1408 0 : if (argc >= 0) {
1409 0 : TALLOC_FREE(tmp_ctx);
1410 0 : return net_run_function(c, argc, argv, "net ads group", func);
1411 : }
1412 :
1413 0 : if (c->display_usage) {
1414 0 : d_printf( "%s\n"
1415 : "net ads group\n"
1416 : " %s\n",
1417 : _("Usage:"),
1418 : _("List AD groups"));
1419 0 : net_display_usage_from_functable(func);
1420 0 : TALLOC_FREE(tmp_ctx);
1421 0 : return -1;
1422 : }
1423 :
1424 0 : status = ads_startup(c, false, tmp_ctx, &ads);
1425 0 : if (!ADS_ERR_OK(status)) {
1426 0 : goto out;
1427 : }
1428 :
1429 0 : if (c->opt_long_list_entries)
1430 0 : d_printf(_("\nGroup name Comment"
1431 : "\n-----------------------------\n"));
1432 :
1433 0 : status = ads_do_search_all_fn(ads,
1434 0 : ads->config.bind_path,
1435 : LDAP_SCOPE_SUBTREE,
1436 : "(objectCategory=group)",
1437 0 : c->opt_long_list_entries ?
1438 : longattrs : shortattrs,
1439 : usergrp_display,
1440 : disp_fields);
1441 0 : if (!ADS_ERR_OK(status)) {
1442 0 : goto out;
1443 : }
1444 :
1445 0 : ret = 0;
1446 0 : out:
1447 0 : TALLOC_FREE(tmp_ctx);
1448 0 : return ret;
1449 : }
1450 :
1451 0 : static int net_ads_status(struct net_context *c, int argc, const char **argv)
1452 : {
1453 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1454 0 : ADS_STRUCT *ads = NULL;
1455 0 : ADS_STATUS status;
1456 0 : LDAPMessage *res = NULL;
1457 0 : int ret = -1;
1458 :
1459 0 : if (c->display_usage) {
1460 0 : d_printf( "%s\n"
1461 : "net ads status\n"
1462 : " %s\n",
1463 : _("Usage:"),
1464 : _("Display machine account details"));
1465 0 : TALLOC_FREE(tmp_ctx);
1466 0 : return -1;
1467 : }
1468 :
1469 0 : net_warn_member_options();
1470 :
1471 0 : status = ads_startup(c, true, tmp_ctx, &ads);
1472 0 : if (!ADS_ERR_OK(status)) {
1473 0 : goto out;
1474 : }
1475 :
1476 0 : status = ads_find_machine_acct(ads, &res, lp_netbios_name());
1477 0 : if (!ADS_ERR_OK(status)) {
1478 0 : d_fprintf(stderr, _("ads_find_machine_acct: %s\n"),
1479 : ads_errstr(status));
1480 0 : goto out;
1481 : }
1482 :
1483 0 : if (ads_count_replies(ads, res) == 0) {
1484 0 : d_fprintf(stderr, _("No machine account for '%s' found\n"),
1485 : lp_netbios_name());
1486 0 : goto out;
1487 : }
1488 :
1489 0 : ads_dump(ads, res);
1490 :
1491 0 : ret = 0;
1492 0 : out:
1493 0 : ads_msgfree(ads, res);
1494 0 : TALLOC_FREE(tmp_ctx);
1495 0 : return ret;
1496 : }
1497 :
1498 : /*******************************************************************
1499 : Leave an AD domain. Windows XP disables the machine account.
1500 : We'll try the same. The old code would do an LDAP delete.
1501 : That only worked using the machine creds because added the machine
1502 : with full control to the computer object's ACL.
1503 : *******************************************************************/
1504 :
1505 34 : static int net_ads_leave(struct net_context *c, int argc, const char **argv)
1506 : {
1507 34 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1508 34 : struct libnet_UnjoinCtx *r = NULL;
1509 0 : WERROR werr;
1510 34 : int ret = -1;
1511 :
1512 34 : if (c->display_usage) {
1513 0 : d_printf( "%s\n"
1514 : "net ads leave [--keep-account]\n"
1515 : " %s\n",
1516 : _("Usage:"),
1517 : _("Leave an AD domain"));
1518 0 : TALLOC_FREE(tmp_ctx);
1519 0 : return -1;
1520 : }
1521 :
1522 34 : if (!*lp_realm()) {
1523 0 : d_fprintf(stderr, _("No realm set, are we joined ?\n"));
1524 0 : TALLOC_FREE(tmp_ctx);
1525 0 : return -1;
1526 : }
1527 :
1528 34 : if (!c->opt_kerberos) {
1529 32 : use_in_memory_ccache();
1530 : }
1531 :
1532 34 : if (!c->msg_ctx) {
1533 0 : d_fprintf(stderr, _("Could not initialise message context. "
1534 : "Try running as root\n"));
1535 0 : goto done;
1536 : }
1537 :
1538 34 : werr = libnet_init_UnjoinCtx(tmp_ctx, &r);
1539 34 : if (!W_ERROR_IS_OK(werr)) {
1540 0 : d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
1541 0 : goto done;
1542 : }
1543 :
1544 34 : r->in.debug = true;
1545 34 : r->in.use_kerberos = c->opt_kerberos;
1546 34 : r->in.dc_name = c->opt_host;
1547 34 : r->in.domain_name = lp_realm();
1548 34 : r->in.admin_account = c->opt_user_name;
1549 34 : r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1550 34 : r->in.modify_config = lp_config_backend_is_registry();
1551 :
1552 : /* Try to delete it, but if that fails, disable it. The
1553 : WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1554 34 : r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1555 : WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
1556 34 : if (c->opt_keep_account) {
1557 2 : r->in.delete_machine_account = false;
1558 : } else {
1559 32 : r->in.delete_machine_account = true;
1560 : }
1561 :
1562 34 : r->in.msg_ctx = c->msg_ctx;
1563 :
1564 34 : werr = libnet_Unjoin(tmp_ctx, r);
1565 34 : if (!W_ERROR_IS_OK(werr)) {
1566 2 : d_printf(_("Failed to leave domain: %s\n"),
1567 2 : r->out.error_string ? r->out.error_string :
1568 0 : get_friendly_werror_msg(werr));
1569 2 : goto done;
1570 : }
1571 :
1572 32 : if (r->out.deleted_machine_account) {
1573 30 : d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1574 30 : r->in.machine_name, r->out.dns_domain_name);
1575 30 : ret = 0;
1576 30 : goto done;
1577 : }
1578 :
1579 : /* We couldn't delete it - see if the disable succeeded. */
1580 2 : if (r->out.disabled_machine_account) {
1581 2 : d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1582 2 : r->in.machine_name, r->out.dns_domain_name);
1583 2 : ret = 0;
1584 2 : goto done;
1585 : }
1586 :
1587 : /* Based on what we requested, we shouldn't get here, but if
1588 : we did, it means the secrets were removed, and therefore
1589 : we have left the domain */
1590 0 : d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"),
1591 0 : r->in.machine_name, r->out.dns_domain_name);
1592 :
1593 0 : ret = 0;
1594 34 : done:
1595 34 : TALLOC_FREE(tmp_ctx);
1596 34 : return ret;
1597 : }
1598 :
1599 30 : static ADS_STATUS net_ads_join_ok(struct net_context *c)
1600 : {
1601 30 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1602 30 : ADS_STRUCT *ads = NULL;
1603 0 : ADS_STATUS status;
1604 0 : fstring dc_name;
1605 0 : struct sockaddr_storage dcip;
1606 :
1607 30 : if (!secrets_init()) {
1608 0 : DEBUG(1,("Failed to initialise secrets database\n"));
1609 0 : TALLOC_FREE(tmp_ctx);
1610 0 : return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
1611 : }
1612 :
1613 30 : net_warn_member_options();
1614 :
1615 30 : net_use_krb_machine_account(c);
1616 :
1617 30 : get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
1618 :
1619 30 : status = ads_startup(c, true, tmp_ctx, &ads);
1620 30 : if (!ADS_ERR_OK(status)) {
1621 0 : goto out;
1622 : }
1623 :
1624 30 : status = ADS_ERROR_NT(NT_STATUS_OK);
1625 30 : out:
1626 30 : TALLOC_FREE(tmp_ctx);
1627 30 : return status;
1628 : }
1629 :
1630 : /*
1631 : check that an existing join is OK
1632 : */
1633 30 : int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
1634 : {
1635 0 : ADS_STATUS status;
1636 30 : use_in_memory_ccache();
1637 :
1638 30 : if (c->display_usage) {
1639 0 : d_printf( "%s\n"
1640 : "net ads testjoin\n"
1641 : " %s\n",
1642 : _("Usage:"),
1643 : _("Test if the existing join is ok"));
1644 0 : return -1;
1645 : }
1646 :
1647 30 : net_warn_member_options();
1648 :
1649 : /* Display success or failure */
1650 30 : status = net_ads_join_ok(c);
1651 30 : if (!ADS_ERR_OK(status)) {
1652 0 : fprintf(stderr, _("Join to domain is not valid: %s\n"),
1653 : get_friendly_nt_error_msg(ads_ntstatus(status)));
1654 0 : return -1;
1655 : }
1656 :
1657 30 : printf(_("Join is OK\n"));
1658 30 : return 0;
1659 : }
1660 :
1661 : /*******************************************************************
1662 : Simple config checks before beginning the join
1663 : ********************************************************************/
1664 :
1665 42 : static WERROR check_ads_config( void )
1666 : {
1667 42 : if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
1668 0 : d_printf(_("Host is not configured as a member server.\n"));
1669 0 : return WERR_INVALID_DOMAIN_ROLE;
1670 : }
1671 :
1672 42 : if (strlen(lp_netbios_name()) > 15) {
1673 0 : d_printf(_("Our netbios name can be at most 15 chars long, "
1674 : "\"%s\" is %u chars long\n"), lp_netbios_name(),
1675 0 : (unsigned int)strlen(lp_netbios_name()));
1676 0 : return WERR_INVALID_COMPUTERNAME;
1677 : }
1678 :
1679 42 : if ( lp_security() == SEC_ADS && !*lp_realm()) {
1680 0 : d_fprintf(stderr, _("realm must be set in %s for ADS "
1681 : "join to succeed.\n"), get_dyn_CONFIGFILE());
1682 0 : return WERR_INVALID_PARAMETER;
1683 : }
1684 :
1685 42 : return WERR_OK;
1686 : }
1687 :
1688 : /*******************************************************************
1689 : ********************************************************************/
1690 :
1691 0 : static int net_ads_join_usage(struct net_context *c, int argc, const char **argv)
1692 : {
1693 0 : d_printf(_("net ads join [--no-dns-updates] [options]\n"
1694 : "Valid options:\n"));
1695 0 : d_printf(_(" dnshostname=FQDN Set the dnsHostName attribute during the join.\n"
1696 : " The default is in the form netbiosname.dnsdomain\n"));
1697 0 : d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1698 : " The default UPN is in the form host/netbiosname@REALM.\n"));
1699 0 : d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1700 : " The OU string read from top to bottom without RDNs\n"
1701 : " and delimited by a '/'.\n"
1702 : " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1703 : " NB: A backslash '\\' is used as escape at multiple\n"
1704 : " levels and may need to be doubled or even\n"
1705 : " quadrupled. It is not used as a separator.\n"));
1706 0 : d_printf(_(" machinepass=PASS Set the machine password to a specific value during\n"
1707 : " the join. The default password is random.\n"));
1708 0 : d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1709 0 : d_printf(_(" osVer=string Set the operatingSystemVersion attribute during join.\n"
1710 : " NB: osName and osVer must be specified together for\n"
1711 : " either to take effect. The operatingSystemService\n"
1712 : " attribute is then also set along with the two\n"
1713 : " other attributes.\n"));
1714 0 : d_printf(_(" osServicePack=string Set the operatingSystemServicePack attribute\n"
1715 : " during the join.\n"
1716 : " NB: If not specified then by default the samba\n"
1717 : " version string is used instead.\n"));
1718 0 : return -1;
1719 : }
1720 :
1721 :
1722 42 : int net_ads_join(struct net_context *c, int argc, const char **argv)
1723 : {
1724 42 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1725 42 : struct libnet_JoinCtx *r = NULL;
1726 42 : const char *domain = lp_realm();
1727 42 : WERROR werr = WERR_NERR_SETUPNOTJOINED;
1728 42 : bool createupn = false;
1729 42 : const char *dnshostname = NULL;
1730 42 : const char *machineupn = NULL;
1731 42 : const char *machine_password = NULL;
1732 42 : const char *create_in_ou = NULL;
1733 0 : int i;
1734 42 : const char *os_name = NULL;
1735 42 : const char *os_version = NULL;
1736 42 : const char *os_servicepack = NULL;
1737 42 : bool modify_config = lp_config_backend_is_registry();
1738 42 : enum libnetjoin_JoinDomNameType domain_name_type = JoinDomNameTypeDNS;
1739 42 : int ret = -1;
1740 :
1741 42 : if (c->display_usage) {
1742 0 : TALLOC_FREE(tmp_ctx);
1743 0 : return net_ads_join_usage(c, argc, argv);
1744 : }
1745 :
1746 42 : net_warn_member_options();
1747 :
1748 42 : if (!modify_config) {
1749 42 : werr = check_ads_config();
1750 42 : if (!W_ERROR_IS_OK(werr)) {
1751 0 : d_fprintf(stderr, _("Invalid configuration. Exiting....\n"));
1752 0 : goto fail;
1753 : }
1754 : }
1755 :
1756 42 : if (!c->opt_kerberos) {
1757 30 : use_in_memory_ccache();
1758 : }
1759 :
1760 42 : werr = libnet_init_JoinCtx(tmp_ctx, &r);
1761 42 : if (!W_ERROR_IS_OK(werr)) {
1762 0 : goto fail;
1763 : }
1764 :
1765 : /* process additional command line args */
1766 :
1767 48 : for ( i=0; i<argc; i++ ) {
1768 6 : if ( !strncasecmp_m(argv[i], "dnshostname", strlen("dnshostname")) ) {
1769 2 : dnshostname = get_string_param(argv[i]);
1770 : }
1771 4 : else if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
1772 2 : createupn = true;
1773 2 : machineupn = get_string_param(argv[i]);
1774 : }
1775 2 : else if ( !strncasecmp_m(argv[i], "createcomputer", strlen("createcomputer")) ) {
1776 2 : if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
1777 0 : d_fprintf(stderr, _("Please supply a valid OU path.\n"));
1778 0 : werr = WERR_INVALID_PARAMETER;
1779 0 : goto fail;
1780 : }
1781 : }
1782 0 : else if ( !strncasecmp_m(argv[i], "osName", strlen("osName")) ) {
1783 0 : if ( (os_name = get_string_param(argv[i])) == NULL ) {
1784 0 : d_fprintf(stderr, _("Please supply a operating system name.\n"));
1785 0 : werr = WERR_INVALID_PARAMETER;
1786 0 : goto fail;
1787 : }
1788 : }
1789 0 : else if ( !strncasecmp_m(argv[i], "osVer", strlen("osVer")) ) {
1790 0 : if ( (os_version = get_string_param(argv[i])) == NULL ) {
1791 0 : d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
1792 0 : werr = WERR_INVALID_PARAMETER;
1793 0 : goto fail;
1794 : }
1795 : }
1796 0 : else if ( !strncasecmp_m(argv[i], "osServicePack", strlen("osServicePack")) ) {
1797 0 : if ( (os_servicepack = get_string_param(argv[i])) == NULL ) {
1798 0 : d_fprintf(stderr, _("Please supply a valid servicepack identifier.\n"));
1799 0 : werr = WERR_INVALID_PARAMETER;
1800 0 : goto fail;
1801 : }
1802 : }
1803 0 : else if ( !strncasecmp_m(argv[i], "machinepass", strlen("machinepass")) ) {
1804 0 : if ( (machine_password = get_string_param(argv[i])) == NULL ) {
1805 0 : d_fprintf(stderr, _("Please supply a valid password to set as trust account password.\n"));
1806 0 : werr = WERR_INVALID_PARAMETER;
1807 0 : goto fail;
1808 : }
1809 : } else {
1810 0 : domain = argv[i];
1811 0 : if (strchr(domain, '.') == NULL) {
1812 0 : domain_name_type = JoinDomNameTypeUnknown;
1813 : } else {
1814 0 : domain_name_type = JoinDomNameTypeDNS;
1815 : }
1816 : }
1817 : }
1818 :
1819 42 : if (!*domain) {
1820 0 : d_fprintf(stderr, _("Please supply a valid domain name\n"));
1821 0 : werr = WERR_INVALID_PARAMETER;
1822 0 : goto fail;
1823 : }
1824 :
1825 42 : if (!c->msg_ctx) {
1826 0 : d_fprintf(stderr, _("Could not initialise message context. "
1827 : "Try running as root\n"));
1828 0 : werr = WERR_ACCESS_DENIED;
1829 0 : goto fail;
1830 : }
1831 :
1832 : /* Do the domain join here */
1833 :
1834 42 : r->in.domain_name = domain;
1835 42 : r->in.domain_name_type = domain_name_type;
1836 42 : r->in.create_upn = createupn;
1837 42 : r->in.upn = machineupn;
1838 42 : r->in.dnshostname = dnshostname;
1839 42 : r->in.account_ou = create_in_ou;
1840 42 : r->in.os_name = os_name;
1841 42 : r->in.os_version = os_version;
1842 42 : r->in.os_servicepack = os_servicepack;
1843 42 : r->in.dc_name = c->opt_host;
1844 42 : r->in.admin_account = c->opt_user_name;
1845 42 : r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1846 42 : r->in.machine_password = machine_password;
1847 42 : r->in.debug = true;
1848 42 : r->in.use_kerberos = c->opt_kerberos;
1849 42 : r->in.modify_config = modify_config;
1850 42 : r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1851 : WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
1852 : WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
1853 42 : r->in.msg_ctx = c->msg_ctx;
1854 :
1855 42 : werr = libnet_Join(tmp_ctx, r);
1856 46 : if (W_ERROR_EQUAL(werr, WERR_NERR_DCNOTFOUND) &&
1857 4 : strequal(domain, lp_realm())) {
1858 4 : r->in.domain_name = lp_workgroup();
1859 4 : r->in.domain_name_type = JoinDomNameTypeNBT;
1860 4 : werr = libnet_Join(tmp_ctx, r);
1861 : }
1862 42 : if (!W_ERROR_IS_OK(werr)) {
1863 2 : goto fail;
1864 : }
1865 :
1866 : /* Check the short name of the domain */
1867 :
1868 40 : if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
1869 0 : d_printf(_("The workgroup in %s does not match the short\n"
1870 : "domain name obtained from the server.\n"
1871 : "Using the name [%s] from the server.\n"
1872 : "You should set \"workgroup = %s\" in %s.\n"),
1873 0 : get_dyn_CONFIGFILE(), r->out.netbios_domain_name,
1874 0 : r->out.netbios_domain_name, get_dyn_CONFIGFILE());
1875 : }
1876 :
1877 40 : d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name);
1878 :
1879 40 : if (r->out.dns_domain_name) {
1880 40 : d_printf(_("Joined '%s' to dns domain '%s'\n"), r->in.machine_name,
1881 40 : r->out.dns_domain_name);
1882 : } else {
1883 0 : d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name,
1884 0 : r->out.netbios_domain_name);
1885 : }
1886 :
1887 : /* print out informative error string in case there is one */
1888 40 : if (r->out.error_string != NULL) {
1889 0 : d_printf("%s\n", r->out.error_string);
1890 : }
1891 :
1892 : /*
1893 : * We try doing the dns update (if it was compiled in
1894 : * and if it was not disabled on the command line).
1895 : * If the dns update fails, we still consider the join
1896 : * operation as succeeded if we came this far.
1897 : */
1898 40 : if (!c->opt_no_dns_updates) {
1899 40 : net_ads_join_dns_updates(c, tmp_ctx, r);
1900 : }
1901 :
1902 40 : ret = 0;
1903 :
1904 42 : fail:
1905 42 : if (ret != 0) {
1906 : /* issue an overall failure message at the end. */
1907 2 : d_printf(_("Failed to join domain: %s\n"),
1908 2 : r && r->out.error_string ? r->out.error_string :
1909 0 : get_friendly_werror_msg(werr));
1910 : }
1911 :
1912 42 : TALLOC_FREE(tmp_ctx);
1913 :
1914 42 : return ret;
1915 : }
1916 :
1917 : /*******************************************************************
1918 : ********************************************************************/
1919 :
1920 12 : static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
1921 : {
1922 : #if defined(HAVE_KRB5)
1923 12 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1924 12 : ADS_STRUCT *ads = NULL;
1925 0 : ADS_STATUS status;
1926 0 : NTSTATUS ntstatus;
1927 12 : const char *hostname = NULL;
1928 12 : const char **addrs_list = NULL;
1929 12 : struct sockaddr_storage *addrs = NULL;
1930 12 : int num_addrs = 0;
1931 0 : int count;
1932 12 : int ret = -1;
1933 :
1934 : #ifdef DEVELOPER
1935 12 : talloc_enable_leak_report();
1936 : #endif
1937 :
1938 12 : if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
1939 0 : d_fprintf(stderr, _("Refusing DNS updates with automatic "
1940 : "detection of addresses in a clustered "
1941 : "setup.\n"));
1942 0 : c->display_usage = true;
1943 : }
1944 :
1945 12 : if (c->display_usage) {
1946 0 : d_printf( "%s\n"
1947 : "net ads dns register [hostname [IP [IP...]]] "
1948 : "[--force] [--dns-ttl TTL]\n"
1949 : " %s\n",
1950 : _("Usage:"),
1951 : _("Register hostname with DNS\n"));
1952 0 : TALLOC_FREE(tmp_ctx);
1953 0 : return -1;
1954 : }
1955 :
1956 12 : if (argc >= 1) {
1957 12 : hostname = argv[0];
1958 : }
1959 :
1960 12 : if (argc > 1) {
1961 12 : num_addrs = argc - 1;
1962 12 : addrs_list = &argv[1];
1963 0 : } else if (lp_clustering()) {
1964 0 : addrs_list = lp_cluster_addresses();
1965 0 : num_addrs = str_list_length(addrs_list);
1966 : }
1967 :
1968 12 : if (num_addrs > 0) {
1969 12 : addrs = talloc_zero_array(tmp_ctx,
1970 : struct sockaddr_storage,
1971 : num_addrs);
1972 12 : if (addrs == NULL) {
1973 0 : d_fprintf(stderr, _("Error allocating memory!\n"));
1974 0 : goto out;
1975 : }
1976 : }
1977 :
1978 26 : for (count = 0; count < num_addrs; count++) {
1979 14 : if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
1980 0 : d_fprintf(stderr, "%s '%s'.\n",
1981 : _("Cannot interpret address"),
1982 0 : addrs_list[count]);
1983 0 : goto out;
1984 : }
1985 : }
1986 :
1987 12 : status = ads_startup(c, true, tmp_ctx, &ads);
1988 12 : if ( !ADS_ERR_OK(status) ) {
1989 0 : DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1990 0 : goto out;
1991 : }
1992 :
1993 12 : ntstatus = net_update_dns_ext(c,
1994 : tmp_ctx,
1995 : ads,
1996 : hostname,
1997 : addrs,
1998 : num_addrs,
1999 : false);
2000 12 : if (!NT_STATUS_IS_OK(ntstatus)) {
2001 2 : d_fprintf( stderr, _("DNS update failed!\n") );
2002 2 : goto out;
2003 : }
2004 :
2005 10 : d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
2006 :
2007 10 : ret = 0;
2008 12 : out:
2009 12 : TALLOC_FREE(tmp_ctx);
2010 :
2011 12 : return ret;
2012 : #else
2013 : d_fprintf(stderr,
2014 : _("DNS update support not enabled at compile time!\n"));
2015 : return -1;
2016 : #endif
2017 : }
2018 :
2019 8 : static int net_ads_dns_unregister(struct net_context *c,
2020 : int argc,
2021 : const char **argv)
2022 : {
2023 : #if defined(HAVE_KRB5)
2024 8 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2025 8 : ADS_STRUCT *ads = NULL;
2026 0 : ADS_STATUS status;
2027 0 : NTSTATUS ntstatus;
2028 8 : const char *hostname = NULL;
2029 8 : int ret = -1;
2030 :
2031 : #ifdef DEVELOPER
2032 8 : talloc_enable_leak_report();
2033 : #endif
2034 :
2035 8 : if (argc != 1) {
2036 0 : c->display_usage = true;
2037 : }
2038 :
2039 8 : if (c->display_usage) {
2040 0 : d_printf( "%s\n"
2041 : "net ads dns unregister [hostname]\n"
2042 : " %s\n",
2043 : _("Usage:"),
2044 : _("Remove all IP Address entries for a given\n"
2045 : " hostname from the Active Directory server.\n"));
2046 0 : TALLOC_FREE(tmp_ctx);
2047 0 : return -1;
2048 : }
2049 :
2050 : /* Get the hostname for un-registering */
2051 8 : hostname = argv[0];
2052 :
2053 8 : status = ads_startup(c, true, tmp_ctx, &ads);
2054 8 : if ( !ADS_ERR_OK(status) ) {
2055 0 : DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
2056 0 : goto out;
2057 : }
2058 :
2059 8 : ntstatus = net_update_dns_ext(c,
2060 : tmp_ctx,
2061 : ads,
2062 : hostname,
2063 : NULL,
2064 : 0,
2065 : true);
2066 8 : if (!NT_STATUS_IS_OK(ntstatus)) {
2067 0 : d_fprintf( stderr, _("DNS update failed!\n") );
2068 0 : goto out;
2069 : }
2070 :
2071 8 : d_fprintf( stderr, _("Successfully un-registered hostname from DNS\n"));
2072 :
2073 8 : ret = 0;
2074 8 : out:
2075 8 : TALLOC_FREE(tmp_ctx);
2076 :
2077 8 : return ret;
2078 : #else
2079 : d_fprintf(stderr,
2080 : _("DNS update support not enabled at compile time!\n"));
2081 : return -1;
2082 : #endif
2083 : }
2084 :
2085 :
2086 2 : static int net_ads_dns_async(struct net_context *c, int argc, const char **argv)
2087 : {
2088 2 : size_t num_names = 0;
2089 2 : char **hostnames = NULL;
2090 2 : size_t i = 0;
2091 2 : struct samba_sockaddr *addrs = NULL;
2092 0 : NTSTATUS status;
2093 :
2094 2 : if (argc != 1 || c->display_usage) {
2095 0 : d_printf( "%s\n"
2096 : " %s\n"
2097 : " %s\n",
2098 : _("Usage:"),
2099 : _("net ads dns async <name>\n"),
2100 : _(" Async look up hostname from the DNS server\n"
2101 : " hostname\tName to look up\n"));
2102 0 : return -1;
2103 : }
2104 :
2105 2 : status = ads_dns_lookup_a(talloc_tos(),
2106 : argv[0],
2107 : &num_names,
2108 : &hostnames,
2109 : &addrs);
2110 2 : if (!NT_STATUS_IS_OK(status)) {
2111 0 : d_printf("Looking up A record for %s got error %s\n",
2112 : argv[0],
2113 : nt_errstr(status));
2114 0 : return -1;
2115 : }
2116 2 : d_printf("Async A record lookup - got %u names for %s\n",
2117 : (unsigned int)num_names,
2118 : argv[0]);
2119 4 : for (i = 0; i < num_names; i++) {
2120 0 : char addr_buf[INET6_ADDRSTRLEN];
2121 2 : print_sockaddr(addr_buf,
2122 : sizeof(addr_buf),
2123 2 : &addrs[i].u.ss);
2124 2 : d_printf("hostname[%u] = %s, IPv4addr = %s\n",
2125 : (unsigned int)i,
2126 2 : hostnames[i],
2127 : addr_buf);
2128 : }
2129 :
2130 : #if defined(HAVE_IPV6)
2131 2 : status = ads_dns_lookup_aaaa(talloc_tos(),
2132 : argv[0],
2133 : &num_names,
2134 : &hostnames,
2135 : &addrs);
2136 2 : if (!NT_STATUS_IS_OK(status)) {
2137 0 : d_printf("Looking up AAAA record for %s got error %s\n",
2138 : argv[0],
2139 : nt_errstr(status));
2140 0 : return -1;
2141 : }
2142 2 : d_printf("Async AAAA record lookup - got %u names for %s\n",
2143 : (unsigned int)num_names,
2144 : argv[0]);
2145 4 : for (i = 0; i < num_names; i++) {
2146 0 : char addr_buf[INET6_ADDRSTRLEN];
2147 2 : print_sockaddr(addr_buf,
2148 : sizeof(addr_buf),
2149 2 : &addrs[i].u.ss);
2150 2 : d_printf("hostname[%u] = %s, IPv6addr = %s\n",
2151 : (unsigned int)i,
2152 2 : hostnames[i],
2153 : addr_buf);
2154 : }
2155 : #endif
2156 2 : return 0;
2157 : }
2158 :
2159 :
2160 22 : static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
2161 : {
2162 22 : struct functable func[] = {
2163 : {
2164 : "register",
2165 : net_ads_dns_register,
2166 : NET_TRANSPORT_ADS,
2167 : N_("Add host dns entry to AD"),
2168 : N_("net ads dns register\n"
2169 : " Add host dns entry to AD")
2170 : },
2171 : {
2172 : "unregister",
2173 : net_ads_dns_unregister,
2174 : NET_TRANSPORT_ADS,
2175 : N_("Remove host dns entry from AD"),
2176 : N_("net ads dns unregister\n"
2177 : " Remove host dns entry from AD")
2178 : },
2179 : {
2180 : "async",
2181 : net_ads_dns_async,
2182 : NET_TRANSPORT_ADS,
2183 : N_("Look up host"),
2184 : N_("net ads dns async\n"
2185 : " Look up host using async DNS")
2186 : },
2187 : {NULL, NULL, 0, NULL, NULL}
2188 : };
2189 :
2190 22 : return net_run_function(c, argc, argv, "net ads dns", func);
2191 : }
2192 :
2193 : /*******************************************************************
2194 : ********************************************************************/
2195 :
2196 0 : int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
2197 : {
2198 0 : d_printf(_(
2199 : "\nnet ads printer search <printer>"
2200 : "\n\tsearch for a printer in the directory\n"
2201 : "\nnet ads printer info <printer> <server>"
2202 : "\n\tlookup info in directory for printer on server"
2203 : "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
2204 : "\nnet ads printer publish <printername>"
2205 : "\n\tpublish printer in directory"
2206 : "\n\t(note: printer name is required)\n"
2207 : "\nnet ads printer remove <printername>"
2208 : "\n\tremove printer from directory"
2209 : "\n\t(note: printer name is required)\n"));
2210 0 : return -1;
2211 : }
2212 :
2213 : /*******************************************************************
2214 : ********************************************************************/
2215 :
2216 0 : static int net_ads_printer_search(struct net_context *c,
2217 : int argc,
2218 : const char **argv)
2219 : {
2220 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2221 0 : ADS_STRUCT *ads = NULL;
2222 0 : ADS_STATUS status;
2223 0 : LDAPMessage *res = NULL;
2224 0 : int ret = -1;
2225 :
2226 0 : if (c->display_usage) {
2227 0 : d_printf( "%s\n"
2228 : "net ads printer search\n"
2229 : " %s\n",
2230 : _("Usage:"),
2231 : _("List printers in the AD"));
2232 0 : TALLOC_FREE(tmp_ctx);
2233 0 : return -1;
2234 : }
2235 :
2236 0 : status = ads_startup(c, false, tmp_ctx, &ads);
2237 0 : if (!ADS_ERR_OK(status)) {
2238 0 : goto out;
2239 : }
2240 :
2241 0 : status = ads_find_printers(ads, &res);
2242 0 : if (!ADS_ERR_OK(status)) {
2243 0 : d_fprintf(stderr, _("ads_find_printer: %s\n"),
2244 : ads_errstr(status));
2245 0 : goto out;
2246 : }
2247 :
2248 0 : if (ads_count_replies(ads, res) == 0) {
2249 0 : d_fprintf(stderr, _("No results found\n"));
2250 0 : goto out;
2251 : }
2252 :
2253 0 : ads_dump(ads, res);
2254 :
2255 0 : ret = 0;
2256 0 : out:
2257 0 : ads_msgfree(ads, res);
2258 0 : TALLOC_FREE(tmp_ctx);
2259 0 : return ret;
2260 : }
2261 :
2262 0 : static int net_ads_printer_info(struct net_context *c,
2263 : int argc,
2264 : const char **argv)
2265 : {
2266 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2267 0 : ADS_STRUCT *ads = NULL;
2268 0 : ADS_STATUS status;
2269 0 : const char *servername = NULL;
2270 0 : const char *printername = NULL;
2271 0 : LDAPMessage *res = NULL;
2272 0 : int ret = -1;
2273 :
2274 0 : if (c->display_usage) {
2275 0 : d_printf("%s\n%s",
2276 : _("Usage:"),
2277 : _("net ads printer info [printername [servername]]\n"
2278 : " Display printer info from AD\n"
2279 : " printername\tPrinter name or wildcard\n"
2280 : " servername\tName of the print server\n"));
2281 0 : TALLOC_FREE(tmp_ctx);
2282 0 : return -1;
2283 : }
2284 :
2285 0 : status = ads_startup(c, false, tmp_ctx, &ads);
2286 0 : if (!ADS_ERR_OK(status)) {
2287 0 : goto out;
2288 : }
2289 :
2290 0 : if (argc > 0) {
2291 0 : printername = argv[0];
2292 : } else {
2293 0 : printername = "*";
2294 : }
2295 :
2296 0 : if (argc > 1) {
2297 0 : servername = argv[1];
2298 : } else {
2299 0 : servername = lp_netbios_name();
2300 : }
2301 :
2302 0 : status = ads_find_printer_on_server(ads, &res, printername, servername);
2303 0 : if (!ADS_ERR_OK(status)) {
2304 0 : d_fprintf(stderr, _("Server '%s' not found: %s\n"),
2305 : servername, ads_errstr(status));
2306 0 : goto out;
2307 : }
2308 :
2309 0 : if (ads_count_replies(ads, res) == 0) {
2310 0 : d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
2311 0 : goto out;
2312 : }
2313 :
2314 0 : ads_dump(ads, res);
2315 :
2316 0 : ret = 0;
2317 0 : out:
2318 0 : ads_msgfree(ads, res);
2319 0 : TALLOC_FREE(tmp_ctx);
2320 0 : return ret;
2321 : }
2322 :
2323 0 : static int net_ads_printer_publish(struct net_context *c,
2324 : int argc,
2325 : const char **argv)
2326 : {
2327 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2328 0 : ADS_STRUCT *ads = NULL;
2329 0 : ADS_STATUS status;
2330 0 : const char *servername = NULL;
2331 0 : const char *printername = NULL;
2332 0 : struct cli_state *cli = NULL;
2333 0 : struct rpc_pipe_client *pipe_hnd = NULL;
2334 0 : struct sockaddr_storage server_ss = { 0 };
2335 0 : NTSTATUS nt_status;
2336 0 : ADS_MODLIST mods = NULL;
2337 0 : char *prt_dn = NULL;
2338 0 : char *srv_dn = NULL;
2339 0 : char **srv_cn = NULL;
2340 0 : char *srv_cn_escaped = NULL;
2341 0 : char *printername_escaped = NULL;
2342 0 : LDAPMessage *res = NULL;
2343 0 : bool ok;
2344 0 : int ret = -1;
2345 :
2346 0 : if (argc < 1 || c->display_usage) {
2347 0 : d_printf("%s\n%s",
2348 : _("Usage:"),
2349 : _("net ads printer publish <printername> [servername]\n"
2350 : " Publish printer in AD\n"
2351 : " printername\tName of the printer\n"
2352 : " servername\tName of the print server\n"));
2353 0 : TALLOC_FREE(tmp_ctx);
2354 0 : return -1;
2355 : }
2356 :
2357 0 : mods = ads_init_mods(tmp_ctx);
2358 0 : if (mods == NULL) {
2359 0 : d_fprintf(stderr, _("Out of memory\n"));
2360 0 : goto out;
2361 : }
2362 :
2363 0 : status = ads_startup(c, true, tmp_ctx, &ads);
2364 0 : if (!ADS_ERR_OK(status)) {
2365 0 : goto out;
2366 : }
2367 :
2368 0 : printername = argv[0];
2369 :
2370 0 : if (argc == 2) {
2371 0 : servername = argv[1];
2372 : } else {
2373 0 : servername = lp_netbios_name();
2374 : }
2375 :
2376 : /* Get printer data from SPOOLSS */
2377 :
2378 0 : ok = resolve_name(servername, &server_ss, 0x20, false);
2379 0 : if (!ok) {
2380 0 : d_fprintf(stderr, _("Could not find server %s\n"),
2381 : servername);
2382 0 : goto out;
2383 : }
2384 :
2385 0 : cli_credentials_set_kerberos_state(c->creds,
2386 : CRED_USE_KERBEROS_REQUIRED,
2387 : CRED_SPECIFIED);
2388 :
2389 0 : nt_status = cli_full_connection_creds(&cli, lp_netbios_name(), servername,
2390 : &server_ss, 0,
2391 : "IPC$", "IPC",
2392 : c->creds,
2393 : CLI_FULL_CONNECTION_IPC);
2394 :
2395 0 : if (NT_STATUS_IS_ERR(nt_status)) {
2396 0 : d_fprintf(stderr, _("Unable to open a connection to %s to "
2397 : "obtain data for %s\n"),
2398 : servername, printername);
2399 0 : goto out;
2400 : }
2401 :
2402 : /* Publish on AD server */
2403 :
2404 0 : ads_find_machine_acct(ads, &res, servername);
2405 :
2406 0 : if (ads_count_replies(ads, res) == 0) {
2407 0 : d_fprintf(stderr, _("Could not find machine account for server "
2408 : "%s\n"),
2409 : servername);
2410 0 : goto out;
2411 : }
2412 :
2413 0 : srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
2414 0 : srv_cn = ldap_explode_dn(srv_dn, 1);
2415 :
2416 0 : srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
2417 0 : printername_escaped = escape_rdn_val_string_alloc(printername);
2418 0 : if (!srv_cn_escaped || !printername_escaped) {
2419 0 : SAFE_FREE(srv_cn_escaped);
2420 0 : SAFE_FREE(printername_escaped);
2421 0 : d_fprintf(stderr, _("Internal error, out of memory!"));
2422 0 : goto out;
2423 : }
2424 :
2425 0 : prt_dn = talloc_asprintf(tmp_ctx,
2426 : "cn=%s-%s,%s",
2427 : srv_cn_escaped,
2428 : printername_escaped,
2429 : srv_dn);
2430 0 : if (prt_dn == NULL) {
2431 0 : SAFE_FREE(srv_cn_escaped);
2432 0 : SAFE_FREE(printername_escaped);
2433 0 : d_fprintf(stderr, _("Internal error, out of memory!"));
2434 0 : goto out;
2435 : }
2436 :
2437 0 : SAFE_FREE(srv_cn_escaped);
2438 0 : SAFE_FREE(printername_escaped);
2439 :
2440 0 : nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd);
2441 0 : if (!NT_STATUS_IS_OK(nt_status)) {
2442 0 : d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
2443 : servername);
2444 0 : goto out;
2445 : }
2446 :
2447 0 : if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd,
2448 : tmp_ctx,
2449 : &mods,
2450 : printername))) {
2451 0 : goto out;
2452 : }
2453 :
2454 0 : status = ads_add_printer_entry(ads, prt_dn, tmp_ctx, &mods);
2455 0 : if (!ADS_ERR_OK(status)) {
2456 0 : d_fprintf(stderr, "ads_publish_printer: %s\n",
2457 : ads_errstr(status));
2458 0 : goto out;
2459 : }
2460 :
2461 0 : d_printf("published printer\n");
2462 :
2463 0 : ret = 0;
2464 0 : out:
2465 0 : talloc_destroy(tmp_ctx);
2466 :
2467 0 : return ret;
2468 : }
2469 :
2470 0 : static int net_ads_printer_remove(struct net_context *c,
2471 : int argc,
2472 : const char **argv)
2473 : {
2474 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2475 0 : ADS_STRUCT *ads = NULL;
2476 0 : ADS_STATUS status;
2477 0 : const char *servername = NULL;
2478 0 : char *prt_dn = NULL;
2479 0 : LDAPMessage *res = NULL;
2480 0 : int ret = -1;
2481 :
2482 0 : if (argc < 1 || c->display_usage) {
2483 0 : d_printf("%s\n%s",
2484 : _("Usage:"),
2485 : _("net ads printer remove <printername> [servername]\n"
2486 : " Remove a printer from the AD\n"
2487 : " printername\tName of the printer\n"
2488 : " servername\tName of the print server\n"));
2489 0 : TALLOC_FREE(tmp_ctx);
2490 0 : return -1;
2491 : }
2492 :
2493 0 : status = ads_startup(c, true, tmp_ctx, &ads);
2494 0 : if (!ADS_ERR_OK(status)) {
2495 0 : goto out;
2496 : }
2497 :
2498 0 : if (argc > 1) {
2499 0 : servername = argv[1];
2500 : } else {
2501 0 : servername = lp_netbios_name();
2502 : }
2503 :
2504 0 : status = ads_find_printer_on_server(ads, &res, argv[0], servername);
2505 0 : if (!ADS_ERR_OK(status)) {
2506 0 : d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"),
2507 : ads_errstr(status));
2508 0 : goto out;
2509 : }
2510 :
2511 0 : if (ads_count_replies(ads, res) == 0) {
2512 0 : d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
2513 0 : goto out;
2514 : }
2515 :
2516 0 : prt_dn = ads_get_dn(ads, tmp_ctx, res);
2517 0 : if (prt_dn == NULL) {
2518 0 : d_fprintf(stderr, _("Out of memory\n"));
2519 0 : goto out;
2520 : }
2521 :
2522 0 : status = ads_del_dn(ads, prt_dn);
2523 0 : if (!ADS_ERR_OK(status)) {
2524 0 : d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(status));
2525 0 : goto out;
2526 : }
2527 :
2528 0 : ret = 0;
2529 0 : out:
2530 0 : ads_msgfree(ads, res);
2531 0 : TALLOC_FREE(tmp_ctx);
2532 0 : return ret;
2533 : }
2534 :
2535 0 : static int net_ads_printer(struct net_context *c, int argc, const char **argv)
2536 : {
2537 0 : struct functable func[] = {
2538 : {
2539 : "search",
2540 : net_ads_printer_search,
2541 : NET_TRANSPORT_ADS,
2542 : N_("Search for a printer"),
2543 : N_("net ads printer search\n"
2544 : " Search for a printer")
2545 : },
2546 : {
2547 : "info",
2548 : net_ads_printer_info,
2549 : NET_TRANSPORT_ADS,
2550 : N_("Display printer information"),
2551 : N_("net ads printer info\n"
2552 : " Display printer information")
2553 : },
2554 : {
2555 : "publish",
2556 : net_ads_printer_publish,
2557 : NET_TRANSPORT_ADS,
2558 : N_("Publish a printer"),
2559 : N_("net ads printer publish\n"
2560 : " Publish a printer")
2561 : },
2562 : {
2563 : "remove",
2564 : net_ads_printer_remove,
2565 : NET_TRANSPORT_ADS,
2566 : N_("Delete a printer"),
2567 : N_("net ads printer remove\n"
2568 : " Delete a printer")
2569 : },
2570 : {NULL, NULL, 0, NULL, NULL}
2571 : };
2572 :
2573 0 : return net_run_function(c, argc, argv, "net ads printer", func);
2574 : }
2575 :
2576 :
2577 4 : static int net_ads_password(struct net_context *c, int argc, const char **argv)
2578 : {
2579 4 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2580 4 : ADS_STRUCT *ads = NULL;
2581 4 : const char *auth_principal = cli_credentials_get_username(c->creds);
2582 4 : const char *auth_password = cli_credentials_get_password(c->creds);
2583 4 : const char *realm = NULL;
2584 4 : char *new_password = NULL;
2585 4 : char *chr = NULL;
2586 4 : char *prompt = NULL;
2587 4 : const char *user = NULL;
2588 4 : char pwd[256] = {0};
2589 0 : ADS_STATUS status;
2590 4 : int ret = 0;
2591 :
2592 4 : if (c->display_usage) {
2593 0 : d_printf("%s\n%s",
2594 : _("Usage:"),
2595 : _("net ads password <username>\n"
2596 : " Change password for user\n"
2597 : " username\tName of user to change password for\n"));
2598 0 : TALLOC_FREE(tmp_ctx);
2599 0 : return -1;
2600 : }
2601 :
2602 4 : if (auth_principal == NULL || auth_password == NULL) {
2603 0 : d_fprintf(stderr, _("You must supply an administrator "
2604 : "username/password\n"));
2605 0 : TALLOC_FREE(tmp_ctx);
2606 0 : return -1;
2607 : }
2608 :
2609 4 : if (argc < 1) {
2610 0 : d_fprintf(stderr, _("ERROR: You must say which username to "
2611 : "change password for\n"));
2612 0 : TALLOC_FREE(tmp_ctx);
2613 0 : return -1;
2614 : }
2615 :
2616 4 : if (strchr_m(argv[0], '@')) {
2617 4 : user = talloc_strdup(tmp_ctx, argv[0]);
2618 : } else {
2619 0 : user = talloc_asprintf(tmp_ctx, "%s@%s", argv[0], lp_realm());
2620 : }
2621 4 : if (user == NULL) {
2622 0 : d_fprintf(stderr, _("Out of memory\n"));
2623 0 : goto out;
2624 : }
2625 :
2626 4 : use_in_memory_ccache();
2627 4 : chr = strchr_m(auth_principal, '@');
2628 4 : if (chr) {
2629 4 : realm = ++chr;
2630 : } else {
2631 0 : realm = lp_realm();
2632 : }
2633 :
2634 : /* use the realm so we can eventually change passwords for users
2635 : in realms other than default */
2636 4 : ads = ads_init(tmp_ctx,
2637 : realm,
2638 : c->opt_workgroup,
2639 : c->opt_host,
2640 : ADS_SASL_PLAIN);
2641 4 : if (ads == NULL) {
2642 0 : goto out;
2643 : }
2644 :
2645 : /* we don't actually need a full connect, but it's the easy way to
2646 : fill in the KDC's address */
2647 4 : ads_connect(ads);
2648 :
2649 4 : if (!ads->config.realm) {
2650 0 : d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
2651 0 : goto out;
2652 : }
2653 :
2654 4 : if (argv[1] != NULL) {
2655 4 : new_password = talloc_strdup(tmp_ctx, argv[1]);
2656 : } else {
2657 0 : int rc;
2658 :
2659 0 : prompt = talloc_asprintf(tmp_ctx, _("Enter new password for %s:"), user);
2660 0 : if (prompt == NULL) {
2661 0 : d_fprintf(stderr, _("Out of memory\n"));
2662 0 : goto out;
2663 : }
2664 :
2665 0 : rc = samba_getpass(prompt, pwd, sizeof(pwd), false, true);
2666 0 : if (rc < 0) {
2667 0 : goto out;
2668 : }
2669 0 : new_password = talloc_strdup(tmp_ctx, pwd);
2670 0 : memset(pwd, '\0', sizeof(pwd));
2671 : }
2672 :
2673 4 : if (new_password == NULL) {
2674 0 : d_fprintf(stderr, _("Out of memory\n"));
2675 0 : goto out;
2676 : }
2677 :
2678 4 : status = kerberos_set_password(ads->auth.kdc_server,
2679 : auth_principal,
2680 : auth_password,
2681 : user,
2682 : new_password,
2683 : ads->auth.time_offset);
2684 4 : memset(new_password, '\0', strlen(new_password));
2685 4 : if (!ADS_ERR_OK(status)) {
2686 0 : d_fprintf(stderr, _("Password change failed: %s\n"),
2687 : ads_errstr(status));
2688 0 : goto out;
2689 : }
2690 :
2691 4 : d_printf(_("Password change for %s completed.\n"), user);
2692 :
2693 4 : ret = 0;
2694 4 : out:
2695 4 : TALLOC_FREE(tmp_ctx);
2696 4 : return ret;
2697 : }
2698 :
2699 4 : int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2700 : {
2701 4 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2702 4 : ADS_STRUCT *ads = NULL;
2703 4 : char *host_principal = NULL;
2704 4 : char *my_name = NULL;
2705 0 : ADS_STATUS status;
2706 4 : int ret = -1;
2707 :
2708 4 : if (c->display_usage) {
2709 0 : d_printf( "%s\n"
2710 : "net ads changetrustpw\n"
2711 : " %s\n",
2712 : _("Usage:"),
2713 : _("Change the machine account's trust password"));
2714 0 : TALLOC_FREE(tmp_ctx);
2715 0 : return -1;
2716 : }
2717 :
2718 4 : if (!secrets_init()) {
2719 0 : DEBUG(1,("Failed to initialise secrets database\n"));
2720 0 : goto out;
2721 : }
2722 :
2723 4 : net_warn_member_options();
2724 :
2725 4 : net_use_krb_machine_account(c);
2726 :
2727 4 : use_in_memory_ccache();
2728 :
2729 4 : status = ads_startup(c, true, tmp_ctx, &ads);
2730 4 : if (!ADS_ERR_OK(status)) {
2731 0 : goto out;
2732 : }
2733 :
2734 4 : my_name = talloc_asprintf_strlower_m(tmp_ctx, "%s", lp_netbios_name());
2735 4 : if (my_name == NULL) {
2736 0 : d_fprintf(stderr, _("Out of memory\n"));
2737 0 : goto out;
2738 : }
2739 :
2740 4 : host_principal = talloc_asprintf(tmp_ctx, "%s$@%s", my_name, ads->config.realm);
2741 4 : if (host_principal == NULL) {
2742 0 : d_fprintf(stderr, _("Out of memory\n"));
2743 0 : goto out;
2744 : }
2745 :
2746 4 : d_printf(_("Changing password for principal: %s\n"), host_principal);
2747 :
2748 4 : status = ads_change_trust_account_password(ads, host_principal);
2749 4 : if (!ADS_ERR_OK(status)) {
2750 0 : d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(status));
2751 0 : goto out;
2752 : }
2753 :
2754 4 : d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2755 :
2756 4 : if (USE_SYSTEM_KEYTAB) {
2757 0 : d_printf(_("Attempting to update system keytab with new password.\n"));
2758 0 : if (ads_keytab_create_default(ads)) {
2759 0 : d_printf(_("Failed to update system keytab.\n"));
2760 : }
2761 : }
2762 :
2763 4 : ret = 0;
2764 4 : out:
2765 4 : TALLOC_FREE(tmp_ctx);
2766 :
2767 4 : return ret;
2768 : }
2769 :
2770 : /*
2771 : help for net ads search
2772 : */
2773 0 : static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2774 : {
2775 0 : d_printf(_(
2776 : "\nnet ads search <expression> <attributes...>\n"
2777 : "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2778 : "The expression is a standard LDAP search expression, and the\n"
2779 : "attributes are a list of LDAP fields to show in the results.\n\n"
2780 : "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2781 : ));
2782 0 : net_common_flags_usage(c, argc, argv);
2783 0 : return -1;
2784 : }
2785 :
2786 :
2787 : /*
2788 : general ADS search function. Useful in diagnosing problems in ADS
2789 : */
2790 34 : static int net_ads_search(struct net_context *c, int argc, const char **argv)
2791 : {
2792 34 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2793 34 : ADS_STRUCT *ads = NULL;
2794 0 : ADS_STATUS status;
2795 34 : const char *ldap_exp = NULL;
2796 34 : const char **attrs = NULL;
2797 34 : LDAPMessage *res = NULL;
2798 34 : int ret = -1;
2799 :
2800 34 : if (argc < 1 || c->display_usage) {
2801 0 : TALLOC_FREE(tmp_ctx);
2802 0 : return net_ads_search_usage(c, argc, argv);
2803 : }
2804 :
2805 34 : status = ads_startup(c, false, tmp_ctx, &ads);
2806 34 : if (!ADS_ERR_OK(status)) {
2807 1 : goto out;
2808 : }
2809 :
2810 33 : ldap_exp = argv[0];
2811 33 : attrs = (argv + 1);
2812 :
2813 33 : status = ads_do_search_retry(ads,
2814 33 : ads->config.bind_path,
2815 : LDAP_SCOPE_SUBTREE,
2816 : ldap_exp,
2817 : attrs,
2818 : &res);
2819 33 : if (!ADS_ERR_OK(status)) {
2820 0 : d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2821 0 : goto out;
2822 : }
2823 :
2824 33 : d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2825 :
2826 : /* dump the results */
2827 33 : ads_dump(ads, res);
2828 :
2829 33 : ret = 0;
2830 34 : out:
2831 34 : ads_msgfree(ads, res);
2832 34 : TALLOC_FREE(tmp_ctx);
2833 34 : return ret;
2834 : }
2835 :
2836 :
2837 : /*
2838 : help for net ads search
2839 : */
2840 0 : static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2841 : {
2842 0 : d_printf(_(
2843 : "\nnet ads dn <dn> <attributes...>\n"
2844 : "\nperform a raw LDAP search on a ADS server and dump the results\n"
2845 : "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2846 : "to show in the results\n\n"
2847 : "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2848 : "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2849 : ));
2850 0 : net_common_flags_usage(c, argc, argv);
2851 0 : return -1;
2852 : }
2853 :
2854 :
2855 : /*
2856 : general ADS search function. Useful in diagnosing problems in ADS
2857 : */
2858 0 : static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2859 : {
2860 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2861 0 : ADS_STRUCT *ads = NULL;
2862 0 : ADS_STATUS status;
2863 0 : const char *dn = NULL;
2864 0 : const char **attrs = NULL;
2865 0 : LDAPMessage *res = NULL;
2866 0 : int ret = -1;
2867 :
2868 0 : if (argc < 1 || c->display_usage) {
2869 0 : TALLOC_FREE(tmp_ctx);
2870 0 : return net_ads_dn_usage(c, argc, argv);
2871 : }
2872 :
2873 0 : status = ads_startup(c, false, tmp_ctx, &ads);
2874 0 : if (!ADS_ERR_OK(status)) {
2875 0 : goto out;
2876 : }
2877 :
2878 0 : dn = argv[0];
2879 0 : attrs = (argv + 1);
2880 :
2881 0 : status = ads_do_search_all(ads,
2882 : dn,
2883 : LDAP_SCOPE_BASE,
2884 : "(objectclass=*)",
2885 : attrs,
2886 : &res);
2887 0 : if (!ADS_ERR_OK(status)) {
2888 0 : d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2889 0 : goto out;
2890 : }
2891 :
2892 0 : d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2893 :
2894 : /* dump the results */
2895 0 : ads_dump(ads, res);
2896 :
2897 0 : ret = 0;
2898 0 : out:
2899 0 : ads_msgfree(ads, res);
2900 0 : TALLOC_FREE(tmp_ctx);
2901 0 : return ret;
2902 : }
2903 :
2904 : /*
2905 : help for net ads sid search
2906 : */
2907 0 : static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2908 : {
2909 0 : d_printf(_(
2910 : "\nnet ads sid <sid> <attributes...>\n"
2911 : "\nperform a raw LDAP search on a ADS server and dump the results\n"
2912 : "The SID is in string format, and the attributes are a list of LDAP fields \n"
2913 : "to show in the results\n\n"
2914 : "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2915 : ));
2916 0 : net_common_flags_usage(c, argc, argv);
2917 0 : return -1;
2918 : }
2919 :
2920 :
2921 : /*
2922 : general ADS search function. Useful in diagnosing problems in ADS
2923 : */
2924 0 : static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2925 : {
2926 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2927 0 : ADS_STRUCT *ads = NULL;
2928 0 : ADS_STATUS status;
2929 0 : const char *sid_string = NULL;
2930 0 : const char **attrs = NULL;
2931 0 : LDAPMessage *res = NULL;
2932 0 : struct dom_sid sid = { 0 };
2933 0 : int ret = -1;
2934 :
2935 0 : if (argc < 1 || c->display_usage) {
2936 0 : TALLOC_FREE(tmp_ctx);
2937 0 : return net_ads_sid_usage(c, argc, argv);
2938 : }
2939 :
2940 0 : status = ads_startup(c, false, tmp_ctx, &ads);
2941 0 : if (!ADS_ERR_OK(status)) {
2942 0 : goto out;
2943 : }
2944 :
2945 0 : sid_string = argv[0];
2946 0 : attrs = (argv + 1);
2947 :
2948 0 : if (!string_to_sid(&sid, sid_string)) {
2949 0 : d_fprintf(stderr, _("could not convert sid\n"));
2950 0 : goto out;
2951 : }
2952 :
2953 0 : status = ads_search_retry_sid(ads, &res, &sid, attrs);
2954 0 : if (!ADS_ERR_OK(status)) {
2955 0 : d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2956 0 : goto out;
2957 : }
2958 :
2959 0 : d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2960 :
2961 : /* dump the results */
2962 0 : ads_dump(ads, res);
2963 :
2964 0 : ret = 0;
2965 0 : out:
2966 0 : ads_msgfree(ads, res);
2967 0 : TALLOC_FREE(tmp_ctx);
2968 0 : return ret;
2969 : }
2970 :
2971 0 : static int net_ads_keytab_flush(struct net_context *c,
2972 : int argc,
2973 : const char **argv)
2974 : {
2975 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2976 0 : ADS_STRUCT *ads = NULL;
2977 0 : ADS_STATUS status;
2978 0 : int ret = -1;
2979 :
2980 0 : if (c->display_usage) {
2981 0 : d_printf( "%s\n"
2982 : "net ads keytab flush\n"
2983 : " %s\n",
2984 : _("Usage:"),
2985 : _("Delete the whole keytab"));
2986 0 : TALLOC_FREE(tmp_ctx);
2987 0 : return -1;
2988 : }
2989 :
2990 0 : if (!c->opt_user_specified && c->opt_password == NULL) {
2991 0 : net_use_krb_machine_account(c);
2992 : }
2993 :
2994 0 : status = ads_startup(c, true, tmp_ctx, &ads);
2995 0 : if (!ADS_ERR_OK(status)) {
2996 0 : goto out;
2997 : }
2998 :
2999 0 : ret = ads_keytab_flush(ads);
3000 0 : out:
3001 0 : TALLOC_FREE(tmp_ctx);
3002 0 : return ret;
3003 : }
3004 :
3005 16 : static int net_ads_keytab_add(struct net_context *c,
3006 : int argc,
3007 : const char **argv,
3008 : bool update_ads)
3009 : {
3010 16 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3011 16 : ADS_STRUCT *ads = NULL;
3012 0 : ADS_STATUS status;
3013 0 : int i;
3014 16 : int ret = -1;
3015 :
3016 16 : if (c->display_usage) {
3017 0 : d_printf("%s\n%s",
3018 : _("Usage:"),
3019 : _("net ads keytab add <principal> [principal ...]\n"
3020 : " Add principals to local keytab\n"
3021 : " principal\tKerberos principal to add to "
3022 : "keytab\n"));
3023 0 : TALLOC_FREE(tmp_ctx);
3024 0 : return -1;
3025 : }
3026 :
3027 16 : net_warn_member_options();
3028 :
3029 16 : d_printf(_("Processing principals to add...\n"));
3030 :
3031 16 : if (!c->opt_user_specified && c->opt_password == NULL) {
3032 0 : net_use_krb_machine_account(c);
3033 : }
3034 :
3035 16 : status = ads_startup(c, true, tmp_ctx, &ads);
3036 16 : if (!ADS_ERR_OK(status)) {
3037 0 : goto out;
3038 : }
3039 :
3040 32 : for (ret = 0, i = 0; i < argc; i++) {
3041 16 : ret |= ads_keytab_add_entry(ads, argv[i], update_ads);
3042 : }
3043 16 : out:
3044 16 : TALLOC_FREE(tmp_ctx);
3045 16 : return ret;
3046 : }
3047 :
3048 14 : static int net_ads_keytab_add_default(struct net_context *c,
3049 : int argc,
3050 : const char **argv)
3051 : {
3052 14 : return net_ads_keytab_add(c, argc, argv, false);
3053 : }
3054 :
3055 2 : static int net_ads_keytab_add_update_ads(struct net_context *c,
3056 : int argc,
3057 : const char **argv)
3058 : {
3059 2 : return net_ads_keytab_add(c, argc, argv, true);
3060 : }
3061 :
3062 12 : static int net_ads_keytab_delete(struct net_context *c,
3063 : int argc,
3064 : const char **argv)
3065 : {
3066 12 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3067 12 : ADS_STRUCT *ads = NULL;
3068 0 : ADS_STATUS status;
3069 0 : int i;
3070 12 : int ret = -1;
3071 :
3072 12 : if (c->display_usage) {
3073 0 : d_printf("%s\n%s",
3074 : _("Usage:"),
3075 : _("net ads keytab delete <principal> [principal ...]\n"
3076 : " Remove entries for service principal, "
3077 : " from the keytab file only."
3078 : " Remove principals from local keytab\n"
3079 : " principal\tKerberos principal to remove from "
3080 : "keytab\n"));
3081 0 : TALLOC_FREE(tmp_ctx);
3082 0 : return -1;
3083 : }
3084 :
3085 12 : d_printf(_("Processing principals to delete...\n"));
3086 :
3087 12 : if (!c->opt_user_specified && c->opt_password == NULL) {
3088 0 : net_use_krb_machine_account(c);
3089 : }
3090 :
3091 12 : status = ads_startup(c, true, tmp_ctx, &ads);
3092 12 : if (!ADS_ERR_OK(status)) {
3093 0 : goto out;
3094 : }
3095 :
3096 24 : for (ret = 0, i = 0; i < argc; i++) {
3097 12 : ret |= ads_keytab_delete_entry(ads, argv[i]);
3098 : }
3099 12 : out:
3100 12 : TALLOC_FREE(tmp_ctx);
3101 12 : return ret;
3102 : }
3103 :
3104 8 : static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
3105 : {
3106 8 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3107 8 : ADS_STRUCT *ads = NULL;
3108 0 : ADS_STATUS status;
3109 8 : int ret = -1;
3110 :
3111 8 : if (c->display_usage) {
3112 0 : d_printf( "%s\n"
3113 : "net ads keytab create\n"
3114 : " %s\n",
3115 : _("Usage:"),
3116 : _("Create new default keytab"));
3117 0 : TALLOC_FREE(tmp_ctx);
3118 0 : return -1;
3119 : }
3120 :
3121 8 : net_warn_member_options();
3122 :
3123 8 : if (!c->opt_user_specified && c->opt_password == NULL) {
3124 6 : net_use_krb_machine_account(c);
3125 : }
3126 :
3127 8 : status = ads_startup(c, true, tmp_ctx, &ads);
3128 8 : if (!ADS_ERR_OK(status)) {
3129 0 : goto out;
3130 : }
3131 :
3132 8 : ret = ads_keytab_create_default(ads);
3133 8 : out:
3134 8 : TALLOC_FREE(tmp_ctx);
3135 8 : return ret;
3136 : }
3137 :
3138 42 : static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
3139 : {
3140 42 : const char *keytab = NULL;
3141 :
3142 42 : if (c->display_usage) {
3143 0 : d_printf("%s\n%s",
3144 : _("Usage:"),
3145 : _("net ads keytab list [keytab]\n"
3146 : " List a local keytab\n"
3147 : " keytab\tKeytab to list\n"));
3148 0 : return -1;
3149 : }
3150 :
3151 42 : if (argc >= 1) {
3152 2 : keytab = argv[0];
3153 : }
3154 :
3155 42 : return ads_keytab_list(keytab);
3156 : }
3157 :
3158 :
3159 78 : int net_ads_keytab(struct net_context *c, int argc, const char **argv)
3160 : {
3161 78 : struct functable func[] = {
3162 : {
3163 : "add",
3164 : net_ads_keytab_add_default,
3165 : NET_TRANSPORT_ADS,
3166 : N_("Add a service principal"),
3167 : N_("net ads keytab add\n"
3168 : " Add a service principal, updates keytab file only.")
3169 : },
3170 : {
3171 : "delete",
3172 : net_ads_keytab_delete,
3173 : NET_TRANSPORT_ADS,
3174 : N_("Delete a service principal"),
3175 : N_("net ads keytab delete\n"
3176 : " Remove entries for service principal, from the keytab file only.")
3177 : },
3178 : {
3179 : "add_update_ads",
3180 : net_ads_keytab_add_update_ads,
3181 : NET_TRANSPORT_ADS,
3182 : N_("Add a service principal"),
3183 : N_("net ads keytab add_update_ads\n"
3184 : " Add a service principal, depending on the param passed may update ADS computer object in addition to the keytab file.")
3185 : },
3186 : {
3187 : "create",
3188 : net_ads_keytab_create,
3189 : NET_TRANSPORT_ADS,
3190 : N_("Create a fresh keytab"),
3191 : N_("net ads keytab create\n"
3192 : " Create a fresh keytab or update existing one.")
3193 : },
3194 : {
3195 : "flush",
3196 : net_ads_keytab_flush,
3197 : NET_TRANSPORT_ADS,
3198 : N_("Remove all keytab entries"),
3199 : N_("net ads keytab flush\n"
3200 : " Remove all keytab entries")
3201 : },
3202 : {
3203 : "list",
3204 : net_ads_keytab_list,
3205 : NET_TRANSPORT_ADS,
3206 : N_("List a keytab"),
3207 : N_("net ads keytab list\n"
3208 : " List a keytab")
3209 : },
3210 : {NULL, NULL, 0, NULL, NULL}
3211 : };
3212 :
3213 78 : if (!USE_KERBEROS_KEYTAB) {
3214 2 : d_printf(_("\nWarning: \"kerberos method\" must be set to a "
3215 : "keytab method to use keytab functions.\n"));
3216 : }
3217 :
3218 78 : return net_run_function(c, argc, argv, "net ads keytab", func);
3219 : }
3220 :
3221 0 : static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
3222 : {
3223 0 : int ret = -1;
3224 :
3225 0 : if (c->display_usage) {
3226 0 : d_printf( "%s\n"
3227 : "net ads kerberos renew\n"
3228 : " %s\n",
3229 : _("Usage:"),
3230 : _("Renew TGT from existing credential cache"));
3231 0 : return -1;
3232 : }
3233 :
3234 0 : ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
3235 0 : if (ret) {
3236 0 : d_printf(_("failed to renew kerberos ticket: %s\n"),
3237 : error_message(ret));
3238 : }
3239 0 : return ret;
3240 : }
3241 :
3242 0 : static int net_ads_kerberos_pac_common(struct net_context *c, int argc, const char **argv,
3243 : struct PAC_DATA_CTR **pac_data_ctr)
3244 : {
3245 0 : NTSTATUS status;
3246 0 : int ret = -1;
3247 0 : const char *impersonate_princ_s = NULL;
3248 0 : const char *local_service = NULL;
3249 0 : int i;
3250 :
3251 0 : for (i=0; i<argc; i++) {
3252 0 : if (strnequal(argv[i], "impersonate", strlen("impersonate"))) {
3253 0 : impersonate_princ_s = get_string_param(argv[i]);
3254 0 : if (impersonate_princ_s == NULL) {
3255 0 : return -1;
3256 : }
3257 : }
3258 0 : if (strnequal(argv[i], "local_service", strlen("local_service"))) {
3259 0 : local_service = get_string_param(argv[i]);
3260 0 : if (local_service == NULL) {
3261 0 : return -1;
3262 : }
3263 : }
3264 : }
3265 :
3266 0 : if (local_service == NULL) {
3267 0 : local_service = talloc_asprintf(c, "%s$@%s",
3268 : lp_netbios_name(), lp_realm());
3269 0 : if (local_service == NULL) {
3270 0 : goto out;
3271 : }
3272 : }
3273 :
3274 0 : c->opt_password = net_prompt_pass(c, c->opt_user_name);
3275 :
3276 0 : status = kerberos_return_pac(c,
3277 : c->opt_user_name,
3278 : c->opt_password,
3279 : 0,
3280 : NULL,
3281 : NULL,
3282 : NULL,
3283 : true,
3284 : true,
3285 : 2592000, /* one month */
3286 : impersonate_princ_s,
3287 : local_service,
3288 : NULL,
3289 : NULL,
3290 : pac_data_ctr);
3291 0 : if (!NT_STATUS_IS_OK(status)) {
3292 0 : d_printf(_("failed to query kerberos PAC: %s\n"),
3293 : nt_errstr(status));
3294 0 : goto out;
3295 : }
3296 :
3297 0 : ret = 0;
3298 0 : out:
3299 0 : return ret;
3300 : }
3301 :
3302 0 : static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv)
3303 : {
3304 0 : struct PAC_DATA_CTR *pac_data_ctr = NULL;
3305 0 : int i, num_buffers;
3306 0 : int ret = -1;
3307 0 : enum PAC_TYPE type = 0;
3308 :
3309 0 : if (c->display_usage) {
3310 0 : d_printf( "%s\n"
3311 : "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
3312 : " %s\n",
3313 : _("Usage:"),
3314 : _("Dump the Kerberos PAC"));
3315 0 : return -1;
3316 : }
3317 :
3318 0 : for (i=0; i<argc; i++) {
3319 0 : if (strnequal(argv[i], "pac_buffer_type", strlen("pac_buffer_type"))) {
3320 0 : type = get_int_param(argv[i]);
3321 : }
3322 : }
3323 :
3324 0 : ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3325 0 : if (ret) {
3326 0 : return ret;
3327 : }
3328 :
3329 0 : if (type == 0) {
3330 :
3331 0 : char *s = NULL;
3332 :
3333 0 : s = NDR_PRINT_STRUCT_STRING(c, PAC_DATA,
3334 : pac_data_ctr->pac_data);
3335 0 : if (s != NULL) {
3336 0 : d_printf(_("The Pac: %s\n"), s);
3337 0 : talloc_free(s);
3338 : }
3339 :
3340 0 : return 0;
3341 : }
3342 :
3343 0 : num_buffers = pac_data_ctr->pac_data->num_buffers;
3344 :
3345 0 : for (i=0; i<num_buffers; i++) {
3346 :
3347 0 : char *s = NULL;
3348 :
3349 0 : if (pac_data_ctr->pac_data->buffers[i].type != type) {
3350 0 : continue;
3351 : }
3352 :
3353 0 : s = NDR_PRINT_UNION_STRING(c, PAC_INFO, type,
3354 : pac_data_ctr->pac_data->buffers[i].info);
3355 0 : if (s != NULL) {
3356 0 : d_printf(_("The Pac: %s\n"), s);
3357 0 : talloc_free(s);
3358 : }
3359 0 : break;
3360 : }
3361 :
3362 0 : return 0;
3363 : }
3364 :
3365 0 : static int net_ads_kerberos_pac_save(struct net_context *c, int argc, const char **argv)
3366 : {
3367 0 : struct PAC_DATA_CTR *pac_data_ctr = NULL;
3368 0 : char *filename = NULL;
3369 0 : int ret = -1;
3370 0 : int i;
3371 :
3372 0 : if (c->display_usage) {
3373 0 : d_printf( "%s\n"
3374 : "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
3375 : " %s\n",
3376 : _("Usage:"),
3377 : _("Save the Kerberos PAC"));
3378 0 : return -1;
3379 : }
3380 :
3381 0 : for (i=0; i<argc; i++) {
3382 0 : if (strnequal(argv[i], "filename", strlen("filename"))) {
3383 0 : filename = get_string_param(argv[i]);
3384 0 : if (filename == NULL) {
3385 0 : return -1;
3386 : }
3387 : }
3388 : }
3389 :
3390 0 : ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3391 0 : if (ret) {
3392 0 : return ret;
3393 : }
3394 :
3395 0 : if (filename == NULL) {
3396 0 : d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
3397 0 : return -1;
3398 : }
3399 :
3400 : /* save the raw format */
3401 0 : if (!file_save(filename, pac_data_ctr->pac_blob.data, pac_data_ctr->pac_blob.length)) {
3402 0 : d_printf(_("failed to save PAC in %s\n"), filename);
3403 0 : return -1;
3404 : }
3405 :
3406 0 : return 0;
3407 : }
3408 :
3409 0 : static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
3410 : {
3411 0 : struct functable func[] = {
3412 : {
3413 : "dump",
3414 : net_ads_kerberos_pac_dump,
3415 : NET_TRANSPORT_ADS,
3416 : N_("Dump Kerberos PAC"),
3417 : N_("net ads kerberos pac dump\n"
3418 : " Dump a Kerberos PAC to stdout")
3419 : },
3420 : {
3421 : "save",
3422 : net_ads_kerberos_pac_save,
3423 : NET_TRANSPORT_ADS,
3424 : N_("Save Kerberos PAC"),
3425 : N_("net ads kerberos pac save\n"
3426 : " Save a Kerberos PAC in a file")
3427 : },
3428 :
3429 : {NULL, NULL, 0, NULL, NULL}
3430 : };
3431 :
3432 0 : return net_run_function(c, argc, argv, "net ads kerberos pac", func);
3433 : }
3434 :
3435 0 : static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
3436 : {
3437 0 : int ret = -1;
3438 0 : NTSTATUS status;
3439 :
3440 0 : if (c->display_usage) {
3441 0 : d_printf( "%s\n"
3442 : "net ads kerberos kinit\n"
3443 : " %s\n",
3444 : _("Usage:"),
3445 : _("Get Ticket Granting Ticket (TGT) for the user"));
3446 0 : return -1;
3447 : }
3448 :
3449 0 : c->opt_password = net_prompt_pass(c, c->opt_user_name);
3450 :
3451 0 : ret = kerberos_kinit_password_ext(c->opt_user_name,
3452 : c->opt_password,
3453 : 0,
3454 : NULL,
3455 : NULL,
3456 : NULL,
3457 : true,
3458 : true,
3459 : 2592000, /* one month */
3460 : NULL,
3461 : NULL,
3462 : NULL,
3463 : &status);
3464 0 : if (ret) {
3465 0 : d_printf(_("failed to kinit password: %s\n"),
3466 : nt_errstr(status));
3467 : }
3468 0 : return ret;
3469 : }
3470 :
3471 0 : int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3472 : {
3473 0 : struct functable func[] = {
3474 : {
3475 : "kinit",
3476 : net_ads_kerberos_kinit,
3477 : NET_TRANSPORT_ADS,
3478 : N_("Retrieve Ticket Granting Ticket (TGT)"),
3479 : N_("net ads kerberos kinit\n"
3480 : " Receive Ticket Granting Ticket (TGT)")
3481 : },
3482 : {
3483 : "renew",
3484 : net_ads_kerberos_renew,
3485 : NET_TRANSPORT_ADS,
3486 : N_("Renew Ticket Granting Ticket from credential cache"),
3487 : N_("net ads kerberos renew\n"
3488 : " Renew Ticket Granting Ticket (TGT) from "
3489 : "credential cache")
3490 : },
3491 : {
3492 : "pac",
3493 : net_ads_kerberos_pac,
3494 : NET_TRANSPORT_ADS,
3495 : N_("Dump Kerberos PAC"),
3496 : N_("net ads kerberos pac\n"
3497 : " Dump Kerberos PAC")
3498 : },
3499 : {NULL, NULL, 0, NULL, NULL}
3500 : };
3501 :
3502 0 : return net_run_function(c, argc, argv, "net ads kerberos", func);
3503 : }
3504 :
3505 16 : static int net_ads_setspn_list(struct net_context *c,
3506 : int argc,
3507 : const char **argv)
3508 : {
3509 16 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3510 16 : ADS_STRUCT *ads = NULL;
3511 0 : ADS_STATUS status;
3512 16 : bool ok = false;
3513 16 : int ret = -1;
3514 :
3515 16 : if (c->display_usage) {
3516 0 : d_printf("%s\n%s",
3517 : _("Usage:"),
3518 : _("net ads setspn list <machinename>\n"));
3519 0 : TALLOC_FREE(tmp_ctx);
3520 0 : return -1;
3521 : }
3522 :
3523 16 : status = ads_startup(c, true, tmp_ctx, &ads);
3524 16 : if (!ADS_ERR_OK(status)) {
3525 0 : goto out;
3526 : }
3527 :
3528 16 : if (argc) {
3529 2 : ok = ads_setspn_list(ads, argv[0]);
3530 : } else {
3531 14 : ok = ads_setspn_list(ads, lp_netbios_name());
3532 : }
3533 :
3534 16 : ret = ok ? 0 : -1;
3535 16 : out:
3536 16 : TALLOC_FREE(tmp_ctx);
3537 16 : return ret;
3538 : }
3539 :
3540 6 : static int net_ads_setspn_add(struct net_context *c, int argc, const char **argv)
3541 : {
3542 6 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3543 6 : ADS_STRUCT *ads = NULL;
3544 0 : ADS_STATUS status;
3545 6 : bool ok = false;
3546 6 : int ret = -1;
3547 :
3548 6 : if (c->display_usage || argc < 1) {
3549 0 : d_printf("%s\n%s",
3550 : _("Usage:"),
3551 : _("net ads setspn add <machinename> SPN\n"));
3552 0 : TALLOC_FREE(tmp_ctx);
3553 0 : return -1;
3554 : }
3555 :
3556 6 : status = ads_startup(c, true, tmp_ctx, &ads);
3557 6 : if (!ADS_ERR_OK(status)) {
3558 0 : goto out;
3559 : }
3560 :
3561 6 : if (argc > 1) {
3562 0 : ok = ads_setspn_add(ads, argv[0], argv[1]);
3563 : } else {
3564 6 : ok = ads_setspn_add(ads, lp_netbios_name(), argv[0]);
3565 : }
3566 :
3567 6 : ret = ok ? 0 : -1;
3568 6 : out:
3569 6 : TALLOC_FREE(tmp_ctx);
3570 6 : return ret;
3571 : }
3572 :
3573 2 : static int net_ads_setspn_delete(struct net_context *c, int argc, const char **argv)
3574 : {
3575 2 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3576 2 : ADS_STRUCT *ads = NULL;
3577 0 : ADS_STATUS status;
3578 2 : bool ok = false;
3579 2 : int ret = -1;
3580 :
3581 2 : if (c->display_usage || argc < 1) {
3582 0 : d_printf("%s\n%s",
3583 : _("Usage:"),
3584 : _("net ads setspn delete <machinename> SPN\n"));
3585 0 : TALLOC_FREE(tmp_ctx);
3586 0 : return -1;
3587 : }
3588 :
3589 2 : status = ads_startup(c, true, tmp_ctx, &ads);
3590 2 : if (!ADS_ERR_OK(status)) {
3591 0 : goto out;
3592 : }
3593 :
3594 2 : if (argc > 1) {
3595 0 : ok = ads_setspn_delete(ads, argv[0], argv[1]);
3596 : } else {
3597 2 : ok = ads_setspn_delete(ads, lp_netbios_name(), argv[0]);
3598 : }
3599 :
3600 2 : ret = ok ? 0 : -1;
3601 2 : out:
3602 2 : TALLOC_FREE(tmp_ctx);
3603 2 : return ret;
3604 : }
3605 :
3606 24 : int net_ads_setspn(struct net_context *c, int argc, const char **argv)
3607 : {
3608 24 : struct functable func[] = {
3609 : {
3610 : "list",
3611 : net_ads_setspn_list,
3612 : NET_TRANSPORT_ADS,
3613 : N_("List Service Principal Names (SPN)"),
3614 : N_("net ads setspn list machine\n"
3615 : " List Service Principal Names (SPN)")
3616 : },
3617 : {
3618 : "add",
3619 : net_ads_setspn_add,
3620 : NET_TRANSPORT_ADS,
3621 : N_("Add Service Principal Names (SPN)"),
3622 : N_("net ads setspn add machine spn\n"
3623 : " Add Service Principal Names (SPN)")
3624 : },
3625 : {
3626 : "delete",
3627 : net_ads_setspn_delete,
3628 : NET_TRANSPORT_ADS,
3629 : N_("Delete Service Principal Names (SPN)"),
3630 : N_("net ads setspn delete machine spn\n"
3631 : " Delete Service Principal Names (SPN)")
3632 : },
3633 : {NULL, NULL, 0, NULL, NULL}
3634 : };
3635 :
3636 24 : return net_run_function(c, argc, argv, "net ads setspn", func);
3637 : }
3638 :
3639 0 : static int net_ads_enctype_lookup_account(struct net_context *c,
3640 : ADS_STRUCT *ads,
3641 : const char *account,
3642 : LDAPMessage **res,
3643 : const char **enctype_str)
3644 : {
3645 0 : const char *filter;
3646 0 : const char *attrs[] = {
3647 : "msDS-SupportedEncryptionTypes",
3648 : NULL
3649 : };
3650 0 : int count;
3651 0 : int ret = -1;
3652 0 : ADS_STATUS status;
3653 :
3654 0 : filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))",
3655 : account);
3656 0 : if (filter == NULL) {
3657 0 : goto done;
3658 : }
3659 :
3660 0 : status = ads_search(ads, res, filter, attrs);
3661 0 : if (!ADS_ERR_OK(status)) {
3662 0 : d_printf(_("no account found with filter: %s\n"), filter);
3663 0 : goto done;
3664 : }
3665 :
3666 0 : count = ads_count_replies(ads, *res);
3667 0 : switch (count) {
3668 0 : case 1:
3669 0 : break;
3670 0 : case 0:
3671 0 : d_printf(_("no account found with filter: %s\n"), filter);
3672 0 : goto done;
3673 0 : default:
3674 0 : d_printf(_("multiple accounts found with filter: %s\n"), filter);
3675 0 : goto done;
3676 : }
3677 :
3678 0 : if (enctype_str) {
3679 0 : *enctype_str = ads_pull_string(ads, c, *res,
3680 : "msDS-SupportedEncryptionTypes");
3681 0 : if (*enctype_str == NULL) {
3682 0 : d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
3683 0 : goto done;
3684 : }
3685 : }
3686 :
3687 0 : ret = 0;
3688 0 : done:
3689 0 : return ret;
3690 : }
3691 :
3692 0 : static void net_ads_enctype_dump_enctypes(const char *username,
3693 : const char *enctype_str)
3694 : {
3695 0 : int enctypes = atoi(enctype_str);
3696 :
3697 0 : d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
3698 : username, enctypes, enctypes);
3699 :
3700 0 : printf("[%s] 0x%08x DES-CBC-CRC\n",
3701 0 : enctypes & ENC_CRC32 ? "X" : " ",
3702 : ENC_CRC32);
3703 0 : printf("[%s] 0x%08x DES-CBC-MD5\n",
3704 0 : enctypes & ENC_RSA_MD5 ? "X" : " ",
3705 : ENC_RSA_MD5);
3706 0 : printf("[%s] 0x%08x RC4-HMAC\n",
3707 0 : enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ",
3708 : ENC_RC4_HMAC_MD5);
3709 0 : printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
3710 0 : enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ",
3711 : ENC_HMAC_SHA1_96_AES128);
3712 0 : printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
3713 0 : enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
3714 : ENC_HMAC_SHA1_96_AES256);
3715 0 : printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96-SK\n",
3716 0 : enctypes & ENC_HMAC_SHA1_96_AES256_SK ? "X" : " ",
3717 : ENC_HMAC_SHA1_96_AES256_SK);
3718 0 : printf("[%s] 0x%08x RESOURCE-SID-COMPRESSION-DISABLED\n",
3719 0 : enctypes & KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED ? "X" : " ",
3720 : KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED);
3721 0 : }
3722 :
3723 0 : static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
3724 : {
3725 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3726 0 : ADS_STATUS status;
3727 0 : ADS_STRUCT *ads = NULL;
3728 0 : LDAPMessage *res = NULL;
3729 0 : const char *str = NULL;
3730 0 : int ret = -1;
3731 :
3732 0 : if (c->display_usage || (argc < 1)) {
3733 0 : d_printf( "%s\n"
3734 : "net ads enctypes list\n"
3735 : " %s\n",
3736 : _("Usage:"),
3737 : _("List supported enctypes"));
3738 0 : TALLOC_FREE(tmp_ctx);
3739 0 : return -1;
3740 : }
3741 :
3742 0 : status = ads_startup(c, false, tmp_ctx, &ads);
3743 0 : if (!ADS_ERR_OK(status)) {
3744 0 : goto out;
3745 : }
3746 :
3747 0 : ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3748 0 : if (ret) {
3749 0 : goto out;
3750 : }
3751 :
3752 0 : net_ads_enctype_dump_enctypes(argv[0], str);
3753 :
3754 0 : ret = 0;
3755 0 : out:
3756 0 : ads_msgfree(ads, res);
3757 0 : TALLOC_FREE(tmp_ctx);
3758 0 : return ret;
3759 : }
3760 :
3761 0 : static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
3762 : {
3763 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3764 0 : int ret = -1;
3765 0 : ADS_STATUS status;
3766 0 : ADS_STRUCT *ads = NULL;
3767 0 : LDAPMessage *res = NULL;
3768 0 : const char *etype_list_str = NULL;
3769 0 : const char *dn = NULL;
3770 0 : ADS_MODLIST mods = NULL;
3771 0 : uint32_t etype_list;
3772 0 : const char *str = NULL;
3773 :
3774 0 : if (c->display_usage || argc < 1) {
3775 0 : d_printf( "%s\n"
3776 : "net ads enctypes set <sAMAccountName> [enctypes]\n"
3777 : " %s\n",
3778 : _("Usage:"),
3779 : _("Set supported enctypes"));
3780 0 : TALLOC_FREE(tmp_ctx);
3781 0 : return -1;
3782 : }
3783 :
3784 0 : status = ads_startup(c, false, tmp_ctx, &ads);
3785 0 : if (!ADS_ERR_OK(status)) {
3786 0 : goto done;
3787 : }
3788 :
3789 0 : ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3790 0 : if (ret) {
3791 0 : goto done;
3792 : }
3793 :
3794 0 : dn = ads_get_dn(ads, tmp_ctx, res);
3795 0 : if (dn == NULL) {
3796 0 : goto done;
3797 : }
3798 :
3799 0 : etype_list = 0;
3800 0 : etype_list |= ENC_RC4_HMAC_MD5;
3801 0 : etype_list |= ENC_HMAC_SHA1_96_AES128;
3802 0 : etype_list |= ENC_HMAC_SHA1_96_AES256;
3803 :
3804 0 : if (argv[1] != NULL) {
3805 0 : sscanf(argv[1], "%i", &etype_list);
3806 : }
3807 :
3808 0 : etype_list_str = talloc_asprintf(tmp_ctx, "%d", etype_list);
3809 0 : if (!etype_list_str) {
3810 0 : goto done;
3811 : }
3812 :
3813 0 : mods = ads_init_mods(tmp_ctx);
3814 0 : if (!mods) {
3815 0 : goto done;
3816 : }
3817 :
3818 0 : status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes",
3819 : etype_list_str);
3820 0 : if (!ADS_ERR_OK(status)) {
3821 0 : goto done;
3822 : }
3823 :
3824 0 : status = ads_gen_mod(ads, dn, mods);
3825 0 : if (!ADS_ERR_OK(status)) {
3826 0 : d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3827 : ads_errstr(status));
3828 0 : goto done;
3829 : }
3830 :
3831 0 : ads_msgfree(ads, res);
3832 0 : res = NULL;
3833 :
3834 0 : ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3835 0 : if (ret) {
3836 0 : goto done;
3837 : }
3838 :
3839 0 : net_ads_enctype_dump_enctypes(argv[0], str);
3840 :
3841 0 : ret = 0;
3842 0 : done:
3843 0 : ads_msgfree(ads, res);
3844 0 : TALLOC_FREE(tmp_ctx);
3845 0 : return ret;
3846 : }
3847 :
3848 0 : static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
3849 : {
3850 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3851 0 : int ret = -1;
3852 0 : ADS_STATUS status;
3853 0 : ADS_STRUCT *ads = NULL;
3854 0 : LDAPMessage *res = NULL;
3855 0 : const char *dn = NULL;
3856 0 : ADS_MODLIST mods = NULL;
3857 :
3858 0 : if (c->display_usage || argc < 1) {
3859 0 : d_printf( "%s\n"
3860 : "net ads enctypes delete <sAMAccountName>\n"
3861 : " %s\n",
3862 : _("Usage:"),
3863 : _("Delete supported enctypes"));
3864 0 : TALLOC_FREE(tmp_ctx);
3865 0 : return -1;
3866 : }
3867 :
3868 0 : status = ads_startup(c, false, tmp_ctx, &ads);
3869 0 : if (!ADS_ERR_OK(status)) {
3870 0 : goto done;
3871 : }
3872 :
3873 0 : ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3874 0 : if (ret) {
3875 0 : goto done;
3876 : }
3877 :
3878 0 : dn = ads_get_dn(ads, tmp_ctx, res);
3879 0 : if (dn == NULL) {
3880 0 : goto done;
3881 : }
3882 :
3883 0 : mods = ads_init_mods(tmp_ctx);
3884 0 : if (!mods) {
3885 0 : goto done;
3886 : }
3887 :
3888 0 : status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes", NULL);
3889 0 : if (!ADS_ERR_OK(status)) {
3890 0 : goto done;
3891 : }
3892 :
3893 0 : status = ads_gen_mod(ads, dn, mods);
3894 0 : if (!ADS_ERR_OK(status)) {
3895 0 : d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3896 : ads_errstr(status));
3897 0 : goto done;
3898 : }
3899 :
3900 0 : ret = 0;
3901 :
3902 0 : done:
3903 0 : ads_msgfree(ads, res);
3904 0 : TALLOC_FREE(tmp_ctx);
3905 0 : return ret;
3906 : }
3907 :
3908 0 : static int net_ads_enctypes(struct net_context *c, int argc, const char **argv)
3909 : {
3910 0 : struct functable func[] = {
3911 : {
3912 : "list",
3913 : net_ads_enctypes_list,
3914 : NET_TRANSPORT_ADS,
3915 : N_("List the supported encryption types"),
3916 : N_("net ads enctypes list\n"
3917 : " List the supported encryption types")
3918 : },
3919 : {
3920 : "set",
3921 : net_ads_enctypes_set,
3922 : NET_TRANSPORT_ADS,
3923 : N_("Set the supported encryption types"),
3924 : N_("net ads enctypes set\n"
3925 : " Set the supported encryption types")
3926 : },
3927 : {
3928 : "delete",
3929 : net_ads_enctypes_delete,
3930 : NET_TRANSPORT_ADS,
3931 : N_("Delete the supported encryption types"),
3932 : N_("net ads enctypes delete\n"
3933 : " Delete the supported encryption types")
3934 : },
3935 :
3936 : {NULL, NULL, 0, NULL, NULL}
3937 : };
3938 :
3939 0 : return net_run_function(c, argc, argv, "net ads enctypes", func);
3940 : }
3941 :
3942 :
3943 288 : int net_ads(struct net_context *c, int argc, const char **argv)
3944 : {
3945 288 : struct functable func[] = {
3946 : {
3947 : "info",
3948 : net_ads_info,
3949 : NET_TRANSPORT_ADS,
3950 : N_("Display details on remote ADS server"),
3951 : N_("net ads info\n"
3952 : " Display details on remote ADS server")
3953 : },
3954 : {
3955 : "join",
3956 : net_ads_join,
3957 : NET_TRANSPORT_ADS,
3958 : N_("Join the local machine to ADS realm"),
3959 : N_("net ads join\n"
3960 : " Join the local machine to ADS realm")
3961 : },
3962 : {
3963 : "testjoin",
3964 : net_ads_testjoin,
3965 : NET_TRANSPORT_ADS,
3966 : N_("Validate machine account"),
3967 : N_("net ads testjoin\n"
3968 : " Validate machine account")
3969 : },
3970 : {
3971 : "leave",
3972 : net_ads_leave,
3973 : NET_TRANSPORT_ADS,
3974 : N_("Remove the local machine from ADS"),
3975 : N_("net ads leave\n"
3976 : " Remove the local machine from ADS")
3977 : },
3978 : {
3979 : "status",
3980 : net_ads_status,
3981 : NET_TRANSPORT_ADS,
3982 : N_("Display machine account details"),
3983 : N_("net ads status\n"
3984 : " Display machine account details")
3985 : },
3986 : {
3987 : "user",
3988 : net_ads_user,
3989 : NET_TRANSPORT_ADS,
3990 : N_("List/modify users"),
3991 : N_("net ads user\n"
3992 : " List/modify users")
3993 : },
3994 : {
3995 : "group",
3996 : net_ads_group,
3997 : NET_TRANSPORT_ADS,
3998 : N_("List/modify groups"),
3999 : N_("net ads group\n"
4000 : " List/modify groups")
4001 : },
4002 : {
4003 : "dns",
4004 : net_ads_dns,
4005 : NET_TRANSPORT_ADS,
4006 : N_("Issue dynamic DNS update"),
4007 : N_("net ads dns\n"
4008 : " Issue dynamic DNS update")
4009 : },
4010 : {
4011 : "password",
4012 : net_ads_password,
4013 : NET_TRANSPORT_ADS,
4014 : N_("Change user passwords"),
4015 : N_("net ads password\n"
4016 : " Change user passwords")
4017 : },
4018 : {
4019 : "changetrustpw",
4020 : net_ads_changetrustpw,
4021 : NET_TRANSPORT_ADS,
4022 : N_("Change trust account password"),
4023 : N_("net ads changetrustpw\n"
4024 : " Change trust account password")
4025 : },
4026 : {
4027 : "printer",
4028 : net_ads_printer,
4029 : NET_TRANSPORT_ADS,
4030 : N_("List/modify printer entries"),
4031 : N_("net ads printer\n"
4032 : " List/modify printer entries")
4033 : },
4034 : {
4035 : "search",
4036 : net_ads_search,
4037 : NET_TRANSPORT_ADS,
4038 : N_("Issue LDAP search using filter"),
4039 : N_("net ads search\n"
4040 : " Issue LDAP search using filter")
4041 : },
4042 : {
4043 : "dn",
4044 : net_ads_dn,
4045 : NET_TRANSPORT_ADS,
4046 : N_("Issue LDAP search by DN"),
4047 : N_("net ads dn\n"
4048 : " Issue LDAP search by DN")
4049 : },
4050 : {
4051 : "sid",
4052 : net_ads_sid,
4053 : NET_TRANSPORT_ADS,
4054 : N_("Issue LDAP search by SID"),
4055 : N_("net ads sid\n"
4056 : " Issue LDAP search by SID")
4057 : },
4058 : {
4059 : "workgroup",
4060 : net_ads_workgroup,
4061 : NET_TRANSPORT_ADS,
4062 : N_("Display workgroup name"),
4063 : N_("net ads workgroup\n"
4064 : " Display the workgroup name")
4065 : },
4066 : {
4067 : "lookup",
4068 : net_ads_lookup,
4069 : NET_TRANSPORT_ADS,
4070 : N_("Perform CLDAP query on DC"),
4071 : N_("net ads lookup\n"
4072 : " Find the ADS DC using CLDAP lookups")
4073 : },
4074 : {
4075 : "keytab",
4076 : net_ads_keytab,
4077 : NET_TRANSPORT_ADS,
4078 : N_("Manage local keytab file"),
4079 : N_("net ads keytab\n"
4080 : " Manage local keytab file")
4081 : },
4082 : {
4083 : "setspn",
4084 : net_ads_setspn,
4085 : NET_TRANSPORT_ADS,
4086 : N_("Manage Service Principal Names (SPN)s"),
4087 : N_("net ads spnset\n"
4088 : " Manage Service Principal Names (SPN)s")
4089 : },
4090 : {
4091 : "gpo",
4092 : net_ads_gpo,
4093 : NET_TRANSPORT_ADS,
4094 : N_("Manage group policy objects"),
4095 : N_("net ads gpo\n"
4096 : " Manage group policy objects")
4097 : },
4098 : {
4099 : "kerberos",
4100 : net_ads_kerberos,
4101 : NET_TRANSPORT_ADS,
4102 : N_("Manage kerberos keytab"),
4103 : N_("net ads kerberos\n"
4104 : " Manage kerberos keytab")
4105 : },
4106 : {
4107 : "enctypes",
4108 : net_ads_enctypes,
4109 : NET_TRANSPORT_ADS,
4110 : N_("List/modify supported encryption types"),
4111 : N_("net ads enctypes\n"
4112 : " List/modify enctypes")
4113 : },
4114 : {NULL, NULL, 0, NULL, NULL}
4115 : };
4116 :
4117 288 : return net_run_function(c, argc, argv, "net ads", func);
4118 : }
4119 :
4120 : #else
4121 :
4122 0 : static int net_ads_noads(void)
4123 : {
4124 0 : d_fprintf(stderr, _("ADS support not compiled in\n"));
4125 0 : return -1;
4126 : }
4127 :
4128 0 : int net_ads_keytab(struct net_context *c, int argc, const char **argv)
4129 : {
4130 0 : return net_ads_noads();
4131 : }
4132 :
4133 0 : int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
4134 : {
4135 0 : return net_ads_noads();
4136 : }
4137 :
4138 0 : int net_ads_setspn(struct net_context *c, int argc, const char **argv)
4139 : {
4140 0 : return net_ads_noads();
4141 : }
4142 :
4143 0 : int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
4144 : {
4145 0 : return net_ads_noads();
4146 : }
4147 :
4148 0 : int net_ads_join(struct net_context *c, int argc, const char **argv)
4149 : {
4150 0 : return net_ads_noads();
4151 : }
4152 :
4153 0 : int net_ads_user(struct net_context *c, int argc, const char **argv)
4154 : {
4155 0 : return net_ads_noads();
4156 : }
4157 :
4158 0 : int net_ads_group(struct net_context *c, int argc, const char **argv)
4159 : {
4160 0 : return net_ads_noads();
4161 : }
4162 :
4163 0 : int net_ads_gpo(struct net_context *c, int argc, const char **argv)
4164 : {
4165 0 : return net_ads_noads();
4166 : }
4167 :
4168 : /* this one shouldn't display a message */
4169 0 : int net_ads_check(struct net_context *c)
4170 : {
4171 0 : return -1;
4172 : }
4173 :
4174 0 : int net_ads_check_our_domain(struct net_context *c)
4175 : {
4176 0 : return -1;
4177 : }
4178 :
4179 0 : int net_ads(struct net_context *c, int argc, const char **argv)
4180 : {
4181 0 : return net_ads_noads();
4182 : }
4183 :
4184 : #endif /* HAVE_ADS */
|