Janitorial duties to make autogen.sh portable.
[Samba/gebeck_regimport.git] / source3 / utils / net_ads.c
blobb4697d73dd7455b91b7dfc4d995388f14f2709ad
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)
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
24 #include "../utils/net.h"
26 #ifdef HAVE_ADS
28 int net_ads_usage(int argc, const char **argv)
30 d_printf(
31 "\nnet ads join <org_unit>"\
32 "\n\tjoins the local machine to a ADS realm\n"\
33 "\nnet ads leave"\
34 "\n\tremoves the local machine from a ADS realm\n"\
35 "\nnet ads testjoin"\
36 "\n\ttests that an exiting join is OK\n"\
37 "\nnet ads user"\
38 "\n\tlist, add, or delete users in the realm\n"\
39 "\nnet ads group"\
40 "\n\tlist, add, or delete groups in the realm\n"\
41 "\nnet ads info"\
42 "\n\tshows some info on the server\n"\
43 "\nnet ads status"\
44 "\n\tdump the machine account details to stdout\n"
45 "\nnet ads lookup"\
46 "\n\tperform a CLDAP search on the server\n"
47 "\nnet ads password <username@realm> -Uadmin_username@realm%%admin_pass"\
48 "\n\tchange a user's password using an admin account"\
49 "\n\t(note: use realm in UPPERCASE)\n"\
50 "\nnet ads chostpass"\
51 "\n\tchange the trust account password of this machine in the AD tree\n"\
52 "\nnet ads printer [info | publish | remove] <printername> <servername>"\
53 "\n\t lookup, add, or remove directory entry for a printer\n"\
54 "\nnet ads search"\
55 "\n\tperform a raw LDAP search and dump the results\n"
56 "\nnet ads dn"\
57 "\n\tperform a raw LDAP search and dump attributes of a particular DN\n"
59 return -1;
64 this implements the CLDAP based netlogon lookup requests
65 for finding the domain controller of a ADS domain
67 static int net_ads_lookup(int argc, const char **argv)
69 ADS_STRUCT *ads;
71 ads = ads_init(NULL, NULL, opt_host);
72 if (ads) {
73 ads->auth.flags |= ADS_AUTH_NO_BIND;
76 ads_connect(ads);
78 if (!ads || !ads->config.realm) {
79 d_printf("Didn't find the cldap server!\n");
80 return -1;
83 return ads_cldap_netlogon(ads);
88 static int net_ads_info(int argc, const char **argv)
90 ADS_STRUCT *ads;
92 ads = ads_init(NULL, NULL, opt_host);
94 if (ads) {
95 ads->auth.flags |= ADS_AUTH_NO_BIND;
98 ads_connect(ads);
100 if (!ads || !ads->config.realm) {
101 d_printf("Didn't find the ldap server!\n");
102 return -1;
105 d_printf("LDAP server: %s\n", inet_ntoa(ads->ldap_ip));
106 d_printf("LDAP server name: %s\n", ads->config.ldap_server_name);
107 d_printf("Realm: %s\n", ads->config.realm);
108 d_printf("Bind Path: %s\n", ads->config.bind_path);
109 d_printf("LDAP port: %d\n", ads->ldap_port);
110 d_printf("Server time: %s\n", http_timestring(ads->config.current_time));
112 return 0;
115 static void use_in_memory_ccache(void) {
116 /* Use in-memory credentials cache so we do not interfere with
117 * existing credentials */
118 setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
121 static ADS_STRUCT *ads_startup(void)
123 ADS_STRUCT *ads;
124 ADS_STATUS status;
125 BOOL need_password = False;
126 BOOL second_time = False;
128 ads = ads_init(NULL, NULL, opt_host);
130 if (!opt_user_name) {
131 opt_user_name = "administrator";
134 if (opt_user_specified) {
135 need_password = True;
138 retry:
139 if (!opt_password && need_password) {
140 char *prompt;
141 asprintf(&prompt,"%s password: ", opt_user_name);
142 opt_password = getpass(prompt);
143 free(prompt);
146 if (opt_password) {
147 use_in_memory_ccache();
148 ads->auth.password = strdup(opt_password);
151 ads->auth.user_name = strdup(opt_user_name);
153 status = ads_connect(ads);
154 if (!ADS_ERR_OK(status)) {
155 if (!need_password && !second_time) {
156 need_password = True;
157 second_time = True;
158 goto retry;
159 } else {
160 DEBUG(1,("ads_connect: %s\n", ads_errstr(status)));
161 return NULL;
164 return ads;
169 Check to see if connection can be made via ads.
170 ads_startup() stores the password in opt_password if it needs to so
171 that rpc or rap can use it without re-prompting.
173 int net_ads_check(void)
175 ADS_STRUCT *ads;
177 ads = ads_startup();
178 if (!ads)
179 return -1;
180 ads_destroy(&ads);
181 return 0;
185 determine the netbios workgroup name for a domain
187 static int net_ads_workgroup(int argc, const char **argv)
189 ADS_STRUCT *ads;
190 TALLOC_CTX *ctx;
191 char *workgroup;
193 if (!(ads = ads_startup())) return -1;
195 if (!(ctx = talloc_init("net_ads_workgroup"))) {
196 return -1;
199 if (!ADS_ERR_OK(ads_workgroup_name(ads, ctx, &workgroup))) {
200 d_printf("Failed to find workgroup for realm '%s'\n",
201 ads->config.realm);
202 talloc_destroy(ctx);
203 return -1;
206 d_printf("Workgroup: %s\n", workgroup);
208 talloc_destroy(ctx);
210 return 0;
215 static BOOL usergrp_display(char *field, void **values, void *data_area)
217 char **disp_fields = (char **) data_area;
219 if (!field) { /* must be end of record */
220 if (!strchr_m(disp_fields[0], '$')) {
221 if (disp_fields[1])
222 d_printf("%-21.21s %-50.50s\n",
223 disp_fields[0], disp_fields[1]);
224 else
225 d_printf("%s\n", disp_fields[0]);
227 SAFE_FREE(disp_fields[0]);
228 SAFE_FREE(disp_fields[1]);
229 return True;
231 if (!values) /* must be new field, indicate string field */
232 return True;
233 if (StrCaseCmp(field, "sAMAccountName") == 0) {
234 disp_fields[0] = strdup((char *) values[0]);
236 if (StrCaseCmp(field, "description") == 0)
237 disp_fields[1] = strdup((char *) values[0]);
238 return True;
241 static int net_ads_user_usage(int argc, const char **argv)
243 return net_help_user(argc, argv);
246 static int ads_user_add(int argc, const char **argv)
248 ADS_STRUCT *ads;
249 ADS_STATUS status;
250 char *upn, *userdn;
251 void *res=NULL;
252 int rc = -1;
254 if (argc < 1) return net_ads_user_usage(argc, argv);
256 if (!(ads = ads_startup())) return -1;
258 status = ads_find_user_acct(ads, &res, argv[0]);
260 if (!ADS_ERR_OK(status)) {
261 d_printf("ads_user_add: %s\n", ads_errstr(status));
262 goto done;
265 if (ads_count_replies(ads, res)) {
266 d_printf("ads_user_add: User %s already exists\n", argv[0]);
267 goto done;
270 status = ads_add_user_acct(ads, argv[0], opt_container, opt_comment);
272 if (!ADS_ERR_OK(status)) {
273 d_printf("Could not add user %s: %s\n", argv[0],
274 ads_errstr(status));
275 goto done;
278 /* if no password is to be set, we're done */
279 if (argc == 1) {
280 d_printf("User %s added\n", argv[0]);
281 rc = 0;
282 goto done;
285 /* try setting the password */
286 asprintf(&upn, "%s@%s", argv[0], ads->config.realm);
287 status = krb5_set_password(ads->auth.kdc_server, upn, argv[1], ads->auth.time_offset);
288 safe_free(upn);
289 if (ADS_ERR_OK(status)) {
290 d_printf("User %s added\n", argv[0]);
291 rc = 0;
292 goto done;
295 /* password didn't set, delete account */
296 d_printf("Could not add user %s. Error setting password %s\n",
297 argv[0], ads_errstr(status));
298 ads_msgfree(ads, res);
299 status=ads_find_user_acct(ads, &res, argv[0]);
300 if (ADS_ERR_OK(status)) {
301 userdn = ads_get_dn(ads, res);
302 ads_del_dn(ads, userdn);
303 ads_memfree(ads, userdn);
306 done:
307 if (res)
308 ads_msgfree(ads, res);
309 ads_destroy(&ads);
310 return rc;
313 static int ads_user_info(int argc, const char **argv)
315 ADS_STRUCT *ads;
316 ADS_STATUS rc;
317 void *res;
318 const char *attrs[] = {"memberOf", NULL};
319 char *searchstring=NULL;
320 char **grouplist;
321 char *escaped_user = escape_ldap_string_alloc(argv[0]);
323 if (argc < 1) return net_ads_user_usage(argc, argv);
325 if (!(ads = ads_startup())) return -1;
327 if (!escaped_user) {
328 d_printf("ads_user_info: failed to escape user %s\n", argv[0]);
329 return -1;
332 asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user);
333 rc = ads_search(ads, &res, searchstring, attrs);
334 safe_free(searchstring);
336 if (!ADS_ERR_OK(rc)) {
337 d_printf("ads_search: %s\n", ads_errstr(rc));
338 return -1;
341 grouplist = ldap_get_values(ads->ld, res, "memberOf");
343 if (grouplist) {
344 int i;
345 char **groupname;
346 for (i=0;grouplist[i];i++) {
347 groupname = ldap_explode_dn(grouplist[i], 1);
348 d_printf("%s\n", groupname[0]);
349 ldap_value_free(groupname);
351 ldap_value_free(grouplist);
354 ads_msgfree(ads, res);
356 ads_destroy(&ads);
357 return 0;
360 static int ads_user_delete(int argc, const char **argv)
362 ADS_STRUCT *ads;
363 ADS_STATUS rc;
364 void *res;
365 char *userdn;
367 if (argc < 1) return net_ads_user_usage(argc, argv);
369 if (!(ads = ads_startup())) return -1;
371 rc = ads_find_user_acct(ads, &res, argv[0]);
372 if (!ADS_ERR_OK(rc)) {
373 DEBUG(0, ("User %s does not exist\n", argv[0]));
374 return -1;
376 userdn = ads_get_dn(ads, res);
377 ads_msgfree(ads, res);
378 rc = ads_del_dn(ads, userdn);
379 ads_memfree(ads, userdn);
380 if (!ADS_ERR_OK(rc)) {
381 d_printf("User %s deleted\n", argv[0]);
382 return 0;
384 d_printf("Error deleting user %s: %s\n", argv[0],
385 ads_errstr(rc));
386 return -1;
389 int net_ads_user(int argc, const char **argv)
391 struct functable func[] = {
392 {"ADD", ads_user_add},
393 {"INFO", ads_user_info},
394 {"DELETE", ads_user_delete},
395 {NULL, NULL}
397 ADS_STRUCT *ads;
398 ADS_STATUS rc;
399 const char *shortattrs[] = {"sAMAccountName", NULL};
400 const char *longattrs[] = {"sAMAccountName", "description", NULL};
401 char *disp_fields[2] = {NULL, NULL};
403 if (argc == 0) {
404 if (!(ads = ads_startup())) return -1;
406 if (opt_long_list_entries)
407 d_printf("\nUser name Comment"\
408 "\n-----------------------------\n");
410 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
411 LDAP_SCOPE_SUBTREE,
412 "(objectclass=user)",
413 opt_long_list_entries ? longattrs :
414 shortattrs, usergrp_display,
415 disp_fields);
416 ads_destroy(&ads);
417 return 0;
420 return net_run_function(argc, argv, func, net_ads_user_usage);
423 static int net_ads_group_usage(int argc, const char **argv)
425 return net_help_group(argc, argv);
428 static int ads_group_add(int argc, const char **argv)
430 ADS_STRUCT *ads;
431 ADS_STATUS status;
432 void *res=NULL;
433 int rc = -1;
435 if (argc < 1) return net_ads_group_usage(argc, argv);
437 if (!(ads = ads_startup())) return -1;
439 status = ads_find_user_acct(ads, &res, argv[0]);
441 if (!ADS_ERR_OK(status)) {
442 d_printf("ads_group_add: %s\n", ads_errstr(status));
443 goto done;
446 if (ads_count_replies(ads, res)) {
447 d_printf("ads_group_add: Group %s already exists\n", argv[0]);
448 ads_msgfree(ads, res);
449 goto done;
452 status = ads_add_group_acct(ads, argv[0], opt_container, opt_comment);
454 if (ADS_ERR_OK(status)) {
455 d_printf("Group %s added\n", argv[0]);
456 rc = 0;
457 } else {
458 d_printf("Could not add group %s: %s\n", argv[0],
459 ads_errstr(status));
462 done:
463 if (res)
464 ads_msgfree(ads, res);
465 ads_destroy(&ads);
466 return rc;
469 static int ads_group_delete(int argc, const char **argv)
471 ADS_STRUCT *ads;
472 ADS_STATUS rc;
473 void *res;
474 char *groupdn;
476 if (argc < 1) return net_ads_group_usage(argc, argv);
478 if (!(ads = ads_startup())) return -1;
480 rc = ads_find_user_acct(ads, &res, argv[0]);
481 if (!ADS_ERR_OK(rc)) {
482 DEBUG(0, ("Group %s does not exist\n", argv[0]));
483 return -1;
485 groupdn = ads_get_dn(ads, res);
486 ads_msgfree(ads, res);
487 rc = ads_del_dn(ads, groupdn);
488 ads_memfree(ads, groupdn);
489 if (!ADS_ERR_OK(rc)) {
490 d_printf("Group %s deleted\n", argv[0]);
491 return 0;
493 d_printf("Error deleting group %s: %s\n", argv[0],
494 ads_errstr(rc));
495 return -1;
498 int net_ads_group(int argc, const char **argv)
500 struct functable func[] = {
501 {"ADD", ads_group_add},
502 {"DELETE", ads_group_delete},
503 {NULL, NULL}
505 ADS_STRUCT *ads;
506 ADS_STATUS rc;
507 const char *shortattrs[] = {"sAMAccountName", NULL};
508 const char *longattrs[] = {"sAMAccountName", "description", NULL};
509 char *disp_fields[2] = {NULL, NULL};
511 if (argc == 0) {
512 if (!(ads = ads_startup())) return -1;
514 if (opt_long_list_entries)
515 d_printf("\nGroup name Comment"\
516 "\n-----------------------------\n");
517 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
518 LDAP_SCOPE_SUBTREE,
519 "(objectclass=group)",
520 opt_long_list_entries ? longattrs :
521 shortattrs, usergrp_display,
522 disp_fields);
524 ads_destroy(&ads);
525 return 0;
527 return net_run_function(argc, argv, func, net_ads_group_usage);
530 static int net_ads_status(int argc, const char **argv)
532 ADS_STRUCT *ads;
533 ADS_STATUS rc;
534 void *res;
536 if (!(ads = ads_startup())) return -1;
538 rc = ads_find_machine_acct(ads, &res, global_myname());
539 if (!ADS_ERR_OK(rc)) {
540 d_printf("ads_find_machine_acct: %s\n", ads_errstr(rc));
541 return -1;
544 if (ads_count_replies(ads, res) == 0) {
545 d_printf("No machine account for '%s' found\n", global_myname());
546 return -1;
549 ads_dump(ads, res);
551 return 0;
554 static int net_ads_leave(int argc, const char **argv)
556 ADS_STRUCT *ads = NULL;
557 ADS_STATUS rc;
559 if (!secrets_init()) {
560 DEBUG(1,("Failed to initialise secrets database\n"));
561 return -1;
564 if (!opt_password) {
565 char *user_name;
566 asprintf(&user_name, "%s$", global_myname());
567 opt_password = secrets_fetch_machine_password();
568 opt_user_name = user_name;
571 if (!(ads = ads_startup())) {
572 return -1;
575 rc = ads_leave_realm(ads, global_myname());
576 if (!ADS_ERR_OK(rc)) {
577 d_printf("Failed to delete host '%s' from the '%s' realm.\n",
578 global_myname(), ads->config.realm);
579 return -1;
582 d_printf("Removed '%s' from realm '%s'\n", global_myname(), ads->config.realm);
584 return 0;
587 static int net_ads_join_ok(void)
589 char *user_name;
590 ADS_STRUCT *ads = NULL;
592 if (!secrets_init()) {
593 DEBUG(1,("Failed to initialise secrets database\n"));
594 return -1;
597 asprintf(&user_name, "%s$", global_myname());
598 opt_user_name = user_name;
599 opt_password = secrets_fetch_machine_password();
601 if (!(ads = ads_startup())) {
602 return -1;
605 ads_destroy(&ads);
606 return 0;
610 check that an existing join is OK
612 int net_ads_testjoin(int argc, const char **argv)
614 use_in_memory_ccache();
616 /* Display success or failure */
617 if (net_ads_join_ok() != 0) {
618 fprintf(stderr,"Join to domain is not valid\n");
619 return -1;
622 printf("Join is OK\n");
623 return 0;
627 join a domain using ADS
629 int net_ads_join(int argc, const char **argv)
631 ADS_STRUCT *ads;
632 ADS_STATUS rc;
633 char *password;
634 char *tmp_password;
635 const char *org_unit = "Computers";
636 char *dn;
637 void *res;
638 DOM_SID dom_sid;
639 char *ou_str;
641 if (argc > 0) org_unit = argv[0];
643 if (!secrets_init()) {
644 DEBUG(1,("Failed to initialise secrets database\n"));
645 return -1;
648 tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
649 password = strdup(tmp_password);
651 if (!(ads = ads_startup())) return -1;
653 ou_str = ads_ou_string(org_unit);
654 asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path);
655 free(ou_str);
657 rc = ads_search_dn(ads, &res, dn, NULL);
658 ads_msgfree(ads, res);
660 if (rc.error_type == ADS_ERROR_LDAP && rc.err.rc == LDAP_NO_SUCH_OBJECT) {
661 d_printf("ads_join_realm: organizational unit %s does not exist (dn:%s)\n",
662 org_unit, dn);
663 return -1;
665 free(dn);
667 if (!ADS_ERR_OK(rc)) {
668 d_printf("ads_join_realm: %s\n", ads_errstr(rc));
669 return -1;
672 rc = ads_join_realm(ads, global_myname(), org_unit);
673 if (!ADS_ERR_OK(rc)) {
674 d_printf("ads_join_realm: %s\n", ads_errstr(rc));
675 return -1;
678 rc = ads_domain_sid(ads, &dom_sid);
679 if (!ADS_ERR_OK(rc)) {
680 d_printf("ads_domain_sid: %s\n", ads_errstr(rc));
681 return -1;
684 rc = ads_set_machine_password(ads, global_myname(), password);
685 if (!ADS_ERR_OK(rc)) {
686 d_printf("ads_set_machine_password: %s\n", ads_errstr(rc));
687 return -1;
690 if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) {
691 DEBUG(1,("Failed to save domain sid\n"));
692 return -1;
695 if (!secrets_store_machine_password(password)) {
696 DEBUG(1,("Failed to save machine password\n"));
697 return -1;
700 d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm);
702 free(password);
704 return 0;
707 int net_ads_printer_usage(int argc, const char **argv)
709 d_printf(
710 "\nnet ads printer info <printer> <server>"
711 "\n\tlookup info in directory for printer on server"
712 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
713 "\nnet ads printer publish <printername>"
714 "\n\tpublish printer in directory"
715 "\n\t(note: printer name is required)\n"
716 "\nnet ads printer remove <printername>"
717 "\n\tremove printer from directory"
718 "\n\t(note: printer name is required)\n");
719 return -1;
722 static int net_ads_printer_info(int argc, const char **argv)
724 ADS_STRUCT *ads;
725 ADS_STATUS rc;
726 const char *servername, *printername;
727 void *res = NULL;
729 if (!(ads = ads_startup())) return -1;
731 if (argc > 0)
732 printername = argv[0];
733 else
734 printername = "*";
736 if (argc > 1)
737 servername = argv[1];
738 else
739 servername = global_myname();
741 rc = ads_find_printer_on_server(ads, &res, printername, servername);
743 if (!ADS_ERR_OK(rc)) {
744 d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc));
745 ads_msgfree(ads, res);
746 return -1;
749 if (ads_count_replies(ads, res) == 0) {
750 d_printf("Printer '%s' not found\n", printername);
751 ads_msgfree(ads, res);
752 return -1;
755 ads_dump(ads, res);
756 ads_msgfree(ads, res);
758 return 0;
761 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
763 return;
766 static int net_ads_printer_publish(int argc, const char **argv)
768 ADS_STRUCT *ads;
769 ADS_STATUS rc;
770 const char *servername;
771 struct cli_state *cli;
772 struct in_addr server_ip;
773 NTSTATUS nt_status;
774 TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
775 ADS_MODLIST mods = ads_init_mods(mem_ctx);
776 char *prt_dn, *srv_dn, **srv_cn;
777 void *res = NULL;
779 if (!(ads = ads_startup())) return -1;
781 if (argc < 1)
782 return net_ads_printer_usage(argc, argv);
784 if (argc == 2)
785 servername = argv[1];
786 else
787 servername = global_myname();
789 ads_find_machine_acct(ads, &res, servername);
790 srv_dn = ldap_get_dn(ads->ld, res);
791 srv_cn = ldap_explode_dn(srv_dn, 1);
792 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], argv[0], srv_dn);
794 resolve_name(servername, &server_ip, 0x20);
796 nt_status = cli_full_connection(&cli, global_myname(), servername,
797 &server_ip, 0,
798 "IPC$", "IPC",
799 opt_user_name, opt_workgroup,
800 opt_password ? opt_password : "",
801 CLI_FULL_CONNECTION_USE_KERBEROS,
802 NULL);
804 cli_nt_session_open(cli, PI_SPOOLSS);
805 get_remote_printer_publishing_data(cli, mem_ctx, &mods, argv[0]);
807 rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
808 if (!ADS_ERR_OK(rc)) {
809 d_printf("ads_publish_printer: %s\n", ads_errstr(rc));
810 return -1;
813 d_printf("published printer\n");
815 return 0;
818 static int net_ads_printer_remove(int argc, const char **argv)
820 ADS_STRUCT *ads;
821 ADS_STATUS rc;
822 const char *servername;
823 char *prt_dn;
824 void *res = NULL;
826 if (!(ads = ads_startup())) return -1;
828 if (argc < 1)
829 return net_ads_printer_usage(argc, argv);
831 if (argc > 1)
832 servername = argv[1];
833 else
834 servername = global_myname();
836 rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
838 if (!ADS_ERR_OK(rc)) {
839 d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc));
840 ads_msgfree(ads, res);
841 return -1;
844 if (ads_count_replies(ads, res) == 0) {
845 d_printf("Printer '%s' not found\n", argv[1]);
846 ads_msgfree(ads, res);
847 return -1;
850 prt_dn = ads_get_dn(ads, res);
851 ads_msgfree(ads, res);
852 rc = ads_del_dn(ads, prt_dn);
853 ads_memfree(ads, prt_dn);
855 if (!ADS_ERR_OK(rc)) {
856 d_printf("ads_del_dn: %s\n", ads_errstr(rc));
857 return -1;
860 return 0;
863 static int net_ads_printer(int argc, const char **argv)
865 struct functable func[] = {
866 {"INFO", net_ads_printer_info},
867 {"PUBLISH", net_ads_printer_publish},
868 {"REMOVE", net_ads_printer_remove},
869 {NULL, NULL}
872 return net_run_function(argc, argv, func, net_ads_printer_usage);
876 static int net_ads_password(int argc, const char **argv)
878 ADS_STRUCT *ads;
879 const char *auth_principal = opt_user_name;
880 const char *auth_password = opt_password;
881 char *realm = NULL;
882 char *new_password = NULL;
883 char *c;
884 char *prompt;
885 ADS_STATUS ret;
888 if ((argc != 1) || (opt_user_name == NULL) ||
889 (opt_password == NULL) || (strchr(opt_user_name, '@') == NULL) ||
890 (strchr(argv[0], '@') == NULL)) {
891 return net_ads_usage(argc, argv);
894 use_in_memory_ccache();
895 c = strchr(auth_principal, '@');
896 realm = ++c;
898 /* use the realm so we can eventually change passwords for users
899 in realms other than default */
900 if (!(ads = ads_init(realm, NULL, NULL))) return -1;
902 /* we don't actually need a full connect, but it's the easy way to
903 fill in the KDC's addresss */
904 ads_connect(ads);
906 if (!ads || !ads->config.realm) {
907 d_printf("Didn't find the kerberos server!\n");
908 return -1;
911 asprintf(&prompt, "Enter new password for %s:", argv[0]);
913 new_password = getpass(prompt);
915 ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
916 auth_password, argv[0], new_password, ads->auth.time_offset);
917 if (!ADS_ERR_OK(ret)) {
918 d_printf("Password change failed :-( ...\n");
919 ads_destroy(&ads);
920 free(prompt);
921 return -1;
924 d_printf("Password change for %s completed.\n", argv[0]);
925 ads_destroy(&ads);
926 free(prompt);
928 return 0;
932 static int net_ads_change_localhost_pass(int argc, const char **argv)
934 ADS_STRUCT *ads;
935 char *host_principal;
936 char *hostname;
937 ADS_STATUS ret;
938 char *user_name;
940 if (!secrets_init()) {
941 DEBUG(1,("Failed to initialise secrets database\n"));
942 return -1;
945 asprintf(&user_name, "%s$", global_myname());
946 opt_user_name = user_name;
948 opt_password = secrets_fetch_machine_password();
950 use_in_memory_ccache();
952 if (!(ads = ads_startup())) {
953 return -1;
956 hostname = strdup(global_myname());
957 strlower(hostname);
958 asprintf(&host_principal, "%s@%s", hostname, ads->config.realm);
959 SAFE_FREE(hostname);
960 d_printf("Changing password for principal: HOST/%s\n", host_principal);
962 ret = ads_change_trust_account_password(ads, host_principal);
964 if (!ADS_ERR_OK(ret)) {
965 d_printf("Password change failed :-( ...\n");
966 ads_destroy(&ads);
967 SAFE_FREE(host_principal);
968 return -1;
971 d_printf("Password change for principal HOST/%s succeeded.\n", host_principal);
972 ads_destroy(&ads);
973 SAFE_FREE(host_principal);
975 return 0;
979 help for net ads search
981 static int net_ads_search_usage(int argc, const char **argv)
983 d_printf(
984 "\nnet ads search <expression> <attributes...>\n"\
985 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
986 "The expression is a standard LDAP search expression, and the\n"\
987 "attributes are a list of LDAP fields to show in the results\n\n"\
988 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
990 net_common_flags_usage(argc, argv);
991 return -1;
996 general ADS search function. Useful in diagnosing problems in ADS
998 static int net_ads_search(int argc, const char **argv)
1000 ADS_STRUCT *ads;
1001 ADS_STATUS rc;
1002 const char *exp;
1003 const char **attrs;
1004 void *res = NULL;
1006 if (argc < 1) {
1007 return net_ads_search_usage(argc, argv);
1010 if (!(ads = ads_startup())) {
1011 return -1;
1014 exp = argv[0];
1015 attrs = (argv + 1);
1017 rc = ads_do_search_all(ads, ads->config.bind_path,
1018 LDAP_SCOPE_SUBTREE,
1019 exp, attrs, &res);
1020 if (!ADS_ERR_OK(rc)) {
1021 d_printf("search failed: %s\n", ads_errstr(rc));
1022 return -1;
1025 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
1027 /* dump the results */
1028 ads_dump(ads, res);
1030 ads_msgfree(ads, res);
1031 ads_destroy(&ads);
1033 return 0;
1038 help for net ads search
1040 static int net_ads_dn_usage(int argc, const char **argv)
1042 d_printf(
1043 "\nnet ads dn <dn> <attributes...>\n"\
1044 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
1045 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"\
1046 "to show in the results\n\n"\
1047 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
1049 net_common_flags_usage(argc, argv);
1050 return -1;
1055 general ADS search function. Useful in diagnosing problems in ADS
1057 static int net_ads_dn(int argc, const char **argv)
1059 ADS_STRUCT *ads;
1060 ADS_STATUS rc;
1061 const char *dn;
1062 const char **attrs;
1063 void *res = NULL;
1065 if (argc < 1) {
1066 return net_ads_dn_usage(argc, argv);
1069 if (!(ads = ads_startup())) {
1070 return -1;
1073 dn = argv[0];
1074 attrs = (argv + 1);
1076 rc = ads_do_search_all(ads, dn,
1077 LDAP_SCOPE_BASE,
1078 "(objectclass=*)", attrs, &res);
1079 if (!ADS_ERR_OK(rc)) {
1080 d_printf("search failed: %s\n", ads_errstr(rc));
1081 return -1;
1084 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
1086 /* dump the results */
1087 ads_dump(ads, res);
1089 ads_msgfree(ads, res);
1090 ads_destroy(&ads);
1092 return 0;
1096 int net_ads_help(int argc, const char **argv)
1098 struct functable func[] = {
1099 {"USER", net_ads_user_usage},
1100 {"GROUP", net_ads_group_usage},
1101 {"PRINTER", net_ads_printer_usage},
1102 {"SEARCH", net_ads_search_usage},
1103 #if 0
1104 {"INFO", net_ads_info},
1105 {"JOIN", net_ads_join},
1106 {"LEAVE", net_ads_leave},
1107 {"STATUS", net_ads_status},
1108 {"PASSWORD", net_ads_password},
1109 {"CHOSTPASS", net_ads_change_localhost_pass},
1110 #endif
1111 {NULL, NULL}
1114 return net_run_function(argc, argv, func, net_ads_usage);
1117 int net_ads(int argc, const char **argv)
1119 struct functable func[] = {
1120 {"INFO", net_ads_info},
1121 {"JOIN", net_ads_join},
1122 {"TESTJOIN", net_ads_testjoin},
1123 {"LEAVE", net_ads_leave},
1124 {"STATUS", net_ads_status},
1125 {"USER", net_ads_user},
1126 {"GROUP", net_ads_group},
1127 {"PASSWORD", net_ads_password},
1128 {"CHOSTPASS", net_ads_change_localhost_pass},
1129 {"PRINTER", net_ads_printer},
1130 {"SEARCH", net_ads_search},
1131 {"DN", net_ads_dn},
1132 {"WORKGROUP", net_ads_workgroup},
1133 {"LOOKUP", net_ads_lookup},
1134 {"HELP", net_ads_help},
1135 {NULL, NULL}
1138 return net_run_function(argc, argv, func, net_ads_usage);
1141 #else
1143 static int net_ads_noads(void)
1145 d_printf("ADS support not compiled in\n");
1146 return -1;
1149 int net_ads_usage(int argc, const char **argv)
1151 return net_ads_noads();
1154 int net_ads_help(int argc, const char **argv)
1156 return net_ads_noads();
1159 int net_ads_join(int argc, const char **argv)
1161 return net_ads_noads();
1164 int net_ads_user(int argc, const char **argv)
1166 return net_ads_noads();
1169 int net_ads_group(int argc, const char **argv)
1171 return net_ads_noads();
1174 /* this one shouldn't display a message */
1175 int net_ads_check(void)
1177 return -1;
1180 int net_ads(int argc, const char **argv)
1182 return net_ads_usage(argc, argv);
1185 #endif