2 Samba Unix/Linux SMB client library
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.
24 #include "../utils/net.h"
28 int net_ads_usage(int argc, const char **argv)
31 "\nnet ads join <org_unit>"\
32 "\n\tjoins the local machine to a ADS realm\n"\
34 "\n\tremoves the local machine from a ADS realm\n"\
36 "\n\ttests that an exiting join is OK\n"\
38 "\n\tlist, add, or delete users in the realm\n"\
40 "\n\tlist, add, or delete groups in the realm\n"\
42 "\n\tshows some info on the server\n"\
44 "\n\tdump the machine account details to stdout\n"
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 changetrustpw"\
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"\
55 "\n\tperform a raw LDAP search and dump the results\n"
57 "\n\tperform a raw LDAP search and dump attributes of a particular DN\n"
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)
71 ads = ads_init(NULL, NULL, opt_host);
73 ads->auth.flags |= ADS_AUTH_NO_BIND;
78 if (!ads || !ads->config.realm) {
79 d_printf("Didn't find the cldap server!\n");
83 return ads_cldap_netlogon(ads);
88 static int net_ads_info(int argc, const char **argv)
92 ads = ads_init(NULL, NULL, opt_host);
95 ads->auth.flags |= ADS_AUTH_NO_BIND;
100 if (!ads || !ads->config.realm) {
101 d_printf("Didn't find the ldap server!\n");
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));
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)
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;
139 if (!opt_password && need_password) {
141 asprintf(&prompt,"%s password: ", opt_user_name);
142 opt_password = getpass(prompt);
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;
160 DEBUG(1,("ads_connect: %s\n", ads_errstr(status)));
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)
185 determine the netbios workgroup name for a domain
187 static int net_ads_workgroup(int argc, const char **argv)
193 if (!(ads = ads_startup())) return -1;
195 if (!(ctx = talloc_init("net_ads_workgroup"))) {
199 if (!ADS_ERR_OK(ads_workgroup_name(ads, ctx, &workgroup))) {
200 d_printf("Failed to find workgroup for realm '%s'\n",
206 d_printf("Workgroup: %s\n", workgroup);
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], '$')) {
222 d_printf("%-21.21s %-50.50s\n",
223 disp_fields[0], disp_fields[1]);
225 d_printf("%s\n", disp_fields[0]);
227 SAFE_FREE(disp_fields[0]);
228 SAFE_FREE(disp_fields[1]);
231 if (!values) /* must be new field, indicate string field */
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]);
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)
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));
265 if (ads_count_replies(ads, res)) {
266 d_printf("ads_user_add: User %s already exists\n", argv[0]);
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],
278 /* if no password is to be set, we're done */
280 d_printf("User %s added\n", argv[0]);
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);
289 if (ADS_ERR_OK(status)) {
290 d_printf("User %s added\n", argv[0]);
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);
308 ads_msgfree(ads, res);
313 static int ads_user_info(int argc, const char **argv)
318 const char *attrs[] = {"memberOf", NULL};
319 char *searchstring=NULL;
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;
328 d_printf("ads_user_info: failed to escape user %s\n", argv[0]);
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));
341 grouplist = ldap_get_values(ads->ld, res, "memberOf");
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);
360 static int ads_user_delete(int argc, const char **argv)
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]));
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]);
384 d_printf("Error deleting user %s: %s\n", argv[0],
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},
399 const char *shortattrs[] = {"sAMAccountName", NULL};
400 const char *longattrs[] = {"sAMAccountName", "description", NULL};
401 char *disp_fields[2] = {NULL, NULL};
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,
412 "(objectclass=user)",
413 opt_long_list_entries ? longattrs :
414 shortattrs, usergrp_display,
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)
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));
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);
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]);
458 d_printf("Could not add group %s: %s\n", argv[0],
464 ads_msgfree(ads, res);
469 static int ads_group_delete(int argc, const char **argv)
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]));
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]);
493 d_printf("Error deleting group %s: %s\n", argv[0],
498 int net_ads_group(int argc, const char **argv)
500 struct functable func[] = {
501 {"ADD", ads_group_add},
502 {"DELETE", ads_group_delete},
507 const char *shortattrs[] = {"sAMAccountName", NULL};
508 const char *longattrs[] = {"sAMAccountName", "description", NULL};
509 char *disp_fields[2] = {NULL, NULL};
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,
519 "(objectclass=group)",
520 opt_long_list_entries ? longattrs :
521 shortattrs, usergrp_display,
527 return net_run_function(argc, argv, func, net_ads_group_usage);
530 static int net_ads_status(int argc, const char **argv)
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));
544 if (ads_count_replies(ads, res) == 0) {
545 d_printf("No machine account for '%s' found\n", global_myname());
554 static int net_ads_leave(int argc, const char **argv)
556 ADS_STRUCT *ads = NULL;
559 if (!secrets_init()) {
560 DEBUG(1,("Failed to initialise secrets database\n"));
566 asprintf(&user_name, "%s$", global_myname());
567 opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL);
568 opt_user_name = user_name;
571 if (!(ads = ads_startup())) {
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);
582 d_printf("Removed '%s' from realm '%s'\n", global_myname(), ads->config.realm);
587 static int net_ads_join_ok(void)
590 ADS_STRUCT *ads = NULL;
592 if (!secrets_init()) {
593 DEBUG(1,("Failed to initialise secrets database\n"));
597 asprintf(&user_name, "%s$", global_myname());
598 opt_user_name = user_name;
599 opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL);
601 if (!(ads = ads_startup())) {
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");
622 printf("Join is OK\n");
627 join a domain using ADS
629 int net_ads_join(int argc, const char **argv)
635 const char *org_unit = "Computers";
640 uint32 sec_channel_type = SEC_CHAN_WKSTA;
641 uint32 account_type = UF_WORKSTATION_TRUST_ACCOUNT;
643 if (argc > 0) org_unit = argv[0];
645 if (!secrets_init()) {
646 DEBUG(1,("Failed to initialise secrets database\n"));
650 tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
651 password = strdup(tmp_password);
653 if (!(ads = ads_startup())) return -1;
655 ou_str = ads_ou_string(org_unit);
656 asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path);
659 rc = ads_search_dn(ads, &res, dn, NULL);
660 ads_msgfree(ads, res);
662 if (rc.error_type == ADS_ERROR_LDAP && rc.err.rc == LDAP_NO_SUCH_OBJECT) {
663 d_printf("ads_join_realm: organizational unit %s does not exist (dn:%s)\n",
669 if (!ADS_ERR_OK(rc)) {
670 d_printf("ads_join_realm: %s\n", ads_errstr(rc));
674 rc = ads_join_realm(ads, global_myname(), account_type, org_unit);
675 if (!ADS_ERR_OK(rc)) {
676 d_printf("ads_join_realm: %s\n", ads_errstr(rc));
680 rc = ads_domain_sid(ads, &dom_sid);
681 if (!ADS_ERR_OK(rc)) {
682 d_printf("ads_domain_sid: %s\n", ads_errstr(rc));
686 rc = ads_set_machine_password(ads, global_myname(), password);
687 if (!ADS_ERR_OK(rc)) {
688 d_printf("ads_set_machine_password: %s\n", ads_errstr(rc));
692 if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) {
693 DEBUG(1,("Failed to save domain sid\n"));
697 if (!secrets_store_machine_password(password, lp_workgroup(), sec_channel_type)) {
698 DEBUG(1,("Failed to save machine password\n"));
702 d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm);
709 int net_ads_printer_usage(int argc, const char **argv)
712 "\nnet ads printer info <printer> <server>"
713 "\n\tlookup info in directory for printer on server"
714 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
715 "\nnet ads printer publish <printername>"
716 "\n\tpublish printer in directory"
717 "\n\t(note: printer name is required)\n"
718 "\nnet ads printer remove <printername>"
719 "\n\tremove printer from directory"
720 "\n\t(note: printer name is required)\n");
724 static int net_ads_printer_info(int argc, const char **argv)
728 const char *servername, *printername;
731 if (!(ads = ads_startup())) return -1;
734 printername = argv[0];
739 servername = argv[1];
741 servername = global_myname();
743 rc = ads_find_printer_on_server(ads, &res, printername, servername);
745 if (!ADS_ERR_OK(rc)) {
746 d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc));
747 ads_msgfree(ads, res);
751 if (ads_count_replies(ads, res) == 0) {
752 d_printf("Printer '%s' not found\n", printername);
753 ads_msgfree(ads, res);
758 ads_msgfree(ads, res);
763 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
768 static int net_ads_printer_publish(int argc, const char **argv)
772 const char *servername;
773 struct cli_state *cli;
774 struct in_addr server_ip;
776 TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
777 ADS_MODLIST mods = ads_init_mods(mem_ctx);
778 char *prt_dn, *srv_dn, **srv_cn;
781 if (!(ads = ads_startup())) return -1;
784 return net_ads_printer_usage(argc, argv);
787 servername = argv[1];
789 servername = global_myname();
791 ads_find_machine_acct(ads, &res, servername);
792 srv_dn = ldap_get_dn(ads->ld, res);
793 srv_cn = ldap_explode_dn(srv_dn, 1);
794 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], argv[0], srv_dn);
796 resolve_name(servername, &server_ip, 0x20);
798 nt_status = cli_full_connection(&cli, global_myname(), servername,
801 opt_user_name, opt_workgroup,
802 opt_password ? opt_password : "",
803 CLI_FULL_CONNECTION_USE_KERBEROS,
806 cli_nt_session_open(cli, PI_SPOOLSS);
807 get_remote_printer_publishing_data(cli, mem_ctx, &mods, argv[0]);
809 rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
810 if (!ADS_ERR_OK(rc)) {
811 d_printf("ads_publish_printer: %s\n", ads_errstr(rc));
815 d_printf("published printer\n");
820 static int net_ads_printer_remove(int argc, const char **argv)
824 const char *servername;
828 if (!(ads = ads_startup())) return -1;
831 return net_ads_printer_usage(argc, argv);
834 servername = argv[1];
836 servername = global_myname();
838 rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
840 if (!ADS_ERR_OK(rc)) {
841 d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc));
842 ads_msgfree(ads, res);
846 if (ads_count_replies(ads, res) == 0) {
847 d_printf("Printer '%s' not found\n", argv[1]);
848 ads_msgfree(ads, res);
852 prt_dn = ads_get_dn(ads, res);
853 ads_msgfree(ads, res);
854 rc = ads_del_dn(ads, prt_dn);
855 ads_memfree(ads, prt_dn);
857 if (!ADS_ERR_OK(rc)) {
858 d_printf("ads_del_dn: %s\n", ads_errstr(rc));
865 static int net_ads_printer(int argc, const char **argv)
867 struct functable func[] = {
868 {"INFO", net_ads_printer_info},
869 {"PUBLISH", net_ads_printer_publish},
870 {"REMOVE", net_ads_printer_remove},
874 return net_run_function(argc, argv, func, net_ads_printer_usage);
878 static int net_ads_password(int argc, const char **argv)
881 const char *auth_principal = opt_user_name;
882 const char *auth_password = opt_password;
884 char *new_password = NULL;
890 if ((argc != 1) || (opt_user_name == NULL) ||
891 (opt_password == NULL) || (strchr(opt_user_name, '@') == NULL) ||
892 (strchr(argv[0], '@') == NULL)) {
893 return net_ads_usage(argc, argv);
896 use_in_memory_ccache();
897 c = strchr(auth_principal, '@');
900 /* use the realm so we can eventually change passwords for users
901 in realms other than default */
902 if (!(ads = ads_init(realm, NULL, NULL))) return -1;
904 /* we don't actually need a full connect, but it's the easy way to
905 fill in the KDC's addresss */
908 if (!ads || !ads->config.realm) {
909 d_printf("Didn't find the kerberos server!\n");
913 asprintf(&prompt, "Enter new password for %s:", argv[0]);
915 new_password = getpass(prompt);
917 ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
918 auth_password, argv[0], new_password, ads->auth.time_offset);
919 if (!ADS_ERR_OK(ret)) {
920 d_printf("Password change failed :-( ...\n");
926 d_printf("Password change for %s completed.\n", argv[0]);
934 int net_ads_changetrustpw(int argc, const char **argv)
937 char *host_principal;
942 if (!secrets_init()) {
943 DEBUG(1,("Failed to initialise secrets database\n"));
947 asprintf(&user_name, "%s$", global_myname());
948 opt_user_name = user_name;
950 opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL);
952 use_in_memory_ccache();
954 if (!(ads = ads_startup())) {
958 hostname = strdup(global_myname());
960 asprintf(&host_principal, "%s@%s", hostname, ads->config.realm);
962 d_printf("Changing password for principal: HOST/%s\n", host_principal);
964 ret = ads_change_trust_account_password(ads, host_principal);
966 if (!ADS_ERR_OK(ret)) {
967 d_printf("Password change failed :-( ...\n");
969 SAFE_FREE(host_principal);
973 d_printf("Password change for principal HOST/%s succeeded.\n", host_principal);
975 SAFE_FREE(host_principal);
981 help for net ads search
983 static int net_ads_search_usage(int argc, const char **argv)
986 "\nnet ads search <expression> <attributes...>\n"\
987 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
988 "The expression is a standard LDAP search expression, and the\n"\
989 "attributes are a list of LDAP fields to show in the results\n\n"\
990 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
992 net_common_flags_usage(argc, argv);
998 general ADS search function. Useful in diagnosing problems in ADS
1000 static int net_ads_search(int argc, const char **argv)
1009 return net_ads_search_usage(argc, argv);
1012 if (!(ads = ads_startup())) {
1019 rc = ads_do_search_all(ads, ads->config.bind_path,
1022 if (!ADS_ERR_OK(rc)) {
1023 d_printf("search failed: %s\n", ads_errstr(rc));
1027 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
1029 /* dump the results */
1032 ads_msgfree(ads, res);
1040 help for net ads search
1042 static int net_ads_dn_usage(int argc, const char **argv)
1045 "\nnet ads dn <dn> <attributes...>\n"\
1046 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
1047 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"\
1048 "to show in the results\n\n"\
1049 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
1051 net_common_flags_usage(argc, argv);
1057 general ADS search function. Useful in diagnosing problems in ADS
1059 static int net_ads_dn(int argc, const char **argv)
1068 return net_ads_dn_usage(argc, argv);
1071 if (!(ads = ads_startup())) {
1078 rc = ads_do_search_all(ads, dn,
1080 "(objectclass=*)", attrs, &res);
1081 if (!ADS_ERR_OK(rc)) {
1082 d_printf("search failed: %s\n", ads_errstr(rc));
1086 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
1088 /* dump the results */
1091 ads_msgfree(ads, res);
1098 int net_ads_help(int argc, const char **argv)
1100 struct functable func[] = {
1101 {"USER", net_ads_user_usage},
1102 {"GROUP", net_ads_group_usage},
1103 {"PRINTER", net_ads_printer_usage},
1104 {"SEARCH", net_ads_search_usage},
1106 {"INFO", net_ads_info},
1107 {"JOIN", net_ads_join},
1108 {"LEAVE", net_ads_leave},
1109 {"STATUS", net_ads_status},
1110 {"PASSWORD", net_ads_password},
1111 {"CHANGETRUSTPW", net_ads_changetrustpw},
1116 return net_run_function(argc, argv, func, net_ads_usage);
1119 int net_ads(int argc, const char **argv)
1121 struct functable func[] = {
1122 {"INFO", net_ads_info},
1123 {"JOIN", net_ads_join},
1124 {"TESTJOIN", net_ads_testjoin},
1125 {"LEAVE", net_ads_leave},
1126 {"STATUS", net_ads_status},
1127 {"USER", net_ads_user},
1128 {"GROUP", net_ads_group},
1129 {"PASSWORD", net_ads_password},
1130 {"CHANGETRUSTPW", net_ads_changetrustpw},
1131 {"PRINTER", net_ads_printer},
1132 {"SEARCH", net_ads_search},
1134 {"WORKGROUP", net_ads_workgroup},
1135 {"LOOKUP", net_ads_lookup},
1136 {"HELP", net_ads_help},
1140 return net_run_function(argc, argv, func, net_ads_usage);
1145 static int net_ads_noads(void)
1147 d_printf("ADS support not compiled in\n");
1151 int net_ads_usage(int argc, const char **argv)
1153 return net_ads_noads();
1156 int net_ads_help(int argc, const char **argv)
1158 return net_ads_noads();
1161 int net_ads_changetrustpw(int argc, const char **argv)
1163 return net_ads_noads();
1166 int net_ads_join(int argc, const char **argv)
1168 return net_ads_noads();
1171 int net_ads_user(int argc, const char **argv)
1173 return net_ads_noads();
1176 int net_ads_group(int argc, const char **argv)
1178 return net_ads_noads();
1181 /* this one shouldn't display a message */
1182 int net_ads_check(void)
1187 int net_ads(int argc, const char **argv)
1189 return net_ads_usage(argc, argv);