Fairly large change to printing code.
[Samba.git] / source / utils / net_ads.c
blobad405fe68c32fb46063fcabe0ca7c51db498a399
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 password <username@realm> -Uadmin_username@realm%%admin_pass"\
46 "\n\tchange a user's password using an admin account"\
47 "\n\t(note: use realm in UPPERCASE)\n"\
48 "\nnet ads chostpass"\
49 "\n\tchange the trust account password of this machine in the AD tree\n"\
50 "\nnet ads printer [info | publish | remove] <printername> <servername>"\
51 "\n\t lookup, add, or remove directory entry for a printer\n"\
52 "\nnet ads search"\
53 "\n\tperform a raw LDAP search and dump the results\n"
55 return -1;
59 static int net_ads_info(int argc, const char **argv)
61 ADS_STRUCT *ads;
63 ads = ads_init(NULL, NULL, opt_host);
65 if (ads) {
66 ads->auth.no_bind = 1;
69 ads_connect(ads);
71 if (!ads || !ads->config.realm) {
72 d_printf("Didn't find the ldap server!\n");
73 return -1;
76 d_printf("LDAP server: %s\n", inet_ntoa(ads->ldap_ip));
77 d_printf("LDAP server name: %s\n", ads->config.ldap_server_name);
78 d_printf("Realm: %s\n", ads->config.realm);
79 d_printf("Bind Path: %s\n", ads->config.bind_path);
80 d_printf("LDAP port: %d\n", ads->ldap_port);
82 return 0;
86 static ADS_STRUCT *ads_startup(void)
88 ADS_STRUCT *ads;
89 ADS_STATUS status;
90 BOOL need_password = False;
91 BOOL second_time = False;
93 ads = ads_init(NULL, NULL, opt_host);
95 if (!opt_user_name) {
96 opt_user_name = "administrator";
99 if (opt_user_specified)
100 need_password = True;
102 retry:
103 if (!opt_password && need_password) {
104 char *prompt;
105 asprintf(&prompt,"%s password: ", opt_user_name);
106 opt_password = getpass(prompt);
107 free(prompt);
110 if (opt_password)
111 ads->auth.password = strdup(opt_password);
113 ads->auth.user_name = strdup(opt_user_name);
115 status = ads_connect(ads);
116 if (!ADS_ERR_OK(status)) {
117 if (!need_password && !second_time) {
118 need_password = True;
119 second_time = True;
120 goto retry;
121 } else {
122 DEBUG(1,("ads_connect: %s\n", ads_errstr(status)));
123 return NULL;
126 return ads;
131 Check to see if connection can be made via ads.
132 ads_startup() stores the password in opt_password if it needs to so
133 that rpc or rap can use it without re-prompting.
135 int net_ads_check(void)
137 ADS_STRUCT *ads;
139 ads = ads_startup();
140 if (!ads)
141 return -1;
142 ads_destroy(&ads);
143 return 0;
147 determine the netbios workgroup name for a domain
149 static int net_ads_workgroup(int argc, const char **argv)
151 ADS_STRUCT *ads;
152 TALLOC_CTX *ctx;
153 char *workgroup;
155 if (!(ads = ads_startup())) return -1;
157 if (!(ctx = talloc_init_named("net_ads_workgroup"))) {
158 return -1;
161 if (!ADS_ERR_OK(ads_workgroup_name(ads, ctx, &workgroup))) {
162 d_printf("Failed to find workgroup for realm '%s'\n",
163 ads->config.realm);
164 talloc_destroy(ctx);
165 return -1;
168 d_printf("Workgroup: %s\n", workgroup);
170 talloc_destroy(ctx);
172 return 0;
177 static void usergrp_display(char *field, void **values, void *data_area)
179 char **disp_fields = (char **) data_area;
181 if (!field) { /* must be end of record */
182 if (!strchr_m(disp_fields[0], '$')) {
183 if (disp_fields[1])
184 d_printf("%-21.21s %-50.50s\n",
185 disp_fields[0], disp_fields[1]);
186 else
187 d_printf("%s\n", disp_fields[0]);
189 SAFE_FREE(disp_fields[0]);
190 SAFE_FREE(disp_fields[1]);
191 return;
193 if (!values) /* must be new field, indicate string field */
194 return;
195 if (StrCaseCmp(field, "sAMAccountName") == 0) {
196 disp_fields[0] = strdup((char *) values[0]);
198 if (StrCaseCmp(field, "description") == 0)
199 disp_fields[1] = strdup((char *) values[0]);
202 static int net_ads_user_usage(int argc, const char **argv)
204 return net_help_user(argc, argv);
207 static int ads_user_add(int argc, const char **argv)
209 ADS_STRUCT *ads;
210 ADS_STATUS status;
211 char *upn, *userdn;
212 void *res=NULL;
213 int rc = -1;
215 if (argc < 1) return net_ads_user_usage(argc, argv);
217 if (!(ads = ads_startup())) return -1;
219 status = ads_find_user_acct(ads, &res, argv[0]);
221 if (!ADS_ERR_OK(status)) {
222 d_printf("ads_user_add: %s\n", ads_errstr(status));
223 goto done;
226 if (ads_count_replies(ads, res)) {
227 d_printf("ads_user_add: User %s already exists\n", argv[0]);
228 goto done;
231 status = ads_add_user_acct(ads, argv[0], opt_comment);
233 if (!ADS_ERR_OK(status)) {
234 d_printf("Could not add user %s: %s\n", argv[0],
235 ads_errstr(status));
236 goto done;
239 /* if no password is to be set, we're done */
240 if (argc == 1) {
241 d_printf("User %s added\n", argv[0]);
242 rc = 0;
243 goto done;
246 /* try setting the password */
247 asprintf(&upn, "%s@%s", argv[0], ads->config.realm);
248 status = krb5_set_password(ads->auth.kdc_server, upn, argv[1]);
249 safe_free(upn);
250 if (ADS_ERR_OK(status)) {
251 d_printf("User %s added\n", argv[0]);
252 rc = 0;
253 goto done;
256 /* password didn't set, delete account */
257 d_printf("Could not add user %s. Error setting password %s\n",
258 argv[0], ads_errstr(status));
259 ads_msgfree(ads, res);
260 status=ads_find_user_acct(ads, &res, argv[0]);
261 if (ADS_ERR_OK(status)) {
262 userdn = ads_get_dn(ads, res);
263 ads_del_dn(ads, userdn);
264 ads_memfree(ads, userdn);
267 done:
268 if (res)
269 ads_msgfree(ads, res);
270 ads_destroy(&ads);
271 return rc;
274 static int ads_user_info(int argc, const char **argv)
276 ADS_STRUCT *ads;
277 ADS_STATUS rc;
278 void *res;
279 const char *attrs[] = {"memberOf", NULL};
280 char *searchstring=NULL;
281 char **grouplist;
283 if (argc < 1) return net_ads_user_usage(argc, argv);
285 if (!(ads = ads_startup())) return -1;
287 asprintf(&searchstring, "(sAMAccountName=%s)", argv[0]);
288 rc = ads_search(ads, &res, searchstring, attrs);
289 safe_free(searchstring);
291 if (!ADS_ERR_OK(rc)) {
292 d_printf("ads_search: %s\n", ads_errstr(rc));
293 return -1;
296 grouplist = ldap_get_values(ads->ld, res, "memberOf");
298 if (grouplist) {
299 int i;
300 char **groupname;
301 for (i=0;grouplist[i];i++) {
302 groupname = ldap_explode_dn(grouplist[i], 1);
303 d_printf("%s\n", groupname[0]);
304 ldap_value_free(groupname);
306 ldap_value_free(grouplist);
309 ads_msgfree(ads, res);
311 ads_destroy(&ads);
312 return 0;
315 static int ads_user_delete(int argc, const char **argv)
317 ADS_STRUCT *ads;
318 ADS_STATUS rc;
319 void *res;
320 char *userdn;
322 if (argc < 1) return net_ads_user_usage(argc, argv);
324 if (!(ads = ads_startup())) return -1;
326 rc = ads_find_user_acct(ads, &res, argv[0]);
327 if (!ADS_ERR_OK(rc)) {
328 DEBUG(0, ("User %s does not exist\n", argv[0]));
329 return -1;
331 userdn = ads_get_dn(ads, res);
332 ads_msgfree(ads, res);
333 rc = ads_del_dn(ads, userdn);
334 ads_memfree(ads, userdn);
335 if (!ADS_ERR_OK(rc)) {
336 d_printf("User %s deleted\n", argv[0]);
337 return 0;
339 d_printf("Error deleting user %s: %s\n", argv[0],
340 ads_errstr(rc));
341 return -1;
344 int net_ads_user(int argc, const char **argv)
346 struct functable func[] = {
347 {"ADD", ads_user_add},
348 {"INFO", ads_user_info},
349 {"DELETE", ads_user_delete},
350 {NULL, NULL}
352 ADS_STRUCT *ads;
353 ADS_STATUS rc;
354 const char *shortattrs[] = {"sAMAccountName", NULL};
355 const char *longattrs[] = {"sAMAccountName", "description", NULL};
356 char *disp_fields[2] = {NULL, NULL};
358 if (argc == 0) {
359 if (!(ads = ads_startup())) return -1;
361 if (opt_long_list_entries)
362 d_printf("\nUser name Comment"\
363 "\n-----------------------------\n");
365 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
366 LDAP_SCOPE_SUBTREE,
367 "(objectclass=user)",
368 opt_long_list_entries ? longattrs :
369 shortattrs, usergrp_display,
370 disp_fields);
371 ads_destroy(&ads);
372 return 0;
375 return net_run_function(argc, argv, func, net_ads_user_usage);
378 static int net_ads_group_usage(int argc, const char **argv)
380 return net_help_group(argc, argv);
383 static int ads_group_add(int argc, const char **argv)
385 ADS_STRUCT *ads;
386 ADS_STATUS status;
387 void *res=NULL;
388 int rc = -1;
390 if (argc < 1) return net_ads_group_usage(argc, argv);
392 if (!(ads = ads_startup())) return -1;
394 status = ads_find_user_acct(ads, &res, argv[0]);
396 if (!ADS_ERR_OK(status)) {
397 d_printf("ads_group_add: %s\n", ads_errstr(status));
398 goto done;
401 if (ads_count_replies(ads, res)) {
402 d_printf("ads_group_add: Group %s already exists\n", argv[0]);
403 ads_msgfree(ads, res);
404 goto done;
407 status = ads_add_group_acct(ads, argv[0], opt_comment);
409 if (ADS_ERR_OK(status)) {
410 d_printf("Group %s added\n", argv[0]);
411 rc = 0;
412 } else {
413 d_printf("Could not add group %s: %s\n", argv[0],
414 ads_errstr(status));
417 done:
418 if (res)
419 ads_msgfree(ads, res);
420 ads_destroy(&ads);
421 return rc;
424 static int ads_group_delete(int argc, const char **argv)
426 ADS_STRUCT *ads;
427 ADS_STATUS rc;
428 void *res;
429 char *groupdn;
431 if (argc < 1) return net_ads_group_usage(argc, argv);
433 if (!(ads = ads_startup())) return -1;
435 rc = ads_find_user_acct(ads, &res, argv[0]);
436 if (!ADS_ERR_OK(rc)) {
437 DEBUG(0, ("Group %s does not exist\n", argv[0]));
438 return -1;
440 groupdn = ads_get_dn(ads, res);
441 ads_msgfree(ads, res);
442 rc = ads_del_dn(ads, groupdn);
443 ads_memfree(ads, groupdn);
444 if (!ADS_ERR_OK(rc)) {
445 d_printf("Group %s deleted\n", argv[0]);
446 return 0;
448 d_printf("Error deleting group %s: %s\n", argv[0],
449 ads_errstr(rc));
450 return -1;
453 int net_ads_group(int argc, const char **argv)
455 struct functable func[] = {
456 {"ADD", ads_group_add},
457 {"DELETE", ads_group_delete},
458 {NULL, NULL}
460 ADS_STRUCT *ads;
461 ADS_STATUS rc;
462 const char *shortattrs[] = {"sAMAccountName", NULL};
463 const char *longattrs[] = {"sAMAccountName", "description", NULL};
464 char *disp_fields[2] = {NULL, NULL};
466 if (argc == 0) {
467 if (!(ads = ads_startup())) return -1;
469 if (opt_long_list_entries)
470 d_printf("\nGroup name Comment"\
471 "\n-----------------------------\n");
472 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
473 LDAP_SCOPE_SUBTREE,
474 "(objectclass=group)",
475 opt_long_list_entries ? longattrs :
476 shortattrs, usergrp_display,
477 disp_fields);
479 ads_destroy(&ads);
480 return 0;
482 return net_run_function(argc, argv, func, net_ads_group_usage);
485 static int net_ads_status(int argc, const char **argv)
487 ADS_STRUCT *ads;
488 ADS_STATUS rc;
489 extern pstring global_myname;
490 void *res;
492 if (!(ads = ads_startup())) return -1;
494 rc = ads_find_machine_acct(ads, &res, global_myname);
495 if (!ADS_ERR_OK(rc)) {
496 d_printf("ads_find_machine_acct: %s\n", ads_errstr(rc));
497 return -1;
500 if (ads_count_replies(ads, res) == 0) {
501 d_printf("No machine account for '%s' found\n", global_myname);
502 return -1;
505 ads_dump(ads, res);
507 return 0;
510 static int net_ads_leave(int argc, const char **argv)
512 ADS_STRUCT *ads = NULL;
513 ADS_STATUS rc;
514 extern pstring global_myname;
516 if (!secrets_init()) {
517 DEBUG(1,("Failed to initialise secrets database\n"));
518 return -1;
521 if (!opt_password) {
522 asprintf(&opt_user_name, "%s$", global_myname);
523 opt_password = secrets_fetch_machine_password();
526 if (!(ads = ads_startup())) {
527 return -1;
530 rc = ads_leave_realm(ads, global_myname);
531 if (!ADS_ERR_OK(rc)) {
532 d_printf("Failed to delete host '%s' from the '%s' realm.\n",
533 global_myname, ads->config.realm);
534 return -1;
537 d_printf("Removed '%s' from realm '%s'\n", global_myname, ads->config.realm);
539 return 0;
542 static int net_ads_join_ok(void)
544 ADS_STRUCT *ads = NULL;
545 extern pstring global_myname;
547 if (!secrets_init()) {
548 DEBUG(1,("Failed to initialise secrets database\n"));
549 return -1;
552 asprintf(&opt_user_name, "%s$", global_myname);
553 opt_password = secrets_fetch_machine_password();
555 if (!(ads = ads_startup())) {
556 return -1;
559 ads_destroy(&ads);
560 return 0;
564 check that an existing join is OK
566 int net_ads_testjoin(int argc, const char **argv)
568 /* Display success or failure */
569 if (net_ads_join_ok() != 0) {
570 fprintf(stderr,"Join to domain is not valid\n");
571 return -1;
574 printf("Join is OK\n");
575 return 0;
579 join a domain using ADS
581 int net_ads_join(int argc, const char **argv)
583 ADS_STRUCT *ads;
584 ADS_STATUS rc;
585 char *password;
586 char *tmp_password;
587 extern pstring global_myname;
588 const char *org_unit = "Computers";
589 char *dn;
590 void *res;
591 DOM_SID dom_sid;
592 char *ou_str;
594 if (argc > 0) org_unit = argv[0];
596 if (!secrets_init()) {
597 DEBUG(1,("Failed to initialise secrets database\n"));
598 return -1;
601 tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
602 password = strdup(tmp_password);
604 if (!(ads = ads_startup())) return -1;
606 ou_str = ads_ou_string(org_unit);
607 asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path);
608 free(ou_str);
610 rc = ads_search_dn(ads, &res, dn, NULL);
611 ads_msgfree(ads, res);
613 if (rc.error_type == ADS_ERROR_LDAP && rc.rc == LDAP_NO_SUCH_OBJECT) {
614 d_printf("ads_join_realm: organizational unit %s does not exist (dn:%s)\n",
615 org_unit, dn);
616 return -1;
618 free(dn);
620 if (!ADS_ERR_OK(rc)) {
621 d_printf("ads_join_realm: %s\n", ads_errstr(rc));
622 return -1;
625 rc = ads_join_realm(ads, global_myname, org_unit);
626 if (!ADS_ERR_OK(rc)) {
627 d_printf("ads_join_realm: %s\n", ads_errstr(rc));
628 return -1;
631 rc = ads_set_machine_password(ads, global_myname, password);
632 if (!ADS_ERR_OK(rc)) {
633 d_printf("ads_set_machine_password: %s\n", ads_errstr(rc));
634 return -1;
637 rc = ads_domain_sid(ads, &dom_sid);
638 if (!ADS_ERR_OK(rc)) {
639 d_printf("ads_domain_sid: %s\n", ads_errstr(rc));
640 return -1;
643 if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) {
644 DEBUG(1,("Failed to save domain sid\n"));
645 return -1;
648 if (!secrets_store_machine_password(password)) {
649 DEBUG(1,("Failed to save machine password\n"));
650 return -1;
653 d_printf("Joined '%s' to realm '%s'\n", global_myname, ads->config.realm);
655 free(password);
657 return 0;
660 int net_ads_printer_usage(int argc, const char **argv)
662 d_printf(
663 "\nnet ads printer info <printer> <server>"
664 "\n\tlookup info in directory for printer on server"
665 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
666 "\nnet ads printer publish <printername>"
667 "\n\tpublish printer in directory"
668 "\n\t(note: printer name is required)\n"
669 "\nnet ads printer remove <printername>"
670 "\n\tremove printer from directory"
671 "\n\t(note: printer name is required)\n");
672 return -1;
675 static int net_ads_printer_info(int argc, const char **argv)
677 ADS_STRUCT *ads;
678 ADS_STATUS rc;
679 const char *servername, *printername;
680 extern pstring global_myname;
681 void *res = NULL;
683 if (!(ads = ads_startup())) return -1;
685 if (argc > 0)
686 printername = argv[0];
687 else
688 printername = "*";
690 if (argc > 1)
691 servername = argv[1];
692 else
693 servername = global_myname;
695 rc = ads_find_printer_on_server(ads, &res, printername, servername);
697 if (!ADS_ERR_OK(rc)) {
698 d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc));
699 ads_msgfree(ads, res);
700 return -1;
703 if (ads_count_replies(ads, res) == 0) {
704 d_printf("Printer '%s' not found\n", printername);
705 ads_msgfree(ads, res);
706 return -1;
709 ads_dump(ads, res);
710 ads_msgfree(ads, res);
712 return 0;
715 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
717 return;
720 static int net_ads_printer_publish(int argc, const char **argv)
722 ADS_STRUCT *ads;
723 ADS_STATUS rc;
724 char *uncname, *servername;
725 ADS_PRINTER_ENTRY prt;
726 extern pstring global_myname;
727 char *ports[2] = {"Samba", NULL};
730 these const strings are only here as an example. The attributes
731 they represent are not implemented yet
733 const char *bins[] = {"Tray 21", NULL};
734 const char *media[] = {"Letter", NULL};
735 const char *orients[] = {"PORTRAIT", NULL};
737 if (!(ads = ads_startup())) return -1;
739 if (argc < 1)
740 return net_ads_printer_usage(argc, argv);
742 memset(&prt, 0, sizeof(ADS_PRINTER_ENTRY));
744 /* we don't sue the servername or unc name provided by
745 get_a_printer, because the server name might be
746 localhost or an ip address */
747 prt.printerName = argv[0];
748 asprintf(&servername, "%s.%s", global_myname, ads->config.realm);
749 prt.serverName = servername;
750 prt.shortServerName = global_myname;
751 prt.versionNumber = "4";
752 asprintf(&uncname, "\\\\%s\\%s", global_myname, argv[0]);
753 prt.uNCName=uncname;
754 prt.printBinNames = (char **) bins;
755 prt.printMediaSupported = (char **) media;
756 prt.printOrientationsSupported = (char **) orients;
757 prt.portName = (char **) ports;
758 prt.printSpooling = "PrintAfterSpooled";
760 rc = ads_add_printer(ads, &prt);
761 if (!ADS_ERR_OK(rc)) {
762 d_printf("ads_publish_printer: %s\n", ads_errstr(rc));
763 return -1;
766 d_printf("published printer\n");
768 return 0;
771 static int net_ads_printer_remove(int argc, const char **argv)
773 ADS_STRUCT *ads;
774 ADS_STATUS rc;
775 char *servername, *prt_dn;
776 extern pstring global_myname;
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 > 1)
785 servername = argv[1];
786 else
787 servername = global_myname;
789 rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
791 if (!ADS_ERR_OK(rc)) {
792 d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc));
793 ads_msgfree(ads, res);
794 return -1;
797 if (ads_count_replies(ads, res) == 0) {
798 d_printf("Printer '%s' not found\n", argv[1]);
799 ads_msgfree(ads, res);
800 return -1;
803 prt_dn = ads_get_dn(ads, res);
804 ads_msgfree(ads, res);
805 rc = ads_del_dn(ads, prt_dn);
806 ads_memfree(ads, prt_dn);
808 if (!ADS_ERR_OK(rc)) {
809 d_printf("ads_del_dn: %s\n", ads_errstr(rc));
810 return -1;
813 return 0;
816 static int net_ads_printer(int argc, const char **argv)
818 struct functable func[] = {
819 {"INFO", net_ads_printer_info},
820 {"PUBLISH", net_ads_printer_publish},
821 {"REMOVE", net_ads_printer_remove},
822 {NULL, NULL}
825 return net_run_function(argc, argv, func, net_ads_printer_usage);
829 static int net_ads_password(int argc, const char **argv)
831 ADS_STRUCT *ads;
832 char *auth_principal = opt_user_name;
833 char *auth_password = opt_password;
834 char *realm = NULL;
835 char *new_password = NULL;
836 char *c;
837 char *prompt;
838 ADS_STATUS ret;
841 if ((argc != 1) || (opt_user_name == NULL) ||
842 (opt_password == NULL) || (strchr(opt_user_name, '@') == NULL) ||
843 (strchr(argv[0], '@') == NULL)) {
844 return net_ads_usage(argc, argv);
847 c = strchr(auth_principal, '@');
848 realm = ++c;
850 /* use the realm so we can eventually change passwords for users
851 in realms other than default */
852 if (!(ads = ads_init(realm, NULL, NULL))) return -1;
854 asprintf(&prompt, "Enter new password for %s:", argv[0]);
856 new_password = getpass(prompt);
858 ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
859 auth_password, argv[0], new_password);
860 if (!ADS_ERR_OK(ret)) {
861 d_printf("Password change failed :-( ...\n");
862 ads_destroy(&ads);
863 free(prompt);
864 return -1;
867 d_printf("Password change for %s completed.\n", argv[0]);
868 ads_destroy(&ads);
869 free(prompt);
871 return 0;
875 static int net_ads_change_localhost_pass(int argc, const char **argv)
877 ADS_STRUCT *ads;
878 extern pstring global_myname;
879 char *host_principal;
880 char *hostname;
881 ADS_STATUS ret;
883 if (!secrets_init()) {
884 DEBUG(1,("Failed to initialise secrets database\n"));
885 return -1;
888 asprintf(&opt_user_name, "%s$", global_myname);
889 opt_password = secrets_fetch_machine_password();
891 if (!(ads = ads_startup())) {
892 return -1;
895 hostname = strdup(global_myname);
896 strlower(hostname);
897 asprintf(&host_principal, "%s@%s", hostname, ads->config.realm);
898 SAFE_FREE(hostname);
899 d_printf("Changing password for principal: HOST/%s\n", host_principal);
901 ret = ads_change_trust_account_password(ads, host_principal);
903 if (!ADS_ERR_OK(ret)) {
904 d_printf("Password change failed :-( ...\n");
905 ads_destroy(&ads);
906 SAFE_FREE(host_principal);
907 return -1;
910 d_printf("Password change for principal HOST/%s succeeded.\n", host_principal);
911 ads_destroy(&ads);
912 SAFE_FREE(host_principal);
914 return 0;
918 help for net ads search
920 static int net_ads_search_usage(int argc, const char **argv)
922 d_printf(
923 "\nnet ads search <expression> <attributes...>\n"\
924 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
925 "The expression is a standard LDAP search expression, and the\n"\
926 "attributes are a list of LDAP fields to show in the results\n\n"\
927 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
929 net_common_flags_usage(argc, argv);
930 return -1;
935 general ADS search function. Useful in diagnosing problems in ADS
937 static int net_ads_search(int argc, const char **argv)
939 ADS_STRUCT *ads;
940 ADS_STATUS rc;
941 const char *exp;
942 const char **attrs;
943 void *res = NULL;
945 if (argc < 1) {
946 return net_ads_search_usage(argc, argv);
949 if (!(ads = ads_startup())) {
950 return -1;
953 exp = argv[0];
954 attrs = (argv + 1);
956 rc = ads_do_search_all(ads, ads->config.bind_path,
957 LDAP_SCOPE_SUBTREE,
958 exp, attrs, &res);
959 if (!ADS_ERR_OK(rc)) {
960 d_printf("search failed: %s\n", ads_errstr(rc));
961 return -1;
964 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
966 /* dump the results */
967 ads_dump(ads, res);
969 ads_msgfree(ads, res);
970 ads_destroy(&ads);
972 return 0;
976 int net_ads_help(int argc, const char **argv)
978 struct functable func[] = {
979 {"USER", net_ads_user_usage},
980 {"GROUP", net_ads_group_usage},
981 {"PRINTER", net_ads_printer_usage},
982 {"SEARCH", net_ads_search_usage},
983 #if 0
984 {"INFO", net_ads_info},
985 {"JOIN", net_ads_join},
986 {"LEAVE", net_ads_leave},
987 {"STATUS", net_ads_status},
988 {"PASSWORD", net_ads_password},
989 {"CHOSTPASS", net_ads_change_localhost_pass},
990 #endif
991 {NULL, NULL}
994 return net_run_function(argc, argv, func, net_ads_usage);
997 int net_ads(int argc, const char **argv)
999 struct functable func[] = {
1000 {"INFO", net_ads_info},
1001 {"JOIN", net_ads_join},
1002 {"TESTJOIN", net_ads_testjoin},
1003 {"LEAVE", net_ads_leave},
1004 {"STATUS", net_ads_status},
1005 {"USER", net_ads_user},
1006 {"GROUP", net_ads_group},
1007 {"PASSWORD", net_ads_password},
1008 {"CHOSTPASS", net_ads_change_localhost_pass},
1009 {"PRINTER", net_ads_printer},
1010 {"SEARCH", net_ads_search},
1011 {"WORKGROUP", net_ads_workgroup},
1012 {"HELP", net_ads_help},
1013 {NULL, NULL}
1016 return net_run_function(argc, argv, func, net_ads_usage);
1019 #else
1021 static int net_ads_noads(void)
1023 d_printf("ADS support not compiled in\n");
1024 return -1;
1027 int net_ads_usage(int argc, const char **argv)
1029 return net_ads_noads();
1032 int net_ads_help(int argc, const char **argv)
1034 return net_ads_noads();
1037 int net_ads_join(int argc, const char **argv)
1039 return net_ads_noads();
1042 int net_ads_user(int argc, const char **argv)
1044 return net_ads_noads();
1047 int net_ads_group(int argc, const char **argv)
1049 return net_ads_noads();
1052 /* this one shouldn't display a message */
1053 int net_ads_check(void)
1055 return -1;
1058 int net_ads(int argc, const char **argv)
1060 return net_ads_usage(argc, argv);
1063 #endif