source: vendor/3.6.23/source3/utils/net_ads.c

Last change on this file was 860, checked in by Silvan Scherrer, 11 years ago

Samba 3.6: updated vendor to latest version

File size: 68.9 KB
Line 
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 "rpc_client/cli_pipe.h"
26#include "librpc/gen_ndr/ndr_krb5pac.h"
27#include "../librpc/gen_ndr/ndr_spoolss.h"
28#include "nsswitch/libwbclient/wbclient.h"
29#include "ads.h"
30#include "libads/cldap.h"
31#include "libads/dns.h"
32#include "../libds/common/flags.h"
33#include "librpc/gen_ndr/libnet_join.h"
34#include "libnet/libnet_join.h"
35#include "smb_krb5.h"
36#include "secrets.h"
37#include "krb5_env.h"
38#include "../libcli/security/security.h"
39#include "libsmb/libsmb.h"
40#include "utils/net_dns.h"
41
42#ifdef HAVE_ADS
43
44/* when we do not have sufficient input parameters to contact a remote domain
45 * we always fall back to our own realm - Guenther*/
46
47static const char *assume_own_realm(struct net_context *c)
48{
49 if (!c->opt_host && strequal(lp_workgroup(), c->opt_target_workgroup)) {
50 return lp_realm();
51 }
52
53 return NULL;
54}
55
56/*
57 do a cldap netlogon query
58*/
59static int net_ads_cldap_netlogon(struct net_context *c, ADS_STRUCT *ads)
60{
61 char addr[INET6_ADDRSTRLEN];
62 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
63
64 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
65 if ( !ads_cldap_netlogon_5(talloc_tos(), addr, ads->server.realm, &reply ) ) {
66 d_fprintf(stderr, _("CLDAP query failed!\n"));
67 return -1;
68 }
69
70 d_printf(_("Information for Domain Controller: %s\n\n"),
71 addr);
72
73 d_printf(_("Response Type: "));
74 switch (reply.command) {
75 case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
76 d_printf("LOGON_SAM_LOGON_USER_UNKNOWN_EX\n");
77 break;
78 case LOGON_SAM_LOGON_RESPONSE_EX:
79 d_printf("LOGON_SAM_LOGON_RESPONSE_EX\n");
80 break;
81 default:
82 d_printf("0x%x\n", reply.command);
83 break;
84 }
85
86 d_printf(_("GUID: %s\n"), GUID_string(talloc_tos(),&reply.domain_uuid));
87
88 d_printf(_("Flags:\n"
89 "\tIs a PDC: %s\n"
90 "\tIs a GC of the forest: %s\n"
91 "\tIs an LDAP server: %s\n"
92 "\tSupports DS: %s\n"
93 "\tIs running a KDC: %s\n"
94 "\tIs running time services: %s\n"
95 "\tIs the closest DC: %s\n"
96 "\tIs writable: %s\n"
97 "\tHas a hardware clock: %s\n"
98 "\tIs a non-domain NC serviced by LDAP server: %s\n"
99 "\tIs NT6 DC that has some secrets: %s\n"
100 "\tIs NT6 DC that has all secrets: %s\n"),
101 (reply.server_type & NBT_SERVER_PDC) ? _("yes") : _("no"),
102 (reply.server_type & NBT_SERVER_GC) ? _("yes") : _("no"),
103 (reply.server_type & NBT_SERVER_LDAP) ? _("yes") : _("no"),
104 (reply.server_type & NBT_SERVER_DS) ? _("yes") : _("no"),
105 (reply.server_type & NBT_SERVER_KDC) ? _("yes") : _("no"),
106 (reply.server_type & NBT_SERVER_TIMESERV) ? _("yes") : _("no"),
107 (reply.server_type & NBT_SERVER_CLOSEST) ? _("yes") : _("no"),
108 (reply.server_type & NBT_SERVER_WRITABLE) ? _("yes") : _("no"),
109 (reply.server_type & NBT_SERVER_GOOD_TIMESERV) ? _("yes") : _("no"),
110 (reply.server_type & NBT_SERVER_NDNC) ? _("yes") : _("no"),
111 (reply.server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6) ? _("yes") : _("no"),
112 (reply.server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6) ? _("yes") : _("no"));
113
114
115 printf(_("Forest:\t\t\t%s\n"), reply.forest);
116 printf(_("Domain:\t\t\t%s\n"), reply.dns_domain);
117 printf(_("Domain Controller:\t%s\n"), reply.pdc_dns_name);
118
119 printf(_("Pre-Win2k Domain:\t%s\n"), reply.domain_name);
120 printf(_("Pre-Win2k Hostname:\t%s\n"), reply.pdc_name);
121
122 if (*reply.user_name) printf(_("User name:\t%s\n"), reply.user_name);
123
124 printf(_("Server Site Name :\t\t%s\n"), reply.server_site);
125 printf(_("Client Site Name :\t\t%s\n"), reply.client_site);
126
127 d_printf(_("NT Version: %d\n"), reply.nt_version);
128 d_printf(_("LMNT Token: %.2x\n"), reply.lmnt_token);
129 d_printf(_("LM20 Token: %.2x\n"), reply.lm20_token);
130
131 return 0;
132}
133
134/*
135 this implements the CLDAP based netlogon lookup requests
136 for finding the domain controller of a ADS domain
137*/
138static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
139{
140 ADS_STRUCT *ads;
141 int ret;
142
143 if (c->display_usage) {
144 d_printf("%s\n"
145 "net ads lookup\n"
146 " %s",
147 _("Usage:"),
148 _("Find the ADS DC using CLDAP lookup.\n"));
149 return 0;
150 }
151
152 if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
153 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
154 ads_destroy(&ads);
155 return -1;
156 }
157
158 if (!ads->config.realm) {
159 ads->config.realm = CONST_DISCARD(char *, c->opt_target_workgroup);
160 ads->ldap.port = 389;
161 }
162
163 ret = net_ads_cldap_netlogon(c, ads);
164 ads_destroy(&ads);
165 return ret;
166}
167
168
169
170static int net_ads_info(struct net_context *c, int argc, const char **argv)
171{
172 ADS_STRUCT *ads;
173 char addr[INET6_ADDRSTRLEN];
174
175 if (c->display_usage) {
176 d_printf("%s\n"
177 "net ads info\n"
178 " %s",
179 _("Usage:"),
180 _("Display information about an Active Directory "
181 "server.\n"));
182 return 0;
183 }
184
185 if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
186 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
187 return -1;
188 }
189
190 if (!ads || !ads->config.realm) {
191 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
192 ads_destroy(&ads);
193 return -1;
194 }
195
196 /* Try to set the server's current time since we didn't do a full
197 TCP LDAP session initially */
198
199 if ( !ADS_ERR_OK(ads_current_time( ads )) ) {
200 d_fprintf( stderr, _("Failed to get server's current time!\n"));
201 }
202
203 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
204
205 d_printf(_("LDAP server: %s\n"), addr);
206 d_printf(_("LDAP server name: %s\n"), ads->config.ldap_server_name);
207 d_printf(_("Realm: %s\n"), ads->config.realm);
208 d_printf(_("Bind Path: %s\n"), ads->config.bind_path);
209 d_printf(_("LDAP port: %d\n"), ads->ldap.port);
210 d_printf(_("Server time: %s\n"),
211 http_timestring(talloc_tos(), ads->config.current_time));
212
213 d_printf(_("KDC server: %s\n"), ads->auth.kdc_server );
214 d_printf(_("Server time offset: %d\n"), ads->auth.time_offset );
215
216 ads_destroy(&ads);
217 return 0;
218}
219
220static void use_in_memory_ccache(void) {
221 /* Use in-memory credentials cache so we do not interfere with
222 * existing credentials */
223 setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
224}
225
226static ADS_STATUS ads_startup_int(struct net_context *c, bool only_own_domain,
227 uint32 auth_flags, ADS_STRUCT **ads_ret)
228{
229 ADS_STRUCT *ads = NULL;
230 ADS_STATUS status;
231 bool need_password = false;
232 bool second_time = false;
233 char *cp;
234 const char *realm = NULL;
235 bool tried_closest_dc = false;
236
237 /* lp_realm() should be handled by a command line param,
238 However, the join requires that realm be set in smb.conf
239 and compares our realm with the remote server's so this is
240 ok until someone needs more flexibility */
241
242 *ads_ret = NULL;
243
244retry_connect:
245 if (only_own_domain) {
246 realm = lp_realm();
247 } else {
248 realm = assume_own_realm(c);
249 }
250
251 ads = ads_init(realm, c->opt_target_workgroup, c->opt_host);
252
253 if (!c->opt_user_name) {
254 c->opt_user_name = "administrator";
255 }
256
257 if (c->opt_user_specified) {
258 need_password = true;
259 }
260
261retry:
262 if (!c->opt_password && need_password && !c->opt_machine_pass) {
263 c->opt_password = net_prompt_pass(c, c->opt_user_name);
264 if (!c->opt_password) {
265 ads_destroy(&ads);
266 return ADS_ERROR(LDAP_NO_MEMORY);
267 }
268 }
269
270 if (c->opt_password) {
271 use_in_memory_ccache();
272 SAFE_FREE(ads->auth.password);
273 ads->auth.password = smb_xstrdup(c->opt_password);
274 }
275
276 ads->auth.flags |= auth_flags;
277 SAFE_FREE(ads->auth.user_name);
278 ads->auth.user_name = smb_xstrdup(c->opt_user_name);
279
280 /*
281 * If the username is of the form "name@realm",
282 * extract the realm and convert to upper case.
283 * This is only used to establish the connection.
284 */
285 if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
286 *cp++ = '\0';
287 SAFE_FREE(ads->auth.realm);
288 ads->auth.realm = smb_xstrdup(cp);
289 strupper_m(ads->auth.realm);
290 }
291
292 status = ads_connect(ads);
293
294 if (!ADS_ERR_OK(status)) {
295
296 if (NT_STATUS_EQUAL(ads_ntstatus(status),
297 NT_STATUS_NO_LOGON_SERVERS)) {
298 DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
299 ads_destroy(&ads);
300 return status;
301 }
302
303 if (!need_password && !second_time && !(auth_flags & ADS_AUTH_NO_BIND)) {
304 need_password = true;
305 second_time = true;
306 goto retry;
307 } else {
308 ads_destroy(&ads);
309 return status;
310 }
311 }
312
313 /* when contacting our own domain, make sure we use the closest DC.
314 * This is done by reconnecting to ADS because only the first call to
315 * ads_connect will give us our own sitename */
316
317 if ((only_own_domain || !c->opt_host) && !tried_closest_dc) {
318
319 tried_closest_dc = true; /* avoid loop */
320
321 if (!ads_closest_dc(ads)) {
322
323 namecache_delete(ads->server.realm, 0x1C);
324 namecache_delete(ads->server.workgroup, 0x1C);
325
326 ads_destroy(&ads);
327 ads = NULL;
328
329 goto retry_connect;
330 }
331 }
332
333 *ads_ret = ads;
334 return status;
335}
336
337ADS_STATUS ads_startup(struct net_context *c, bool only_own_domain, ADS_STRUCT **ads)
338{
339 return ads_startup_int(c, only_own_domain, 0, ads);
340}
341
342ADS_STATUS ads_startup_nobind(struct net_context *c, bool only_own_domain, ADS_STRUCT **ads)
343{
344 return ads_startup_int(c, only_own_domain, ADS_AUTH_NO_BIND, ads);
345}
346
347/*
348 Check to see if connection can be made via ads.
349 ads_startup() stores the password in opt_password if it needs to so
350 that rpc or rap can use it without re-prompting.
351*/
352static int net_ads_check_int(const char *realm, const char *workgroup, const char *host)
353{
354 ADS_STRUCT *ads;
355 ADS_STATUS status;
356
357 if ( (ads = ads_init( realm, workgroup, host )) == NULL ) {
358 return -1;
359 }
360
361 ads->auth.flags |= ADS_AUTH_NO_BIND;
362
363 status = ads_connect(ads);
364 if ( !ADS_ERR_OK(status) ) {
365 return -1;
366 }
367
368 ads_destroy(&ads);
369 return 0;
370}
371
372int net_ads_check_our_domain(struct net_context *c)
373{
374 return net_ads_check_int(lp_realm(), lp_workgroup(), NULL);
375}
376
377int net_ads_check(struct net_context *c)
378{
379 return net_ads_check_int(NULL, c->opt_workgroup, c->opt_host);
380}
381
382/*
383 determine the netbios workgroup name for a domain
384 */
385static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
386{
387 ADS_STRUCT *ads;
388 char addr[INET6_ADDRSTRLEN];
389 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
390
391 if (c->display_usage) {
392 d_printf ("%s\n"
393 "net ads workgroup\n"
394 " %s\n",
395 _("Usage:"),
396 _("Print the workgroup name"));
397 return 0;
398 }
399
400 if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
401 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
402 return -1;
403 }
404
405 if (!ads->config.realm) {
406 ads->config.realm = CONST_DISCARD(char *, c->opt_target_workgroup);
407 ads->ldap.port = 389;
408 }
409
410 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
411 if ( !ads_cldap_netlogon_5(talloc_tos(), addr, ads->server.realm, &reply ) ) {
412 d_fprintf(stderr, _("CLDAP query failed!\n"));
413 ads_destroy(&ads);
414 return -1;
415 }
416
417 d_printf(_("Workgroup: %s\n"), reply.domain_name);
418
419 ads_destroy(&ads);
420
421 return 0;
422}
423
424
425
426static bool usergrp_display(ADS_STRUCT *ads, char *field, void **values, void *data_area)
427{
428 char **disp_fields = (char **) data_area;
429
430 if (!field) { /* must be end of record */
431 if (disp_fields[0]) {
432 if (!strchr_m(disp_fields[0], '$')) {
433 if (disp_fields[1])
434 d_printf("%-21.21s %s\n",
435 disp_fields[0], disp_fields[1]);
436 else
437 d_printf("%s\n", disp_fields[0]);
438 }
439 }
440 SAFE_FREE(disp_fields[0]);
441 SAFE_FREE(disp_fields[1]);
442 return true;
443 }
444 if (!values) /* must be new field, indicate string field */
445 return true;
446 if (StrCaseCmp(field, "sAMAccountName") == 0) {
447 disp_fields[0] = SMB_STRDUP((char *) values[0]);
448 }
449 if (StrCaseCmp(field, "description") == 0)
450 disp_fields[1] = SMB_STRDUP((char *) values[0]);
451 return true;
452}
453
454static int net_ads_user_usage(struct net_context *c, int argc, const char **argv)
455{
456 return net_user_usage(c, argc, argv);
457}
458
459static int ads_user_add(struct net_context *c, int argc, const char **argv)
460{
461 ADS_STRUCT *ads;
462 ADS_STATUS status;
463 char *upn, *userdn;
464 LDAPMessage *res=NULL;
465 int rc = -1;
466 char *ou_str = NULL;
467
468 if (argc < 1 || c->display_usage)
469 return net_ads_user_usage(c, argc, argv);
470
471 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
472 return -1;
473 }
474
475 status = ads_find_user_acct(ads, &res, argv[0]);
476
477 if (!ADS_ERR_OK(status)) {
478 d_fprintf(stderr, _("ads_user_add: %s\n"), ads_errstr(status));
479 goto done;
480 }
481
482 if (ads_count_replies(ads, res)) {
483 d_fprintf(stderr, _("ads_user_add: User %s already exists\n"),
484 argv[0]);
485 goto done;
486 }
487
488 if (c->opt_container) {
489 ou_str = SMB_STRDUP(c->opt_container);
490 } else {
491 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
492 }
493
494 status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment);
495
496 if (!ADS_ERR_OK(status)) {
497 d_fprintf(stderr, _("Could not add user %s: %s\n"), argv[0],
498 ads_errstr(status));
499 goto done;
500 }
501
502 /* if no password is to be set, we're done */
503 if (argc == 1) {
504 d_printf(_("User %s added\n"), argv[0]);
505 rc = 0;
506 goto done;
507 }
508
509 /* try setting the password */
510 if (asprintf(&upn, "%s@%s", argv[0], ads->config.realm) == -1) {
511 goto done;
512 }
513 status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
514 ads->auth.time_offset);
515 SAFE_FREE(upn);
516 if (ADS_ERR_OK(status)) {
517 d_printf(_("User %s added\n"), argv[0]);
518 rc = 0;
519 goto done;
520 }
521
522 /* password didn't set, delete account */
523 d_fprintf(stderr, _("Could not add user %s. "
524 "Error setting password %s\n"),
525 argv[0], ads_errstr(status));
526 ads_msgfree(ads, res);
527 status=ads_find_user_acct(ads, &res, argv[0]);
528 if (ADS_ERR_OK(status)) {
529 userdn = ads_get_dn(ads, talloc_tos(), res);
530 ads_del_dn(ads, userdn);
531 TALLOC_FREE(userdn);
532 }
533
534 done:
535 if (res)
536 ads_msgfree(ads, res);
537 ads_destroy(&ads);
538 SAFE_FREE(ou_str);
539 return rc;
540}
541
542static int ads_user_info(struct net_context *c, int argc, const char **argv)
543{
544 ADS_STRUCT *ads = NULL;
545 ADS_STATUS rc;
546 LDAPMessage *res = NULL;
547 TALLOC_CTX *frame;
548 int ret = 0;
549 wbcErr wbc_status;
550 const char *attrs[] = {"memberOf", "primaryGroupID", NULL};
551 char *searchstring=NULL;
552 char **grouplist;
553 char *primary_group;
554 char *escaped_user;
555 struct dom_sid primary_group_sid;
556 uint32_t group_rid;
557 enum wbcSidType type;
558
559 if (argc < 1 || c->display_usage) {
560 return net_ads_user_usage(c, argc, argv);
561 }
562
563 frame = talloc_new(talloc_tos());
564 if (frame == NULL) {
565 return -1;
566 }
567
568 escaped_user = escape_ldap_string(frame, argv[0]);
569 if (!escaped_user) {
570 d_fprintf(stderr,
571 _("ads_user_info: failed to escape user %s\n"),
572 argv[0]);
573 return -1;
574 }
575
576 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
577 ret = -1;
578 goto error;
579 }
580
581 if (asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user) == -1) {
582 ret =-1;
583 goto error;
584 }
585 rc = ads_search(ads, &res, searchstring, attrs);
586 SAFE_FREE(searchstring);
587
588 if (!ADS_ERR_OK(rc)) {
589 d_fprintf(stderr, _("ads_search: %s\n"), ads_errstr(rc));
590 ret = -1;
591 goto error;
592 }
593
594 if (!ads_pull_uint32(ads, res, "primaryGroupID", &group_rid)) {
595 d_fprintf(stderr, _("ads_pull_uint32 failed\n"));
596 ret = -1;
597 goto error;
598 }
599
600 rc = ads_domain_sid(ads, &primary_group_sid);
601 if (!ADS_ERR_OK(rc)) {
602 d_fprintf(stderr, _("ads_domain_sid: %s\n"), ads_errstr(rc));
603 ret = -1;
604 goto error;
605 }
606
607 sid_append_rid(&primary_group_sid, group_rid);
608
609 wbc_status = wbcLookupSid((struct wbcDomainSid *)&primary_group_sid,
610 NULL, /* don't look up domain */
611 &primary_group,
612 &type);
613 if (!WBC_ERROR_IS_OK(wbc_status)) {
614 d_fprintf(stderr, "wbcLookupSid: %s\n",
615 wbcErrorString(wbc_status));
616 ret = -1;
617 goto error;
618 }
619
620 d_printf("%s\n", primary_group);
621
622 wbcFreeMemory(primary_group);
623
624 grouplist = ldap_get_values((LDAP *)ads->ldap.ld,
625 (LDAPMessage *)res, "memberOf");
626
627 if (grouplist) {
628 int i;
629 char **groupname;
630 for (i=0;grouplist[i];i++) {
631 groupname = ldap_explode_dn(grouplist[i], 1);
632 d_printf("%s\n", groupname[0]);
633 ldap_value_free(groupname);
634 }
635 ldap_value_free(grouplist);
636 }
637
638error:
639 if (res) ads_msgfree(ads, res);
640 if (ads) ads_destroy(&ads);
641 TALLOC_FREE(frame);
642 return ret;
643}
644
645static int ads_user_delete(struct net_context *c, int argc, const char **argv)
646{
647 ADS_STRUCT *ads;
648 ADS_STATUS rc;
649 LDAPMessage *res = NULL;
650 char *userdn;
651
652 if (argc < 1) {
653 return net_ads_user_usage(c, argc, argv);
654 }
655
656 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
657 return -1;
658 }
659
660 rc = ads_find_user_acct(ads, &res, argv[0]);
661 if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) {
662 d_printf(_("User %s does not exist.\n"), argv[0]);
663 ads_msgfree(ads, res);
664 ads_destroy(&ads);
665 return -1;
666 }
667 userdn = ads_get_dn(ads, talloc_tos(), res);
668 ads_msgfree(ads, res);
669 rc = ads_del_dn(ads, userdn);
670 TALLOC_FREE(userdn);
671 if (ADS_ERR_OK(rc)) {
672 d_printf(_("User %s deleted\n"), argv[0]);
673 ads_destroy(&ads);
674 return 0;
675 }
676 d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
677 ads_errstr(rc));
678 ads_destroy(&ads);
679 return -1;
680}
681
682int net_ads_user(struct net_context *c, int argc, const char **argv)
683{
684 struct functable func[] = {
685 {
686 "add",
687 ads_user_add,
688 NET_TRANSPORT_ADS,
689 N_("Add an AD user"),
690 N_("net ads user add\n"
691 " Add an AD user")
692 },
693 {
694 "info",
695 ads_user_info,
696 NET_TRANSPORT_ADS,
697 N_("Display information about an AD user"),
698 N_("net ads user info\n"
699 " Display information about an AD user")
700 },
701 {
702 "delete",
703 ads_user_delete,
704 NET_TRANSPORT_ADS,
705 N_("Delete an AD user"),
706 N_("net ads user delete\n"
707 " Delete an AD user")
708 },
709 {NULL, NULL, 0, NULL, NULL}
710 };
711 ADS_STRUCT *ads;
712 ADS_STATUS rc;
713 const char *shortattrs[] = {"sAMAccountName", NULL};
714 const char *longattrs[] = {"sAMAccountName", "description", NULL};
715 char *disp_fields[2] = {NULL, NULL};
716
717 if (argc == 0) {
718 if (c->display_usage) {
719 d_printf( "%s\n"
720 "net ads user\n"
721 " %s\n",
722 _("Usage:"),
723 _("List AD users"));
724 net_display_usage_from_functable(func);
725 return 0;
726 }
727
728 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
729 return -1;
730 }
731
732 if (c->opt_long_list_entries)
733 d_printf(_("\nUser name Comment"
734 "\n-----------------------------\n"));
735
736 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
737 LDAP_SCOPE_SUBTREE,
738 "(objectCategory=user)",
739 c->opt_long_list_entries ? longattrs :
740 shortattrs, usergrp_display,
741 disp_fields);
742 ads_destroy(&ads);
743 return ADS_ERR_OK(rc) ? 0 : -1;
744 }
745
746 return net_run_function(c, argc, argv, "net ads user", func);
747}
748
749static int net_ads_group_usage(struct net_context *c, int argc, const char **argv)
750{
751 return net_group_usage(c, argc, argv);
752}
753
754static int ads_group_add(struct net_context *c, int argc, const char **argv)
755{
756 ADS_STRUCT *ads;
757 ADS_STATUS status;
758 LDAPMessage *res=NULL;
759 int rc = -1;
760 char *ou_str = NULL;
761
762 if (argc < 1 || c->display_usage) {
763 return net_ads_group_usage(c, argc, argv);
764 }
765
766 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
767 return -1;
768 }
769
770 status = ads_find_user_acct(ads, &res, argv[0]);
771
772 if (!ADS_ERR_OK(status)) {
773 d_fprintf(stderr, _("ads_group_add: %s\n"), ads_errstr(status));
774 goto done;
775 }
776
777 if (ads_count_replies(ads, res)) {
778 d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]);
779 goto done;
780 }
781
782 if (c->opt_container) {
783 ou_str = SMB_STRDUP(c->opt_container);
784 } else {
785 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
786 }
787
788 status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
789
790 if (ADS_ERR_OK(status)) {
791 d_printf(_("Group %s added\n"), argv[0]);
792 rc = 0;
793 } else {
794 d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0],
795 ads_errstr(status));
796 }
797
798 done:
799 if (res)
800 ads_msgfree(ads, res);
801 ads_destroy(&ads);
802 SAFE_FREE(ou_str);
803 return rc;
804}
805
806static int ads_group_delete(struct net_context *c, int argc, const char **argv)
807{
808 ADS_STRUCT *ads;
809 ADS_STATUS rc;
810 LDAPMessage *res = NULL;
811 char *groupdn;
812
813 if (argc < 1 || c->display_usage) {
814 return net_ads_group_usage(c, argc, argv);
815 }
816
817 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
818 return -1;
819 }
820
821 rc = ads_find_user_acct(ads, &res, argv[0]);
822 if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) {
823 d_printf(_("Group %s does not exist.\n"), argv[0]);
824 ads_msgfree(ads, res);
825 ads_destroy(&ads);
826 return -1;
827 }
828 groupdn = ads_get_dn(ads, talloc_tos(), res);
829 ads_msgfree(ads, res);
830 rc = ads_del_dn(ads, groupdn);
831 TALLOC_FREE(groupdn);
832 if (ADS_ERR_OK(rc)) {
833 d_printf(_("Group %s deleted\n"), argv[0]);
834 ads_destroy(&ads);
835 return 0;
836 }
837 d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
838 ads_errstr(rc));
839 ads_destroy(&ads);
840 return -1;
841}
842
843int net_ads_group(struct net_context *c, int argc, const char **argv)
844{
845 struct functable func[] = {
846 {
847 "add",
848 ads_group_add,
849 NET_TRANSPORT_ADS,
850 N_("Add an AD group"),
851 N_("net ads group add\n"
852 " Add an AD group")
853 },
854 {
855 "delete",
856 ads_group_delete,
857 NET_TRANSPORT_ADS,
858 N_("Delete an AD group"),
859 N_("net ads group delete\n"
860 " Delete an AD group")
861 },
862 {NULL, NULL, 0, NULL, NULL}
863 };
864 ADS_STRUCT *ads;
865 ADS_STATUS rc;
866 const char *shortattrs[] = {"sAMAccountName", NULL};
867 const char *longattrs[] = {"sAMAccountName", "description", NULL};
868 char *disp_fields[2] = {NULL, NULL};
869
870 if (argc == 0) {
871 if (c->display_usage) {
872 d_printf( "%s\n"
873 "net ads group\n"
874 " %s\n",
875 _("Usage:"),
876 _("List AD groups"));
877 net_display_usage_from_functable(func);
878 return 0;
879 }
880
881 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
882 return -1;
883 }
884
885 if (c->opt_long_list_entries)
886 d_printf(_("\nGroup name Comment"
887 "\n-----------------------------\n"));
888 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
889 LDAP_SCOPE_SUBTREE,
890 "(objectCategory=group)",
891 c->opt_long_list_entries ? longattrs :
892 shortattrs, usergrp_display,
893 disp_fields);
894
895 ads_destroy(&ads);
896 return ADS_ERR_OK(rc) ? 0 : -1;
897 }
898 return net_run_function(c, argc, argv, "net ads group", func);
899}
900
901static int net_ads_status(struct net_context *c, int argc, const char **argv)
902{
903 ADS_STRUCT *ads;
904 ADS_STATUS rc;
905 LDAPMessage *res;
906
907 if (c->display_usage) {
908 d_printf( "%s\n"
909 "net ads status\n"
910 " %s\n",
911 _("Usage:"),
912 _("Display machine account details"));
913 return 0;
914 }
915
916 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
917 return -1;
918 }
919
920 rc = ads_find_machine_acct(ads, &res, global_myname());
921 if (!ADS_ERR_OK(rc)) {
922 d_fprintf(stderr, _("ads_find_machine_acct: %s\n"), ads_errstr(rc));
923 ads_destroy(&ads);
924 return -1;
925 }
926
927 if (ads_count_replies(ads, res) == 0) {
928 d_fprintf(stderr, _("No machine account for '%s' found\n"), global_myname());
929 ads_destroy(&ads);
930 return -1;
931 }
932
933 ads_dump(ads, res);
934 ads_destroy(&ads);
935 return 0;
936}
937
938/*******************************************************************
939 Leave an AD domain. Windows XP disables the machine account.
940 We'll try the same. The old code would do an LDAP delete.
941 That only worked using the machine creds because added the machine
942 with full control to the computer object's ACL.
943*******************************************************************/
944
945static int net_ads_leave(struct net_context *c, int argc, const char **argv)
946{
947 TALLOC_CTX *ctx;
948 struct libnet_UnjoinCtx *r = NULL;
949 WERROR werr;
950
951 if (c->display_usage) {
952 d_printf( "%s\n"
953 "net ads leave\n"
954 " %s\n",
955 _("Usage:"),
956 _("Leave an AD domain"));
957 return 0;
958 }
959
960 if (!*lp_realm()) {
961 d_fprintf(stderr, _("No realm set, are we joined ?\n"));
962 return -1;
963 }
964
965 if (!(ctx = talloc_init("net_ads_leave"))) {
966 d_fprintf(stderr, _("Could not initialise talloc context.\n"));
967 return -1;
968 }
969
970 if (!c->opt_kerberos) {
971 use_in_memory_ccache();
972 }
973
974 if (!c->msg_ctx) {
975 d_fprintf(stderr, _("Could not initialise message context. "
976 "Try running as root\n"));
977 return -1;
978 }
979
980 werr = libnet_init_UnjoinCtx(ctx, &r);
981 if (!W_ERROR_IS_OK(werr)) {
982 d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
983 return -1;
984 }
985
986 r->in.debug = true;
987 r->in.use_kerberos = c->opt_kerberos;
988 r->in.dc_name = c->opt_host;
989 r->in.domain_name = lp_realm();
990 r->in.admin_account = c->opt_user_name;
991 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
992 r->in.modify_config = lp_config_backend_is_registry();
993
994 /* Try to delete it, but if that fails, disable it. The
995 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
996 r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
997 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
998 r->in.delete_machine_account = true;
999 r->in.msg_ctx = c->msg_ctx;
1000
1001 werr = libnet_Unjoin(ctx, r);
1002 if (!W_ERROR_IS_OK(werr)) {
1003 d_printf(_("Failed to leave domain: %s\n"),
1004 r->out.error_string ? r->out.error_string :
1005 get_friendly_werror_msg(werr));
1006 goto done;
1007 }
1008
1009 if (r->out.deleted_machine_account) {
1010 d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1011 r->in.machine_name, r->out.dns_domain_name);
1012 goto done;
1013 }
1014
1015 /* We couldn't delete it - see if the disable succeeded. */
1016 if (r->out.disabled_machine_account) {
1017 d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1018 r->in.machine_name, r->out.dns_domain_name);
1019 werr = WERR_OK;
1020 goto done;
1021 }
1022
1023 /* Based on what we requseted, we shouldn't get here, but if
1024 we did, it means the secrets were removed, and therefore
1025 we have left the domain */
1026 d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"),
1027 r->in.machine_name, r->out.dns_domain_name);
1028
1029 done:
1030 TALLOC_FREE(r);
1031 TALLOC_FREE(ctx);
1032
1033 if (W_ERROR_IS_OK(werr)) {
1034 return 0;
1035 }
1036
1037 return -1;
1038}
1039
1040static NTSTATUS net_ads_join_ok(struct net_context *c)
1041{
1042 ADS_STRUCT *ads = NULL;
1043 ADS_STATUS status;
1044 fstring dc_name;
1045 struct sockaddr_storage dcip;
1046
1047 if (!secrets_init()) {
1048 DEBUG(1,("Failed to initialise secrets database\n"));
1049 return NT_STATUS_ACCESS_DENIED;
1050 }
1051
1052 net_use_krb_machine_account(c);
1053
1054 get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
1055
1056 status = ads_startup(c, true, &ads);
1057 if (!ADS_ERR_OK(status)) {
1058 return ads_ntstatus(status);
1059 }
1060
1061 ads_destroy(&ads);
1062 return NT_STATUS_OK;
1063}
1064
1065/*
1066 check that an existing join is OK
1067 */
1068int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
1069{
1070 NTSTATUS status;
1071 use_in_memory_ccache();
1072
1073 if (c->display_usage) {
1074 d_printf( "%s\n"
1075 "net ads testjoin\n"
1076 " %s\n",
1077 _("Usage:"),
1078 _("Test if the existing join is ok"));
1079 return 0;
1080 }
1081
1082 /* Display success or failure */
1083 status = net_ads_join_ok(c);
1084 if (!NT_STATUS_IS_OK(status)) {
1085 fprintf(stderr, _("Join to domain is not valid: %s\n"),
1086 get_friendly_nt_error_msg(status));
1087 return -1;
1088 }
1089
1090 printf(_("Join is OK\n"));
1091 return 0;
1092}
1093
1094/*******************************************************************
1095 Simple configu checks before beginning the join
1096 ********************************************************************/
1097
1098static WERROR check_ads_config( void )
1099{
1100 if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
1101 d_printf(_("Host is not configured as a member server.\n"));
1102 return WERR_INVALID_DOMAIN_ROLE;
1103 }
1104
1105 if (strlen(global_myname()) > 15) {
1106 d_printf(_("Our netbios name can be at most 15 chars long, "
1107 "\"%s\" is %u chars long\n"), global_myname(),
1108 (unsigned int)strlen(global_myname()));
1109 return WERR_INVALID_COMPUTERNAME;
1110 }
1111
1112 if ( lp_security() == SEC_ADS && !*lp_realm()) {
1113 d_fprintf(stderr, _("realm must be set in in %s for ADS "
1114 "join to succeed.\n"), get_dyn_CONFIGFILE());
1115 return WERR_INVALID_PARAM;
1116 }
1117
1118 return WERR_OK;
1119}
1120
1121/*******************************************************************
1122 Send a DNS update request
1123*******************************************************************/
1124
1125#if defined(WITH_DNS_UPDATES)
1126#include "../lib/addns/dns.h"
1127
1128static NTSTATUS net_update_dns_internal(struct net_context *c,
1129 TALLOC_CTX *ctx, ADS_STRUCT *ads,
1130 const char *machine_name,
1131 const struct sockaddr_storage *addrs,
1132 int num_addrs)
1133{
1134 struct dns_rr_ns *nameservers = NULL;
1135 int ns_count = 0, i;
1136 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1137 DNS_ERROR dns_err;
1138 fstring dns_server;
1139 const char *dnsdomain = NULL;
1140 char *root_domain = NULL;
1141
1142 if ( (dnsdomain = strchr_m( machine_name, '.')) == NULL ) {
1143 d_printf(_("No DNS domain configured for %s. "
1144 "Unable to perform DNS Update.\n"), machine_name);
1145 status = NT_STATUS_INVALID_PARAMETER;
1146 goto done;
1147 }
1148 dnsdomain++;
1149
1150 status = ads_dns_lookup_ns( ctx, dnsdomain, &nameservers, &ns_count );
1151 if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
1152 /* Child domains often do not have NS records. Look
1153 for the NS record for the forest root domain
1154 (rootDomainNamingContext in therootDSE) */
1155
1156 const char *rootname_attrs[] = { "rootDomainNamingContext", NULL };
1157 LDAPMessage *msg = NULL;
1158 char *root_dn;
1159 ADS_STATUS ads_status;
1160
1161 if ( !ads->ldap.ld ) {
1162 ads_status = ads_connect( ads );
1163 if ( !ADS_ERR_OK(ads_status) ) {
1164 DEBUG(0,("net_update_dns_internal: Failed to connect to our DC!\n"));
1165 goto done;
1166 }
1167 }
1168
1169 ads_status = ads_do_search(ads, "", LDAP_SCOPE_BASE,
1170 "(objectclass=*)", rootname_attrs, &msg);
1171 if (!ADS_ERR_OK(ads_status)) {
1172 goto done;
1173 }
1174
1175 root_dn = ads_pull_string(ads, ctx, msg, "rootDomainNamingContext");
1176 if ( !root_dn ) {
1177 ads_msgfree( ads, msg );
1178 goto done;
1179 }
1180
1181 root_domain = ads_build_domain( root_dn );
1182
1183 /* cleanup */
1184 ads_msgfree( ads, msg );
1185
1186 /* try again for NS servers */
1187
1188 status = ads_dns_lookup_ns( ctx, root_domain, &nameservers, &ns_count );
1189
1190 if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
1191 DEBUG(3,("net_update_dns_internal: Failed to find name server for the %s "
1192 "realm\n", ads->config.realm));
1193 goto done;
1194 }
1195
1196 dnsdomain = root_domain;
1197
1198 }
1199
1200 for (i=0; i < ns_count; i++) {
1201
1202 uint32_t flags = DNS_UPDATE_SIGNED |
1203 DNS_UPDATE_UNSIGNED |
1204 DNS_UPDATE_UNSIGNED_SUFFICIENT |
1205 DNS_UPDATE_PROBE |
1206 DNS_UPDATE_PROBE_SUFFICIENT;
1207
1208 if (c->opt_force) {
1209 flags &= ~DNS_UPDATE_PROBE_SUFFICIENT;
1210 flags &= ~DNS_UPDATE_UNSIGNED_SUFFICIENT;
1211 }
1212
1213 status = NT_STATUS_UNSUCCESSFUL;
1214
1215 /* Now perform the dns update - we'll try non-secure and if we fail,
1216 we'll follow it up with a secure update */
1217
1218 fstrcpy( dns_server, nameservers[i].hostname );
1219
1220 dns_err = DoDNSUpdate(dns_server, dnsdomain, machine_name, addrs, num_addrs, flags);
1221 if (ERR_DNS_IS_OK(dns_err)) {
1222 status = NT_STATUS_OK;
1223 goto done;
1224 }
1225
1226 if (ERR_DNS_EQUAL(dns_err, ERROR_DNS_INVALID_NAME_SERVER) ||
1227 ERR_DNS_EQUAL(dns_err, ERROR_DNS_CONNECTION_FAILED) ||
1228 ERR_DNS_EQUAL(dns_err, ERROR_DNS_SOCKET_ERROR)) {
1229 DEBUG(1,("retrying DNS update with next nameserver after receiving %s\n",
1230 dns_errstr(dns_err)));
1231 continue;
1232 }
1233
1234 d_printf(_("DNS Update for %s failed: %s\n"),
1235 machine_name, dns_errstr(dns_err));
1236 status = NT_STATUS_UNSUCCESSFUL;
1237 goto done;
1238 }
1239
1240done:
1241
1242 SAFE_FREE( root_domain );
1243
1244 return status;
1245}
1246
1247static NTSTATUS net_update_dns_ext(struct net_context *c,
1248 TALLOC_CTX *mem_ctx, ADS_STRUCT *ads,
1249 const char *hostname,
1250 struct sockaddr_storage *iplist,
1251 int num_addrs)
1252{
1253 struct sockaddr_storage *iplist_alloc = NULL;
1254 fstring machine_name;
1255 NTSTATUS status;
1256
1257 if (hostname) {
1258 fstrcpy(machine_name, hostname);
1259 } else {
1260 name_to_fqdn( machine_name, global_myname() );
1261 }
1262 strlower_m( machine_name );
1263
1264 if (num_addrs == 0 || iplist == NULL) {
1265 /*
1266 * Get our ip address
1267 * (not the 127.0.0.x address but a real ip address)
1268 */
1269 num_addrs = get_my_ip_address(&iplist_alloc);
1270 if ( num_addrs <= 0 ) {
1271 DEBUG(4, ("net_update_dns_ext: Failed to find my "
1272 "non-loopback IP addresses!\n"));
1273 return NT_STATUS_INVALID_PARAMETER;
1274 }
1275 iplist = iplist_alloc;
1276 }
1277
1278 status = net_update_dns_internal(c, mem_ctx, ads, machine_name,
1279 iplist, num_addrs);
1280
1281 SAFE_FREE(iplist_alloc);
1282 return status;
1283}
1284
1285static NTSTATUS net_update_dns(struct net_context *c, TALLOC_CTX *mem_ctx, ADS_STRUCT *ads, const char *hostname)
1286{
1287 NTSTATUS status;
1288
1289 status = net_update_dns_ext(c, mem_ctx, ads, hostname, NULL, 0);
1290 return status;
1291}
1292#endif
1293
1294
1295/*******************************************************************
1296 ********************************************************************/
1297
1298static int net_ads_join_usage(struct net_context *c, int argc, const char **argv)
1299{
1300 d_printf(_("net ads join [options]\n"
1301 "Valid options:\n"));
1302 d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1303 " The deault UPN is in the form host/netbiosname@REALM.\n"));
1304 d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1305 " The OU string read from top to bottom without RDNs and delimited by a '/'.\n"
1306 " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1307 " NB: A backslash '\\' is used as escape at multiple levels and may\n"
1308 " need to be doubled or even quadrupled. It is not used as a separator.\n"));
1309 d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1310 d_printf(_(" osVer=string Set the operatingSystemVersion attribute during the join.\n"
1311 " NB: osName and osVer must be specified together for either to take effect.\n"
1312 " Also, the operatingSystemService attribute is also set when along with\n"
1313 " the two other attributes.\n"));
1314
1315 return -1;
1316}
1317
1318/*******************************************************************
1319 ********************************************************************/
1320
1321int net_ads_join(struct net_context *c, int argc, const char **argv)
1322{
1323 TALLOC_CTX *ctx = NULL;
1324 struct libnet_JoinCtx *r = NULL;
1325 const char *domain = lp_realm();
1326 WERROR werr = WERR_SETUP_NOT_JOINED;
1327 bool createupn = false;
1328 const char *machineupn = NULL;
1329 const char *create_in_ou = NULL;
1330 int i;
1331 const char *os_name = NULL;
1332 const char *os_version = NULL;
1333 bool modify_config = lp_config_backend_is_registry();
1334
1335 if (c->display_usage)
1336 return net_ads_join_usage(c, argc, argv);
1337
1338 if (!modify_config) {
1339
1340 werr = check_ads_config();
1341 if (!W_ERROR_IS_OK(werr)) {
1342 d_fprintf(stderr, _("Invalid configuration. Exiting....\n"));
1343 goto fail;
1344 }
1345 }
1346
1347 if (!(ctx = talloc_init("net_ads_join"))) {
1348 d_fprintf(stderr, _("Could not initialise talloc context.\n"));
1349 werr = WERR_NOMEM;
1350 goto fail;
1351 }
1352
1353 if (!c->opt_kerberos) {
1354 use_in_memory_ccache();
1355 }
1356
1357 werr = libnet_init_JoinCtx(ctx, &r);
1358 if (!W_ERROR_IS_OK(werr)) {
1359 goto fail;
1360 }
1361
1362 /* process additional command line args */
1363
1364 for ( i=0; i<argc; i++ ) {
1365 if ( !StrnCaseCmp(argv[i], "createupn", strlen("createupn")) ) {
1366 createupn = true;
1367 machineupn = get_string_param(argv[i]);
1368 }
1369 else if ( !StrnCaseCmp(argv[i], "createcomputer", strlen("createcomputer")) ) {
1370 if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
1371 d_fprintf(stderr, _("Please supply a valid OU path.\n"));
1372 werr = WERR_INVALID_PARAM;
1373 goto fail;
1374 }
1375 }
1376 else if ( !StrnCaseCmp(argv[i], "osName", strlen("osName")) ) {
1377 if ( (os_name = get_string_param(argv[i])) == NULL ) {
1378 d_fprintf(stderr, _("Please supply a operating system name.\n"));
1379 werr = WERR_INVALID_PARAM;
1380 goto fail;
1381 }
1382 }
1383 else if ( !StrnCaseCmp(argv[i], "osVer", strlen("osVer")) ) {
1384 if ( (os_version = get_string_param(argv[i])) == NULL ) {
1385 d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
1386 werr = WERR_INVALID_PARAM;
1387 goto fail;
1388 }
1389 }
1390 else {
1391 domain = argv[i];
1392 }
1393 }
1394
1395 if (!*domain) {
1396 d_fprintf(stderr, _("Please supply a valid domain name\n"));
1397 werr = WERR_INVALID_PARAM;
1398 goto fail;
1399 }
1400
1401 if (!c->msg_ctx) {
1402 d_fprintf(stderr, _("Could not initialise message context. "
1403 "Try running as root\n"));
1404 werr = WERR_ACCESS_DENIED;
1405 goto fail;
1406 }
1407
1408 /* Do the domain join here */
1409
1410 r->in.domain_name = domain;
1411 r->in.create_upn = createupn;
1412 r->in.upn = machineupn;
1413 r->in.account_ou = create_in_ou;
1414 r->in.os_name = os_name;
1415 r->in.os_version = os_version;
1416 r->in.dc_name = c->opt_host;
1417 r->in.admin_account = c->opt_user_name;
1418 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1419 r->in.debug = true;
1420 r->in.use_kerberos = c->opt_kerberos;
1421 r->in.modify_config = modify_config;
1422 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1423 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
1424 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
1425 r->in.msg_ctx = c->msg_ctx;
1426
1427 werr = libnet_Join(ctx, r);
1428 if (W_ERROR_EQUAL(werr, WERR_DCNOTFOUND) &&
1429 strequal(domain, lp_realm())) {
1430 r->in.domain_name = lp_workgroup();
1431 werr = libnet_Join(ctx, r);
1432 }
1433 if (!W_ERROR_IS_OK(werr)) {
1434 goto fail;
1435 }
1436
1437 /* Check the short name of the domain */
1438
1439 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
1440 d_printf(_("The workgroup in %s does not match the short\n"
1441 "domain name obtained from the server.\n"
1442 "Using the name [%s] from the server.\n"
1443 "You should set \"workgroup = %s\" in %s.\n"),
1444 get_dyn_CONFIGFILE(), r->out.netbios_domain_name,
1445 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
1446 }
1447
1448 d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name);
1449
1450 if (r->out.dns_domain_name) {
1451 d_printf(_("Joined '%s' to dns domain '%s'\n"), r->in.machine_name,
1452 r->out.dns_domain_name);
1453 } else {
1454 d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name,
1455 r->out.netbios_domain_name);
1456 }
1457
1458#if defined(WITH_DNS_UPDATES)
1459 /*
1460 * In a clustered environment, don't do dynamic dns updates:
1461 * Registering the set of ip addresses that are assigned to
1462 * the interfaces of the node that performs the join does usually
1463 * not have the desired effect, since the local interfaces do not
1464 * carry the complete set of the cluster's public IP addresses.
1465 * And it can also contain internal addresses that should not
1466 * be visible to the outside at all.
1467 * In order to do dns updates in a clustererd setup, use
1468 * net ads dns register.
1469 */
1470 if (lp_clustering()) {
1471 d_fprintf(stderr, _("Not doing automatic DNS update in a"
1472 "clustered setup.\n"));
1473 goto done;
1474 }
1475
1476 if (r->out.domain_is_ad) {
1477 /* We enter this block with user creds */
1478 ADS_STRUCT *ads_dns = NULL;
1479
1480 if ( (ads_dns = ads_init( lp_realm(), NULL, NULL )) != NULL ) {
1481 /* kinit with the machine password */
1482
1483 use_in_memory_ccache();
1484 if (asprintf( &ads_dns->auth.user_name, "%s$", global_myname()) == -1) {
1485 goto fail;
1486 }
1487 ads_dns->auth.password = secrets_fetch_machine_password(
1488 r->out.netbios_domain_name, NULL, NULL );
1489 ads_dns->auth.realm = SMB_STRDUP( r->out.dns_domain_name );
1490 strupper_m(ads_dns->auth.realm );
1491 ads_kinit_password( ads_dns );
1492 }
1493
1494 if ( !ads_dns || !NT_STATUS_IS_OK(net_update_dns(c, ctx, ads_dns, NULL)) ) {
1495 d_fprintf( stderr, _("DNS update failed!\n") );
1496 }
1497
1498 /* exit from this block using machine creds */
1499 ads_destroy(&ads_dns);
1500 }
1501
1502done:
1503#endif
1504
1505 TALLOC_FREE(r);
1506 TALLOC_FREE( ctx );
1507
1508 return 0;
1509
1510fail:
1511 /* issue an overall failure message at the end. */
1512 d_printf(_("Failed to join domain: %s\n"),
1513 r && r->out.error_string ? r->out.error_string :
1514 get_friendly_werror_msg(werr));
1515 TALLOC_FREE( ctx );
1516
1517 return -1;
1518}
1519
1520/*******************************************************************
1521 ********************************************************************/
1522
1523static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
1524{
1525#if defined(WITH_DNS_UPDATES)
1526 ADS_STRUCT *ads;
1527 ADS_STATUS status;
1528 NTSTATUS ntstatus;
1529 TALLOC_CTX *ctx;
1530 const char *hostname = NULL;
1531 const char **addrs_list = NULL;
1532 struct sockaddr_storage *addrs = NULL;
1533 int num_addrs = 0;
1534 int count;
1535
1536#ifdef DEVELOPER
1537 talloc_enable_leak_report();
1538#endif
1539
1540 if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
1541 d_fprintf(stderr, _("Refusing DNS updates with automatic "
1542 "detection of addresses in a clustered "
1543 "setup.\n"));
1544 c->display_usage = true;
1545 }
1546
1547 if (c->display_usage) {
1548 d_printf( "%s\n"
1549 "net ads dns register [hostname [IP [IP...]]]\n"
1550 " %s\n",
1551 _("Usage:"),
1552 _("Register hostname with DNS\n"));
1553 return -1;
1554 }
1555
1556 if (!(ctx = talloc_init("net_ads_dns"))) {
1557 d_fprintf(stderr, _("Could not initialise talloc context\n"));
1558 return -1;
1559 }
1560
1561 if (argc >= 1) {
1562 hostname = argv[0];
1563 }
1564
1565 if (argc > 1) {
1566 num_addrs = argc - 1;
1567 addrs_list = &argv[1];
1568 } else if (lp_clustering()) {
1569 addrs_list = lp_cluster_addresses();
1570 num_addrs = str_list_length(addrs_list);
1571 }
1572
1573 if (num_addrs > 0) {
1574 addrs = talloc_zero_array(ctx, struct sockaddr_storage, num_addrs);
1575 if (addrs == NULL) {
1576 d_fprintf(stderr, _("Error allocating memory!\n"));
1577 talloc_free(ctx);
1578 return -1;
1579 }
1580 }
1581
1582 for (count = 0; count < num_addrs; count++) {
1583 if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
1584 d_fprintf(stderr, "%s '%s'.\n",
1585 _("Cannot interpret address"),
1586 addrs_list[count]);
1587 talloc_free(ctx);
1588 return -1;
1589 }
1590 }
1591
1592 status = ads_startup(c, true, &ads);
1593 if ( !ADS_ERR_OK(status) ) {
1594 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1595 TALLOC_FREE(ctx);
1596 return -1;
1597 }
1598
1599 ntstatus = net_update_dns_ext(c, ctx, ads, hostname, addrs, num_addrs);
1600 if (!NT_STATUS_IS_OK(ntstatus)) {
1601 d_fprintf( stderr, _("DNS update failed!\n") );
1602 ads_destroy( &ads );
1603 TALLOC_FREE( ctx );
1604 return -1;
1605 }
1606
1607 d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
1608
1609 ads_destroy(&ads);
1610 TALLOC_FREE( ctx );
1611
1612 return 0;
1613#else
1614 d_fprintf(stderr,
1615 _("DNS update support not enabled at compile time!\n"));
1616 return -1;
1617#endif
1618}
1619
1620static int net_ads_dns_gethostbyname(struct net_context *c, int argc, const char **argv)
1621{
1622#if defined(WITH_DNS_UPDATES)
1623 DNS_ERROR err;
1624
1625#ifdef DEVELOPER
1626 talloc_enable_leak_report();
1627#endif
1628
1629 if (argc != 2 || c->display_usage) {
1630 d_printf( "%s\n"
1631 " %s\n"
1632 " %s\n",
1633 _("Usage:"),
1634 _("net ads dns gethostbyname <server> <name>\n"),
1635 _(" Look up hostname from the AD\n"
1636 " server\tName server to use\n"
1637 " name\tName to look up\n"));
1638 return -1;
1639 }
1640
1641 err = do_gethostbyname(argv[0], argv[1]);
1642
1643 d_printf(_("do_gethostbyname returned %s (%d)\n"),
1644 dns_errstr(err), ERROR_DNS_V(err));
1645#endif
1646 return 0;
1647}
1648
1649static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
1650{
1651 struct functable func[] = {
1652 {
1653 "register",
1654 net_ads_dns_register,
1655 NET_TRANSPORT_ADS,
1656 N_("Add host dns entry to AD"),
1657 N_("net ads dns register\n"
1658 " Add host dns entry to AD")
1659 },
1660 {
1661 "gethostbyname",
1662 net_ads_dns_gethostbyname,
1663 NET_TRANSPORT_ADS,
1664 N_("Look up host"),
1665 N_("net ads dns gethostbyname\n"
1666 " Look up host")
1667 },
1668 {NULL, NULL, 0, NULL, NULL}
1669 };
1670
1671 return net_run_function(c, argc, argv, "net ads dns", func);
1672}
1673
1674/*******************************************************************
1675 ********************************************************************/
1676
1677int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
1678{
1679 d_printf(_(
1680"\nnet ads printer search <printer>"
1681"\n\tsearch for a printer in the directory\n"
1682"\nnet ads printer info <printer> <server>"
1683"\n\tlookup info in directory for printer on server"
1684"\n\t(note: printer defaults to \"*\", server defaults to local)\n"
1685"\nnet ads printer publish <printername>"
1686"\n\tpublish printer in directory"
1687"\n\t(note: printer name is required)\n"
1688"\nnet ads printer remove <printername>"
1689"\n\tremove printer from directory"
1690"\n\t(note: printer name is required)\n"));
1691 return -1;
1692}
1693
1694/*******************************************************************
1695 ********************************************************************/
1696
1697static int net_ads_printer_search(struct net_context *c, int argc, const char **argv)
1698{
1699 ADS_STRUCT *ads;
1700 ADS_STATUS rc;
1701 LDAPMessage *res = NULL;
1702
1703 if (c->display_usage) {
1704 d_printf( "%s\n"
1705 "net ads printer search\n"
1706 " %s\n",
1707 _("Usage:"),
1708 _("List printers in the AD"));
1709 return 0;
1710 }
1711
1712 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
1713 return -1;
1714 }
1715
1716 rc = ads_find_printers(ads, &res);
1717
1718 if (!ADS_ERR_OK(rc)) {
1719 d_fprintf(stderr, _("ads_find_printer: %s\n"), ads_errstr(rc));
1720 ads_msgfree(ads, res);
1721 ads_destroy(&ads);
1722 return -1;
1723 }
1724
1725 if (ads_count_replies(ads, res) == 0) {
1726 d_fprintf(stderr, _("No results found\n"));
1727 ads_msgfree(ads, res);
1728 ads_destroy(&ads);
1729 return -1;
1730 }
1731
1732 ads_dump(ads, res);
1733 ads_msgfree(ads, res);
1734 ads_destroy(&ads);
1735 return 0;
1736}
1737
1738static int net_ads_printer_info(struct net_context *c, int argc, const char **argv)
1739{
1740 ADS_STRUCT *ads;
1741 ADS_STATUS rc;
1742 const char *servername, *printername;
1743 LDAPMessage *res = NULL;
1744
1745 if (c->display_usage) {
1746 d_printf("%s\n%s",
1747 _("Usage:"),
1748 _("net ads printer info [printername [servername]]\n"
1749 " Display printer info from AD\n"
1750 " printername\tPrinter name or wildcard\n"
1751 " servername\tName of the print server\n"));
1752 return 0;
1753 }
1754
1755 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
1756 return -1;
1757 }
1758
1759 if (argc > 0) {
1760 printername = argv[0];
1761 } else {
1762 printername = "*";
1763 }
1764
1765 if (argc > 1) {
1766 servername = argv[1];
1767 } else {
1768 servername = global_myname();
1769 }
1770
1771 rc = ads_find_printer_on_server(ads, &res, printername, servername);
1772
1773 if (!ADS_ERR_OK(rc)) {
1774 d_fprintf(stderr, _("Server '%s' not found: %s\n"),
1775 servername, ads_errstr(rc));
1776 ads_msgfree(ads, res);
1777 ads_destroy(&ads);
1778 return -1;
1779 }
1780
1781 if (ads_count_replies(ads, res) == 0) {
1782 d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
1783 ads_msgfree(ads, res);
1784 ads_destroy(&ads);
1785 return -1;
1786 }
1787
1788 ads_dump(ads, res);
1789 ads_msgfree(ads, res);
1790 ads_destroy(&ads);
1791
1792 return 0;
1793}
1794
1795static int net_ads_printer_publish(struct net_context *c, int argc, const char **argv)
1796{
1797 ADS_STRUCT *ads;
1798 ADS_STATUS rc;
1799 const char *servername, *printername;
1800 struct cli_state *cli = NULL;
1801 struct rpc_pipe_client *pipe_hnd = NULL;
1802 struct sockaddr_storage server_ss;
1803 NTSTATUS nt_status;
1804 TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
1805 ADS_MODLIST mods = ads_init_mods(mem_ctx);
1806 char *prt_dn, *srv_dn, **srv_cn;
1807 char *srv_cn_escaped = NULL, *printername_escaped = NULL;
1808 LDAPMessage *res = NULL;
1809
1810 if (argc < 1 || c->display_usage) {
1811 d_printf("%s\n%s",
1812 _("Usage:"),
1813 _("net ads printer publish <printername> [servername]\n"
1814 " Publish printer in AD\n"
1815 " printername\tName of the printer\n"
1816 " servername\tName of the print server\n"));
1817 talloc_destroy(mem_ctx);
1818 return -1;
1819 }
1820
1821 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
1822 talloc_destroy(mem_ctx);
1823 return -1;
1824 }
1825
1826 printername = argv[0];
1827
1828 if (argc == 2) {
1829 servername = argv[1];
1830 } else {
1831 servername = global_myname();
1832 }
1833
1834 /* Get printer data from SPOOLSS */
1835
1836 resolve_name(servername, &server_ss, 0x20, false);
1837
1838 nt_status = cli_full_connection(&cli, global_myname(), servername,
1839 &server_ss, 0,
1840 "IPC$", "IPC",
1841 c->opt_user_name, c->opt_workgroup,
1842 c->opt_password ? c->opt_password : "",
1843 CLI_FULL_CONNECTION_USE_KERBEROS,
1844 Undefined);
1845
1846 if (NT_STATUS_IS_ERR(nt_status)) {
1847 d_fprintf(stderr, _("Unable to open a connection to %s to "
1848 "obtain data for %s\n"),
1849 servername, printername);
1850 ads_destroy(&ads);
1851 talloc_destroy(mem_ctx);
1852 return -1;
1853 }
1854
1855 /* Publish on AD server */
1856
1857 ads_find_machine_acct(ads, &res, servername);
1858
1859 if (ads_count_replies(ads, res) == 0) {
1860 d_fprintf(stderr, _("Could not find machine account for server "
1861 "%s\n"),
1862 servername);
1863 ads_destroy(&ads);
1864 talloc_destroy(mem_ctx);
1865 return -1;
1866 }
1867
1868 srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
1869 srv_cn = ldap_explode_dn(srv_dn, 1);
1870
1871 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
1872 printername_escaped = escape_rdn_val_string_alloc(printername);
1873 if (!srv_cn_escaped || !printername_escaped) {
1874 SAFE_FREE(srv_cn_escaped);
1875 SAFE_FREE(printername_escaped);
1876 d_fprintf(stderr, _("Internal error, out of memory!"));
1877 ads_destroy(&ads);
1878 talloc_destroy(mem_ctx);
1879 return -1;
1880 }
1881
1882 if (asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, printername_escaped, srv_dn) == -1) {
1883 SAFE_FREE(srv_cn_escaped);
1884 SAFE_FREE(printername_escaped);
1885 d_fprintf(stderr, _("Internal error, out of memory!"));
1886 ads_destroy(&ads);
1887 talloc_destroy(mem_ctx);
1888 return -1;
1889 }
1890
1891 SAFE_FREE(srv_cn_escaped);
1892 SAFE_FREE(printername_escaped);
1893
1894 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss.syntax_id, &pipe_hnd);
1895 if (!NT_STATUS_IS_OK(nt_status)) {
1896 d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
1897 servername);
1898 SAFE_FREE(prt_dn);
1899 ads_destroy(&ads);
1900 talloc_destroy(mem_ctx);
1901 return -1;
1902 }
1903
1904 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
1905 printername))) {
1906 SAFE_FREE(prt_dn);
1907 ads_destroy(&ads);
1908 talloc_destroy(mem_ctx);
1909 return -1;
1910 }
1911
1912 rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
1913 if (!ADS_ERR_OK(rc)) {
1914 d_fprintf(stderr, "ads_publish_printer: %s\n", ads_errstr(rc));
1915 SAFE_FREE(prt_dn);
1916 ads_destroy(&ads);
1917 talloc_destroy(mem_ctx);
1918 return -1;
1919 }
1920
1921 d_printf("published printer\n");
1922 SAFE_FREE(prt_dn);
1923 ads_destroy(&ads);
1924 talloc_destroy(mem_ctx);
1925
1926 return 0;
1927}
1928
1929static int net_ads_printer_remove(struct net_context *c, int argc, const char **argv)
1930{
1931 ADS_STRUCT *ads;
1932 ADS_STATUS rc;
1933 const char *servername;
1934 char *prt_dn;
1935 LDAPMessage *res = NULL;
1936
1937 if (argc < 1 || c->display_usage) {
1938 d_printf("%s\n%s",
1939 _("Usage:"),
1940 _("net ads printer remove <printername> [servername]\n"
1941 " Remove a printer from the AD\n"
1942 " printername\tName of the printer\n"
1943 " servername\tName of the print server\n"));
1944 return -1;
1945 }
1946
1947 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
1948 return -1;
1949 }
1950
1951 if (argc > 1) {
1952 servername = argv[1];
1953 } else {
1954 servername = global_myname();
1955 }
1956
1957 rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
1958
1959 if (!ADS_ERR_OK(rc)) {
1960 d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"), ads_errstr(rc));
1961 ads_msgfree(ads, res);
1962 ads_destroy(&ads);
1963 return -1;
1964 }
1965
1966 if (ads_count_replies(ads, res) == 0) {
1967 d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
1968 ads_msgfree(ads, res);
1969 ads_destroy(&ads);
1970 return -1;
1971 }
1972
1973 prt_dn = ads_get_dn(ads, talloc_tos(), res);
1974 ads_msgfree(ads, res);
1975 rc = ads_del_dn(ads, prt_dn);
1976 TALLOC_FREE(prt_dn);
1977
1978 if (!ADS_ERR_OK(rc)) {
1979 d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(rc));
1980 ads_destroy(&ads);
1981 return -1;
1982 }
1983
1984 ads_destroy(&ads);
1985 return 0;
1986}
1987
1988static int net_ads_printer(struct net_context *c, int argc, const char **argv)
1989{
1990 struct functable func[] = {
1991 {
1992 "search",
1993 net_ads_printer_search,
1994 NET_TRANSPORT_ADS,
1995 N_("Search for a printer"),
1996 N_("net ads printer search\n"
1997 " Search for a printer")
1998 },
1999 {
2000 "info",
2001 net_ads_printer_info,
2002 NET_TRANSPORT_ADS,
2003 N_("Display printer information"),
2004 N_("net ads printer info\n"
2005 " Display printer information")
2006 },
2007 {
2008 "publish",
2009 net_ads_printer_publish,
2010 NET_TRANSPORT_ADS,
2011 N_("Publish a printer"),
2012 N_("net ads printer publish\n"
2013 " Publish a printer")
2014 },
2015 {
2016 "remove",
2017 net_ads_printer_remove,
2018 NET_TRANSPORT_ADS,
2019 N_("Delete a printer"),
2020 N_("net ads printer remove\n"
2021 " Delete a printer")
2022 },
2023 {NULL, NULL, 0, NULL, NULL}
2024 };
2025
2026 return net_run_function(c, argc, argv, "net ads printer", func);
2027}
2028
2029
2030static int net_ads_password(struct net_context *c, int argc, const char **argv)
2031{
2032 ADS_STRUCT *ads;
2033 const char *auth_principal = c->opt_user_name;
2034 const char *auth_password = c->opt_password;
2035 char *realm = NULL;
2036 char *new_password = NULL;
2037 char *chr, *prompt;
2038 const char *user;
2039 ADS_STATUS ret;
2040
2041 if (c->display_usage) {
2042 d_printf("%s\n%s",
2043 _("Usage:"),
2044 _("net ads password <username>\n"
2045 " Change password for user\n"
2046 " username\tName of user to change password for\n"));
2047 return 0;
2048 }
2049
2050 if (c->opt_user_name == NULL || c->opt_password == NULL) {
2051 d_fprintf(stderr, _("You must supply an administrator "
2052 "username/password\n"));
2053 return -1;
2054 }
2055
2056 if (argc < 1) {
2057 d_fprintf(stderr, _("ERROR: You must say which username to "
2058 "change password for\n"));
2059 return -1;
2060 }
2061
2062 user = argv[0];
2063 if (!strchr_m(user, '@')) {
2064 if (asprintf(&chr, "%s@%s", argv[0], lp_realm()) == -1) {
2065 return -1;
2066 }
2067 user = chr;
2068 }
2069
2070 use_in_memory_ccache();
2071 chr = strchr_m(auth_principal, '@');
2072 if (chr) {
2073 realm = ++chr;
2074 } else {
2075 realm = lp_realm();
2076 }
2077
2078 /* use the realm so we can eventually change passwords for users
2079 in realms other than default */
2080 if (!(ads = ads_init(realm, c->opt_workgroup, c->opt_host))) {
2081 return -1;
2082 }
2083
2084 /* we don't actually need a full connect, but it's the easy way to
2085 fill in the KDC's addresss */
2086 ads_connect(ads);
2087
2088 if (!ads->config.realm) {
2089 d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
2090 ads_destroy(&ads);
2091 return -1;
2092 }
2093
2094 if (argv[1]) {
2095 new_password = (char *)argv[1];
2096 } else {
2097 if (asprintf(&prompt, _("Enter new password for %s:"), user) == -1) {
2098 return -1;
2099 }
2100 new_password = getpass(prompt);
2101 free(prompt);
2102 }
2103
2104 ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
2105 auth_password, user, new_password, ads->auth.time_offset);
2106 if (!ADS_ERR_OK(ret)) {
2107 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
2108 ads_destroy(&ads);
2109 return -1;
2110 }
2111
2112 d_printf(_("Password change for %s completed.\n"), user);
2113 ads_destroy(&ads);
2114
2115 return 0;
2116}
2117
2118int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2119{
2120 ADS_STRUCT *ads;
2121 char *host_principal;
2122 fstring my_name;
2123 ADS_STATUS ret;
2124
2125 if (c->display_usage) {
2126 d_printf( "%s\n"
2127 "net ads changetrustpw\n"
2128 " %s\n",
2129 _("Usage:"),
2130 _("Change the machine account's trust password"));
2131 return 0;
2132 }
2133
2134 if (!secrets_init()) {
2135 DEBUG(1,("Failed to initialise secrets database\n"));
2136 return -1;
2137 }
2138
2139 net_use_krb_machine_account(c);
2140
2141 use_in_memory_ccache();
2142
2143 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2144 return -1;
2145 }
2146
2147 fstrcpy(my_name, global_myname());
2148 strlower_m(my_name);
2149 if (asprintf(&host_principal, "%s$@%s", my_name, ads->config.realm) == -1) {
2150 ads_destroy(&ads);
2151 return -1;
2152 }
2153 d_printf(_("Changing password for principal: %s\n"), host_principal);
2154
2155 ret = ads_change_trust_account_password(ads, host_principal);
2156
2157 if (!ADS_ERR_OK(ret)) {
2158 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
2159 ads_destroy(&ads);
2160 SAFE_FREE(host_principal);
2161 return -1;
2162 }
2163
2164 d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2165
2166 if (USE_SYSTEM_KEYTAB) {
2167 d_printf(_("Attempting to update system keytab with new password.\n"));
2168 if (ads_keytab_create_default(ads)) {
2169 d_printf(_("Failed to update system keytab.\n"));
2170 }
2171 }
2172
2173 ads_destroy(&ads);
2174 SAFE_FREE(host_principal);
2175
2176 return 0;
2177}
2178
2179/*
2180 help for net ads search
2181*/
2182static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2183{
2184 d_printf(_(
2185 "\nnet ads search <expression> <attributes...>\n"
2186 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2187 "The expression is a standard LDAP search expression, and the\n"
2188 "attributes are a list of LDAP fields to show in the results.\n\n"
2189 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2190 ));
2191 net_common_flags_usage(c, argc, argv);
2192 return -1;
2193}
2194
2195
2196/*
2197 general ADS search function. Useful in diagnosing problems in ADS
2198*/
2199static int net_ads_search(struct net_context *c, int argc, const char **argv)
2200{
2201 ADS_STRUCT *ads;
2202 ADS_STATUS rc;
2203 const char *ldap_exp;
2204 const char **attrs;
2205 LDAPMessage *res = NULL;
2206
2207 if (argc < 1 || c->display_usage) {
2208 return net_ads_search_usage(c, argc, argv);
2209 }
2210
2211 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2212 return -1;
2213 }
2214
2215 ldap_exp = argv[0];
2216 attrs = (argv + 1);
2217
2218 rc = ads_do_search_retry(ads, ads->config.bind_path,
2219 LDAP_SCOPE_SUBTREE,
2220 ldap_exp, attrs, &res);
2221 if (!ADS_ERR_OK(rc)) {
2222 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2223 ads_destroy(&ads);
2224 return -1;
2225 }
2226
2227 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2228
2229 /* dump the results */
2230 ads_dump(ads, res);
2231
2232 ads_msgfree(ads, res);
2233 ads_destroy(&ads);
2234
2235 return 0;
2236}
2237
2238
2239/*
2240 help for net ads search
2241*/
2242static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2243{
2244 d_printf(_(
2245 "\nnet ads dn <dn> <attributes...>\n"
2246 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2247 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2248 "to show in the results\n\n"
2249 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2250 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2251 ));
2252 net_common_flags_usage(c, argc, argv);
2253 return -1;
2254}
2255
2256
2257/*
2258 general ADS search function. Useful in diagnosing problems in ADS
2259*/
2260static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2261{
2262 ADS_STRUCT *ads;
2263 ADS_STATUS rc;
2264 const char *dn;
2265 const char **attrs;
2266 LDAPMessage *res = NULL;
2267
2268 if (argc < 1 || c->display_usage) {
2269 return net_ads_dn_usage(c, argc, argv);
2270 }
2271
2272 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2273 return -1;
2274 }
2275
2276 dn = argv[0];
2277 attrs = (argv + 1);
2278
2279 rc = ads_do_search_all(ads, dn,
2280 LDAP_SCOPE_BASE,
2281 "(objectclass=*)", attrs, &res);
2282 if (!ADS_ERR_OK(rc)) {
2283 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2284 ads_destroy(&ads);
2285 return -1;
2286 }
2287
2288 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2289
2290 /* dump the results */
2291 ads_dump(ads, res);
2292
2293 ads_msgfree(ads, res);
2294 ads_destroy(&ads);
2295
2296 return 0;
2297}
2298
2299/*
2300 help for net ads sid search
2301*/
2302static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2303{
2304 d_printf(_(
2305 "\nnet ads sid <sid> <attributes...>\n"
2306 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2307 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2308 "to show in the results\n\n"
2309 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2310 ));
2311 net_common_flags_usage(c, argc, argv);
2312 return -1;
2313}
2314
2315
2316/*
2317 general ADS search function. Useful in diagnosing problems in ADS
2318*/
2319static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2320{
2321 ADS_STRUCT *ads;
2322 ADS_STATUS rc;
2323 const char *sid_string;
2324 const char **attrs;
2325 LDAPMessage *res = NULL;
2326 struct dom_sid sid;
2327
2328 if (argc < 1 || c->display_usage) {
2329 return net_ads_sid_usage(c, argc, argv);
2330 }
2331
2332 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2333 return -1;
2334 }
2335
2336 sid_string = argv[0];
2337 attrs = (argv + 1);
2338
2339 if (!string_to_sid(&sid, sid_string)) {
2340 d_fprintf(stderr, _("could not convert sid\n"));
2341 ads_destroy(&ads);
2342 return -1;
2343 }
2344
2345 rc = ads_search_retry_sid(ads, &res, &sid, attrs);
2346 if (!ADS_ERR_OK(rc)) {
2347 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2348 ads_destroy(&ads);
2349 return -1;
2350 }
2351
2352 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2353
2354 /* dump the results */
2355 ads_dump(ads, res);
2356
2357 ads_msgfree(ads, res);
2358 ads_destroy(&ads);
2359
2360 return 0;
2361}
2362
2363static int net_ads_keytab_flush(struct net_context *c, int argc, const char **argv)
2364{
2365 int ret;
2366 ADS_STRUCT *ads;
2367
2368 if (c->display_usage) {
2369 d_printf( "%s\n"
2370 "net ads keytab flush\n"
2371 " %s\n",
2372 _("Usage:"),
2373 _("Delete the whole keytab"));
2374 return 0;
2375 }
2376
2377 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2378 return -1;
2379 }
2380 ret = ads_keytab_flush(ads);
2381 ads_destroy(&ads);
2382 return ret;
2383}
2384
2385static int net_ads_keytab_add(struct net_context *c, int argc, const char **argv)
2386{
2387 int i;
2388 int ret = 0;
2389 ADS_STRUCT *ads;
2390
2391 if (c->display_usage) {
2392 d_printf("%s\n%s",
2393 _("Usage:"),
2394 _("net ads keytab add <principal> [principal ...]\n"
2395 " Add principals to local keytab\n"
2396 " principal\tKerberos principal to add to "
2397 "keytab\n"));
2398 return 0;
2399 }
2400
2401 d_printf(_("Processing principals to add...\n"));
2402 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2403 return -1;
2404 }
2405 for (i = 0; i < argc; i++) {
2406 ret |= ads_keytab_add_entry(ads, argv[i]);
2407 }
2408 ads_destroy(&ads);
2409 return ret;
2410}
2411
2412static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
2413{
2414 ADS_STRUCT *ads;
2415 int ret;
2416
2417 if (c->display_usage) {
2418 d_printf( "%s\n"
2419 "net ads keytab create\n"
2420 " %s\n",
2421 _("Usage:"),
2422 _("Create new default keytab"));
2423 return 0;
2424 }
2425
2426 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2427 return -1;
2428 }
2429 ret = ads_keytab_create_default(ads);
2430 ads_destroy(&ads);
2431 return ret;
2432}
2433
2434static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
2435{
2436 const char *keytab = NULL;
2437
2438 if (c->display_usage) {
2439 d_printf("%s\n%s",
2440 _("Usage:"),
2441 _("net ads keytab list [keytab]\n"
2442 " List a local keytab\n"
2443 " keytab\tKeytab to list\n"));
2444 return 0;
2445 }
2446
2447 if (argc >= 1) {
2448 keytab = argv[0];
2449 }
2450
2451 return ads_keytab_list(keytab);
2452}
2453
2454
2455int net_ads_keytab(struct net_context *c, int argc, const char **argv)
2456{
2457 struct functable func[] = {
2458 {
2459 "add",
2460 net_ads_keytab_add,
2461 NET_TRANSPORT_ADS,
2462 N_("Add a service principal"),
2463 N_("net ads keytab add\n"
2464 " Add a service principal")
2465 },
2466 {
2467 "create",
2468 net_ads_keytab_create,
2469 NET_TRANSPORT_ADS,
2470 N_("Create a fresh keytab"),
2471 N_("net ads keytab create\n"
2472 " Create a fresh keytab")
2473 },
2474 {
2475 "flush",
2476 net_ads_keytab_flush,
2477 NET_TRANSPORT_ADS,
2478 N_("Remove all keytab entries"),
2479 N_("net ads keytab flush\n"
2480 " Remove all keytab entries")
2481 },
2482 {
2483 "list",
2484 net_ads_keytab_list,
2485 NET_TRANSPORT_ADS,
2486 N_("List a keytab"),
2487 N_("net ads keytab list\n"
2488 " List a keytab")
2489 },
2490 {NULL, NULL, 0, NULL, NULL}
2491 };
2492
2493 if (!USE_KERBEROS_KEYTAB) {
2494 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
2495 "keytab method to use keytab functions.\n"));
2496 }
2497
2498 return net_run_function(c, argc, argv, "net ads keytab", func);
2499}
2500
2501static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
2502{
2503 int ret = -1;
2504
2505 if (c->display_usage) {
2506 d_printf( "%s\n"
2507 "net ads kerberos renew\n"
2508 " %s\n",
2509 _("Usage:"),
2510 _("Renew TGT from existing credential cache"));
2511 return 0;
2512 }
2513
2514 ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
2515 if (ret) {
2516 d_printf(_("failed to renew kerberos ticket: %s\n"),
2517 error_message(ret));
2518 }
2519 return ret;
2520}
2521
2522static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
2523{
2524 struct PAC_LOGON_INFO *info = NULL;
2525 TALLOC_CTX *mem_ctx = NULL;
2526 NTSTATUS status;
2527 int ret = -1;
2528 const char *impersonate_princ_s = NULL;
2529
2530 if (c->display_usage) {
2531 d_printf( "%s\n"
2532 "net ads kerberos pac\n"
2533 " %s\n",
2534 _("Usage:"),
2535 _("Dump the Kerberos PAC"));
2536 return 0;
2537 }
2538
2539 mem_ctx = talloc_init("net_ads_kerberos_pac");
2540 if (!mem_ctx) {
2541 goto out;
2542 }
2543
2544 if (argc > 0) {
2545 impersonate_princ_s = argv[0];
2546 }
2547
2548 c->opt_password = net_prompt_pass(c, c->opt_user_name);
2549
2550 status = kerberos_return_pac(mem_ctx,
2551 c->opt_user_name,
2552 c->opt_password,
2553 0,
2554 NULL,
2555 NULL,
2556 NULL,
2557 true,
2558 true,
2559 2592000, /* one month */
2560 impersonate_princ_s,
2561 &info);
2562 if (!NT_STATUS_IS_OK(status)) {
2563 d_printf(_("failed to query kerberos PAC: %s\n"),
2564 nt_errstr(status));
2565 goto out;
2566 }
2567
2568 if (info) {
2569 const char *s;
2570 s = NDR_PRINT_STRUCT_STRING(mem_ctx, PAC_LOGON_INFO, info);
2571 d_printf(_("The Pac: %s\n"), s);
2572 }
2573
2574 ret = 0;
2575 out:
2576 TALLOC_FREE(mem_ctx);
2577 return ret;
2578}
2579
2580static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
2581{
2582 TALLOC_CTX *mem_ctx = NULL;
2583 int ret = -1;
2584 NTSTATUS status;
2585
2586 if (c->display_usage) {
2587 d_printf( "%s\n"
2588 "net ads kerberos kinit\n"
2589 " %s\n",
2590 _("Usage:"),
2591 _("Get Ticket Granting Ticket (TGT) for the user"));
2592 return 0;
2593 }
2594
2595 mem_ctx = talloc_init("net_ads_kerberos_kinit");
2596 if (!mem_ctx) {
2597 goto out;
2598 }
2599
2600 c->opt_password = net_prompt_pass(c, c->opt_user_name);
2601
2602 ret = kerberos_kinit_password_ext(c->opt_user_name,
2603 c->opt_password,
2604 0,
2605 NULL,
2606 NULL,
2607 NULL,
2608 true,
2609 true,
2610 2592000, /* one month */
2611 &status);
2612 if (ret) {
2613 d_printf(_("failed to kinit password: %s\n"),
2614 nt_errstr(status));
2615 }
2616 out:
2617 return ret;
2618}
2619
2620int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
2621{
2622 struct functable func[] = {
2623 {
2624 "kinit",
2625 net_ads_kerberos_kinit,
2626 NET_TRANSPORT_ADS,
2627 N_("Retrieve Ticket Granting Ticket (TGT)"),
2628 N_("net ads kerberos kinit\n"
2629 " Receive Ticket Granting Ticket (TGT)")
2630 },
2631 {
2632 "renew",
2633 net_ads_kerberos_renew,
2634 NET_TRANSPORT_ADS,
2635 N_("Renew Ticket Granting Ticket from credential cache"),
2636 N_("net ads kerberos renew\n"
2637 " Renew Ticket Granting Ticket (TGT) from "
2638 "credential cache")
2639 },
2640 {
2641 "pac",
2642 net_ads_kerberos_pac,
2643 NET_TRANSPORT_ADS,
2644 N_("Dump Kerberos PAC"),
2645 N_("net ads kerberos pac\n"
2646 " Dump Kerberos PAC")
2647 },
2648 {NULL, NULL, 0, NULL, NULL}
2649 };
2650
2651 return net_run_function(c, argc, argv, "net ads kerberos", func);
2652}
2653
2654int net_ads(struct net_context *c, int argc, const char **argv)
2655{
2656 struct functable func[] = {
2657 {
2658 "info",
2659 net_ads_info,
2660 NET_TRANSPORT_ADS,
2661 N_("Display details on remote ADS server"),
2662 N_("net ads info\n"
2663 " Display details on remote ADS server")
2664 },
2665 {
2666 "join",
2667 net_ads_join,
2668 NET_TRANSPORT_ADS,
2669 N_("Join the local machine to ADS realm"),
2670 N_("net ads join\n"
2671 " Join the local machine to ADS realm")
2672 },
2673 {
2674 "testjoin",
2675 net_ads_testjoin,
2676 NET_TRANSPORT_ADS,
2677 N_("Validate machine account"),
2678 N_("net ads testjoin\n"
2679 " Validate machine account")
2680 },
2681 {
2682 "leave",
2683 net_ads_leave,
2684 NET_TRANSPORT_ADS,
2685 N_("Remove the local machine from ADS"),
2686 N_("net ads leave\n"
2687 " Remove the local machine from ADS")
2688 },
2689 {
2690 "status",
2691 net_ads_status,
2692 NET_TRANSPORT_ADS,
2693 N_("Display machine account details"),
2694 N_("net ads status\n"
2695 " Display machine account details")
2696 },
2697 {
2698 "user",
2699 net_ads_user,
2700 NET_TRANSPORT_ADS,
2701 N_("List/modify users"),
2702 N_("net ads user\n"
2703 " List/modify users")
2704 },
2705 {
2706 "group",
2707 net_ads_group,
2708 NET_TRANSPORT_ADS,
2709 N_("List/modify groups"),
2710 N_("net ads group\n"
2711 " List/modify groups")
2712 },
2713 {
2714 "dns",
2715 net_ads_dns,
2716 NET_TRANSPORT_ADS,
2717 N_("Issue dynamic DNS update"),
2718 N_("net ads dns\n"
2719 " Issue dynamic DNS update")
2720 },
2721 {
2722 "password",
2723 net_ads_password,
2724 NET_TRANSPORT_ADS,
2725 N_("Change user passwords"),
2726 N_("net ads password\n"
2727 " Change user passwords")
2728 },
2729 {
2730 "changetrustpw",
2731 net_ads_changetrustpw,
2732 NET_TRANSPORT_ADS,
2733 N_("Change trust account password"),
2734 N_("net ads changetrustpw\n"
2735 " Change trust account password")
2736 },
2737 {
2738 "printer",
2739 net_ads_printer,
2740 NET_TRANSPORT_ADS,
2741 N_("List/modify printer entries"),
2742 N_("net ads printer\n"
2743 " List/modify printer entries")
2744 },
2745 {
2746 "search",
2747 net_ads_search,
2748 NET_TRANSPORT_ADS,
2749 N_("Issue LDAP search using filter"),
2750 N_("net ads search\n"
2751 " Issue LDAP search using filter")
2752 },
2753 {
2754 "dn",
2755 net_ads_dn,
2756 NET_TRANSPORT_ADS,
2757 N_("Issue LDAP search by DN"),
2758 N_("net ads dn\n"
2759 " Issue LDAP search by DN")
2760 },
2761 {
2762 "sid",
2763 net_ads_sid,
2764 NET_TRANSPORT_ADS,
2765 N_("Issue LDAP search by SID"),
2766 N_("net ads sid\n"
2767 " Issue LDAP search by SID")
2768 },
2769 {
2770 "workgroup",
2771 net_ads_workgroup,
2772 NET_TRANSPORT_ADS,
2773 N_("Display workgroup name"),
2774 N_("net ads workgroup\n"
2775 " Display the workgroup name")
2776 },
2777 {
2778 "lookup",
2779 net_ads_lookup,
2780 NET_TRANSPORT_ADS,
2781 N_("Perfom CLDAP query on DC"),
2782 N_("net ads lookup\n"
2783 " Find the ADS DC using CLDAP lookups")
2784 },
2785 {
2786 "keytab",
2787 net_ads_keytab,
2788 NET_TRANSPORT_ADS,
2789 N_("Manage local keytab file"),
2790 N_("net ads keytab\n"
2791 " Manage local keytab file")
2792 },
2793 {
2794 "gpo",
2795 net_ads_gpo,
2796 NET_TRANSPORT_ADS,
2797 N_("Manage group policy objects"),
2798 N_("net ads gpo\n"
2799 " Manage group policy objects")
2800 },
2801 {
2802 "kerberos",
2803 net_ads_kerberos,
2804 NET_TRANSPORT_ADS,
2805 N_("Manage kerberos keytab"),
2806 N_("net ads kerberos\n"
2807 " Manage kerberos keytab")
2808 },
2809 {NULL, NULL, 0, NULL, NULL}
2810 };
2811
2812 return net_run_function(c, argc, argv, "net ads", func);
2813}
2814
2815#else
2816
2817static int net_ads_noads(void)
2818{
2819 d_fprintf(stderr, _("ADS support not compiled in\n"));
2820 return -1;
2821}
2822
2823int net_ads_keytab(struct net_context *c, int argc, const char **argv)
2824{
2825 return net_ads_noads();
2826}
2827
2828int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
2829{
2830 return net_ads_noads();
2831}
2832
2833int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2834{
2835 return net_ads_noads();
2836}
2837
2838int net_ads_join(struct net_context *c, int argc, const char **argv)
2839{
2840 return net_ads_noads();
2841}
2842
2843int net_ads_user(struct net_context *c, int argc, const char **argv)
2844{
2845 return net_ads_noads();
2846}
2847
2848int net_ads_group(struct net_context *c, int argc, const char **argv)
2849{
2850 return net_ads_noads();
2851}
2852
2853int net_ads_gpo(struct net_context *c, int argc, const char **argv)
2854{
2855 return net_ads_noads();
2856}
2857
2858/* this one shouldn't display a message */
2859int net_ads_check(struct net_context *c)
2860{
2861 return -1;
2862}
2863
2864int net_ads_check_our_domain(struct net_context *c)
2865{
2866 return -1;
2867}
2868
2869int net_ads(struct net_context *c, int argc, const char **argv)
2870{
2871 return net_ads_noads();
2872}
2873
2874#endif /* WITH_ADS */
Note: See TracBrowser for help on using the repository browser.