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;
129 ads = ads_init(NULL, NULL, opt_host);
131 if (!opt_user_name) {
132 opt_user_name = "administrator";
135 if (opt_user_specified) {
136 need_password = True;
140 if (!opt_password && need_password) {
142 asprintf(&prompt,"%s password: ", opt_user_name);
143 opt_password = getpass(prompt);
148 use_in_memory_ccache();
149 ads->auth.password = strdup(opt_password);
152 ads->auth.user_name = strdup(opt_user_name);
155 * If the username is of the form "name@realm",
156 * extract the realm and convert to upper case.
158 if ((realm = strchr(ads->auth.user_name, '@'))) {
160 ads->auth.realm = strdup(realm);
161 strupper(ads->auth.realm);
164 status = ads_connect(ads);
165 if (!ADS_ERR_OK(status)) {
166 if (!need_password && !second_time) {
167 need_password = True;
171 DEBUG(1,("ads_connect: %s\n", ads_errstr(status)));
180 Check to see if connection can be made via ads.
181 ads_startup() stores the password in opt_password if it needs to so
182 that rpc or rap can use it without re-prompting.
184 int net_ads_check(void)
196 determine the netbios workgroup name for a domain
198 static int net_ads_workgroup(int argc, const char **argv)
204 if (!(ads = ads_startup())) return -1;
206 if (!(ctx = talloc_init("net_ads_workgroup"))) {
210 if (!ADS_ERR_OK(ads_workgroup_name(ads, ctx, &workgroup))) {
211 d_printf("Failed to find workgroup for realm '%s'\n",
217 d_printf("Workgroup: %s\n", workgroup);
226 static BOOL usergrp_display(char *field, void **values, void *data_area)
228 char **disp_fields = (char **) data_area;
230 if (!field) { /* must be end of record */
231 if (!strchr_m(disp_fields[0], '$')) {
233 d_printf("%-21.21s %-50.50s\n",
234 disp_fields[0], disp_fields[1]);
236 d_printf("%s\n", disp_fields[0]);
238 SAFE_FREE(disp_fields[0]);
239 SAFE_FREE(disp_fields[1]);
242 if (!values) /* must be new field, indicate string field */
244 if (StrCaseCmp(field, "sAMAccountName") == 0) {
245 disp_fields[0] = strdup((char *) values[0]);
247 if (StrCaseCmp(field, "description") == 0)
248 disp_fields[1] = strdup((char *) values[0]);
252 static int net_ads_user_usage(int argc, const char **argv)
254 return net_help_user(argc, argv);
257 static int ads_user_add(int argc, const char **argv)
265 if (argc < 1) return net_ads_user_usage(argc, argv);
267 if (!(ads = ads_startup())) return -1;
269 status = ads_find_user_acct(ads, &res, argv[0]);
271 if (!ADS_ERR_OK(status)) {
272 d_printf("ads_user_add: %s\n", ads_errstr(status));
276 if (ads_count_replies(ads, res)) {
277 d_printf("ads_user_add: User %s already exists\n", argv[0]);
281 status = ads_add_user_acct(ads, argv[0], opt_container, opt_comment);
283 if (!ADS_ERR_OK(status)) {
284 d_printf("Could not add user %s: %s\n", argv[0],
289 /* if no password is to be set, we're done */
291 d_printf("User %s added\n", argv[0]);
296 /* try setting the password */
297 asprintf(&upn, "%s@%s", argv[0], ads->config.realm);
298 status = krb5_set_password(ads->auth.kdc_server, upn, argv[1], ads->auth.time_offset);
300 if (ADS_ERR_OK(status)) {
301 d_printf("User %s added\n", argv[0]);
306 /* password didn't set, delete account */
307 d_printf("Could not add user %s. Error setting password %s\n",
308 argv[0], ads_errstr(status));
309 ads_msgfree(ads, res);
310 status=ads_find_user_acct(ads, &res, argv[0]);
311 if (ADS_ERR_OK(status)) {
312 userdn = ads_get_dn(ads, res);
313 ads_del_dn(ads, userdn);
314 ads_memfree(ads, userdn);
319 ads_msgfree(ads, res);
324 static int ads_user_info(int argc, const char **argv)
329 const char *attrs[] = {"memberOf", NULL};
330 char *searchstring=NULL;
332 char *escaped_user = escape_ldap_string_alloc(argv[0]);
334 if (argc < 1) return net_ads_user_usage(argc, argv);
336 if (!(ads = ads_startup())) return -1;
339 d_printf("ads_user_info: failed to escape user %s\n", argv[0]);
343 asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user);
344 rc = ads_search(ads, &res, searchstring, attrs);
345 safe_free(searchstring);
347 if (!ADS_ERR_OK(rc)) {
348 d_printf("ads_search: %s\n", ads_errstr(rc));
352 grouplist = ldap_get_values(ads->ld, res, "memberOf");
357 for (i=0;grouplist[i];i++) {
358 groupname = ldap_explode_dn(grouplist[i], 1);
359 d_printf("%s\n", groupname[0]);
360 ldap_value_free(groupname);
362 ldap_value_free(grouplist);
365 ads_msgfree(ads, res);
371 static int ads_user_delete(int argc, const char **argv)
378 if (argc < 1) return net_ads_user_usage(argc, argv);
380 if (!(ads = ads_startup())) return -1;
382 rc = ads_find_user_acct(ads, &res, argv[0]);
383 if (!ADS_ERR_OK(rc)) {
384 DEBUG(0, ("User %s does not exist\n", argv[0]));
387 userdn = ads_get_dn(ads, res);
388 ads_msgfree(ads, res);
389 rc = ads_del_dn(ads, userdn);
390 ads_memfree(ads, userdn);
391 if (!ADS_ERR_OK(rc)) {
392 d_printf("User %s deleted\n", argv[0]);
395 d_printf("Error deleting user %s: %s\n", argv[0],
400 int net_ads_user(int argc, const char **argv)
402 struct functable func[] = {
403 {"ADD", ads_user_add},
404 {"INFO", ads_user_info},
405 {"DELETE", ads_user_delete},
410 const char *shortattrs[] = {"sAMAccountName", NULL};
411 const char *longattrs[] = {"sAMAccountName", "description", NULL};
412 char *disp_fields[2] = {NULL, NULL};
415 if (!(ads = ads_startup())) return -1;
417 if (opt_long_list_entries)
418 d_printf("\nUser name Comment"\
419 "\n-----------------------------\n");
421 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
423 "(objectclass=user)",
424 opt_long_list_entries ? longattrs :
425 shortattrs, usergrp_display,
431 return net_run_function(argc, argv, func, net_ads_user_usage);
434 static int net_ads_group_usage(int argc, const char **argv)
436 return net_help_group(argc, argv);
439 static int ads_group_add(int argc, const char **argv)
446 if (argc < 1) return net_ads_group_usage(argc, argv);
448 if (!(ads = ads_startup())) return -1;
450 status = ads_find_user_acct(ads, &res, argv[0]);
452 if (!ADS_ERR_OK(status)) {
453 d_printf("ads_group_add: %s\n", ads_errstr(status));
457 if (ads_count_replies(ads, res)) {
458 d_printf("ads_group_add: Group %s already exists\n", argv[0]);
459 ads_msgfree(ads, res);
463 status = ads_add_group_acct(ads, argv[0], opt_container, opt_comment);
465 if (ADS_ERR_OK(status)) {
466 d_printf("Group %s added\n", argv[0]);
469 d_printf("Could not add group %s: %s\n", argv[0],
475 ads_msgfree(ads, res);
480 static int ads_group_delete(int argc, const char **argv)
487 if (argc < 1) return net_ads_group_usage(argc, argv);
489 if (!(ads = ads_startup())) return -1;
491 rc = ads_find_user_acct(ads, &res, argv[0]);
492 if (!ADS_ERR_OK(rc)) {
493 DEBUG(0, ("Group %s does not exist\n", argv[0]));
496 groupdn = ads_get_dn(ads, res);
497 ads_msgfree(ads, res);
498 rc = ads_del_dn(ads, groupdn);
499 ads_memfree(ads, groupdn);
500 if (!ADS_ERR_OK(rc)) {
501 d_printf("Group %s deleted\n", argv[0]);
504 d_printf("Error deleting group %s: %s\n", argv[0],
509 int net_ads_group(int argc, const char **argv)
511 struct functable func[] = {
512 {"ADD", ads_group_add},
513 {"DELETE", ads_group_delete},
518 const char *shortattrs[] = {"sAMAccountName", NULL};
519 const char *longattrs[] = {"sAMAccountName", "description", NULL};
520 char *disp_fields[2] = {NULL, NULL};
523 if (!(ads = ads_startup())) return -1;
525 if (opt_long_list_entries)
526 d_printf("\nGroup name Comment"\
527 "\n-----------------------------\n");
528 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
530 "(objectclass=group)",
531 opt_long_list_entries ? longattrs :
532 shortattrs, usergrp_display,
538 return net_run_function(argc, argv, func, net_ads_group_usage);
541 static int net_ads_status(int argc, const char **argv)
547 if (!(ads = ads_startup())) return -1;
549 rc = ads_find_machine_acct(ads, &res, global_myname());
550 if (!ADS_ERR_OK(rc)) {
551 d_printf("ads_find_machine_acct: %s\n", ads_errstr(rc));
555 if (ads_count_replies(ads, res) == 0) {
556 d_printf("No machine account for '%s' found\n", global_myname());
565 static int net_ads_leave(int argc, const char **argv)
567 ADS_STRUCT *ads = NULL;
570 if (!secrets_init()) {
571 DEBUG(1,("Failed to initialise secrets database\n"));
577 asprintf(&user_name, "%s$", global_myname());
578 opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL);
579 opt_user_name = user_name;
582 if (!(ads = ads_startup())) {
586 rc = ads_leave_realm(ads, global_myname());
587 if (!ADS_ERR_OK(rc)) {
588 d_printf("Failed to delete host '%s' from the '%s' realm.\n",
589 global_myname(), ads->config.realm);
593 d_printf("Removed '%s' from realm '%s'\n", global_myname(), ads->config.realm);
598 static int net_ads_join_ok(void)
601 ADS_STRUCT *ads = NULL;
603 if (!secrets_init()) {
604 DEBUG(1,("Failed to initialise secrets database\n"));
608 asprintf(&user_name, "%s$", global_myname());
609 opt_user_name = user_name;
610 opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL);
612 if (!(ads = ads_startup())) {
621 check that an existing join is OK
623 int net_ads_testjoin(int argc, const char **argv)
625 use_in_memory_ccache();
627 /* Display success or failure */
628 if (net_ads_join_ok() != 0) {
629 fprintf(stderr,"Join to domain is not valid\n");
633 printf("Join is OK\n");
638 join a domain using ADS
640 int net_ads_join(int argc, const char **argv)
646 const char *org_unit = "Computers";
651 uint32 sec_channel_type;
652 uint32 account_type = UF_WORKSTATION_TRUST_ACCOUNT;
654 if (argc > 0) org_unit = argv[0];
656 if (!secrets_init()) {
657 DEBUG(1,("Failed to initialise secrets database\n"));
661 /* check what type of join
662 TODO: make this variable like RPC
664 account_type = UF_WORKSTATION_TRUST_ACCOUNT;
666 tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
667 password = strdup(tmp_password);
669 if (!(ads = ads_startup())) return -1;
671 ou_str = ads_ou_string(org_unit);
672 asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path);
675 rc = ads_search_dn(ads, &res, dn, NULL);
676 ads_msgfree(ads, res);
678 if (rc.error_type == ADS_ERROR_LDAP && rc.err.rc == LDAP_NO_SUCH_OBJECT) {
679 d_printf("ads_join_realm: organizational unit %s does not exist (dn:%s)\n",
685 if (!ADS_ERR_OK(rc)) {
686 d_printf("ads_join_realm: %s\n", ads_errstr(rc));
690 rc = ads_join_realm(ads, global_myname(), account_type, org_unit);
691 if (!ADS_ERR_OK(rc)) {
692 d_printf("ads_join_realm: %s\n", ads_errstr(rc));
696 rc = ads_domain_sid(ads, &dom_sid);
697 if (!ADS_ERR_OK(rc)) {
698 d_printf("ads_domain_sid: %s\n", ads_errstr(rc));
702 rc = ads_set_machine_password(ads, global_myname(), password);
703 if (!ADS_ERR_OK(rc)) {
704 d_printf("ads_set_machine_password: %s\n", ads_errstr(rc));
708 if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) {
709 DEBUG(1,("Failed to save domain sid\n"));
713 if (!secrets_store_machine_password(password, lp_workgroup(), sec_channel_type)) {
714 DEBUG(1,("Failed to save machine password\n"));
718 d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm);
725 int net_ads_printer_usage(int argc, const char **argv)
728 "\nnet ads printer info <printer> <server>"
729 "\n\tlookup info in directory for printer on server"
730 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
731 "\nnet ads printer publish <printername>"
732 "\n\tpublish printer in directory"
733 "\n\t(note: printer name is required)\n"
734 "\nnet ads printer remove <printername>"
735 "\n\tremove printer from directory"
736 "\n\t(note: printer name is required)\n");
740 static int net_ads_printer_info(int argc, const char **argv)
744 const char *servername, *printername;
747 if (!(ads = ads_startup())) return -1;
750 printername = argv[0];
755 servername = argv[1];
757 servername = global_myname();
759 rc = ads_find_printer_on_server(ads, &res, printername, servername);
761 if (!ADS_ERR_OK(rc)) {
762 d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc));
763 ads_msgfree(ads, res);
767 if (ads_count_replies(ads, res) == 0) {
768 d_printf("Printer '%s' not found\n", printername);
769 ads_msgfree(ads, res);
774 ads_msgfree(ads, res);
779 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
784 static int net_ads_printer_publish(int argc, const char **argv)
788 const char *servername;
789 struct cli_state *cli;
790 struct in_addr server_ip;
792 TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
793 ADS_MODLIST mods = ads_init_mods(mem_ctx);
794 char *prt_dn, *srv_dn, **srv_cn;
797 if (!(ads = ads_startup())) return -1;
800 return net_ads_printer_usage(argc, argv);
803 servername = argv[1];
805 servername = global_myname();
807 ads_find_machine_acct(ads, &res, servername);
808 srv_dn = ldap_get_dn(ads->ld, res);
809 srv_cn = ldap_explode_dn(srv_dn, 1);
810 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], argv[0], srv_dn);
812 resolve_name(servername, &server_ip, 0x20);
814 nt_status = cli_full_connection(&cli, global_myname(), servername,
817 opt_user_name, opt_workgroup,
818 opt_password ? opt_password : "",
819 CLI_FULL_CONNECTION_USE_KERBEROS,
822 cli_nt_session_open(cli, PI_SPOOLSS);
823 get_remote_printer_publishing_data(cli, mem_ctx, &mods, argv[0]);
825 rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
826 if (!ADS_ERR_OK(rc)) {
827 d_printf("ads_publish_printer: %s\n", ads_errstr(rc));
831 d_printf("published printer\n");
836 static int net_ads_printer_remove(int argc, const char **argv)
840 const char *servername;
844 if (!(ads = ads_startup())) return -1;
847 return net_ads_printer_usage(argc, argv);
850 servername = argv[1];
852 servername = global_myname();
854 rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
856 if (!ADS_ERR_OK(rc)) {
857 d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc));
858 ads_msgfree(ads, res);
862 if (ads_count_replies(ads, res) == 0) {
863 d_printf("Printer '%s' not found\n", argv[1]);
864 ads_msgfree(ads, res);
868 prt_dn = ads_get_dn(ads, res);
869 ads_msgfree(ads, res);
870 rc = ads_del_dn(ads, prt_dn);
871 ads_memfree(ads, prt_dn);
873 if (!ADS_ERR_OK(rc)) {
874 d_printf("ads_del_dn: %s\n", ads_errstr(rc));
881 static int net_ads_printer(int argc, const char **argv)
883 struct functable func[] = {
884 {"INFO", net_ads_printer_info},
885 {"PUBLISH", net_ads_printer_publish},
886 {"REMOVE", net_ads_printer_remove},
890 return net_run_function(argc, argv, func, net_ads_printer_usage);
894 static int net_ads_password(int argc, const char **argv)
897 const char *auth_principal = opt_user_name;
898 const char *auth_password = opt_password;
900 char *new_password = NULL;
906 if ((argc != 1) || (opt_user_name == NULL) ||
907 (opt_password == NULL) || (strchr(opt_user_name, '@') == NULL) ||
908 (strchr(argv[0], '@') == NULL)) {
909 return net_ads_usage(argc, argv);
912 use_in_memory_ccache();
913 c = strchr(auth_principal, '@');
916 /* use the realm so we can eventually change passwords for users
917 in realms other than default */
918 if (!(ads = ads_init(realm, NULL, NULL))) return -1;
920 /* we don't actually need a full connect, but it's the easy way to
921 fill in the KDC's addresss */
924 if (!ads || !ads->config.realm) {
925 d_printf("Didn't find the kerberos server!\n");
929 asprintf(&prompt, "Enter new password for %s:", argv[0]);
931 new_password = getpass(prompt);
933 ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
934 auth_password, argv[0], new_password, ads->auth.time_offset);
935 if (!ADS_ERR_OK(ret)) {
936 d_printf("Password change failed :-( ...\n");
942 d_printf("Password change for %s completed.\n", argv[0]);
950 int net_ads_changetrustpw(int argc, const char **argv)
953 char *host_principal;
958 if (!secrets_init()) {
959 DEBUG(1,("Failed to initialise secrets database\n"));
963 asprintf(&user_name, "%s$", global_myname());
964 opt_user_name = user_name;
966 opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL);
968 use_in_memory_ccache();
970 if (!(ads = ads_startup())) {
974 hostname = strdup(global_myname());
976 asprintf(&host_principal, "%s@%s", hostname, ads->config.realm);
978 d_printf("Changing password for principal: HOST/%s\n", host_principal);
980 ret = ads_change_trust_account_password(ads, host_principal);
982 if (!ADS_ERR_OK(ret)) {
983 d_printf("Password change failed :-( ...\n");
985 SAFE_FREE(host_principal);
989 d_printf("Password change for principal HOST/%s succeeded.\n", host_principal);
991 SAFE_FREE(host_principal);
997 help for net ads search
999 static int net_ads_search_usage(int argc, const char **argv)
1002 "\nnet ads search <expression> <attributes...>\n"\
1003 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
1004 "The expression is a standard LDAP search expression, and the\n"\
1005 "attributes are a list of LDAP fields to show in the results\n\n"\
1006 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
1008 net_common_flags_usage(argc, argv);
1014 general ADS search function. Useful in diagnosing problems in ADS
1016 static int net_ads_search(int argc, const char **argv)
1025 return net_ads_search_usage(argc, argv);
1028 if (!(ads = ads_startup())) {
1035 rc = ads_do_search_all(ads, ads->config.bind_path,
1038 if (!ADS_ERR_OK(rc)) {
1039 d_printf("search failed: %s\n", ads_errstr(rc));
1043 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
1045 /* dump the results */
1048 ads_msgfree(ads, res);
1056 help for net ads search
1058 static int net_ads_dn_usage(int argc, const char **argv)
1061 "\nnet ads dn <dn> <attributes...>\n"\
1062 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
1063 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"\
1064 "to show in the results\n\n"\
1065 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
1067 net_common_flags_usage(argc, argv);
1073 general ADS search function. Useful in diagnosing problems in ADS
1075 static int net_ads_dn(int argc, const char **argv)
1084 return net_ads_dn_usage(argc, argv);
1087 if (!(ads = ads_startup())) {
1094 rc = ads_do_search_all(ads, dn,
1096 "(objectclass=*)", attrs, &res);
1097 if (!ADS_ERR_OK(rc)) {
1098 d_printf("search failed: %s\n", ads_errstr(rc));
1102 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
1104 /* dump the results */
1107 ads_msgfree(ads, res);
1114 int net_ads_help(int argc, const char **argv)
1116 struct functable func[] = {
1117 {"USER", net_ads_user_usage},
1118 {"GROUP", net_ads_group_usage},
1119 {"PRINTER", net_ads_printer_usage},
1120 {"SEARCH", net_ads_search_usage},
1122 {"INFO", net_ads_info},
1123 {"JOIN", net_ads_join},
1124 {"LEAVE", net_ads_leave},
1125 {"STATUS", net_ads_status},
1126 {"PASSWORD", net_ads_password},
1127 {"CHANGETRUSTPW", net_ads_changetrustpw},
1132 return net_run_function(argc, argv, func, net_ads_usage);
1135 int net_ads(int argc, const char **argv)
1137 struct functable func[] = {
1138 {"INFO", net_ads_info},
1139 {"JOIN", net_ads_join},
1140 {"TESTJOIN", net_ads_testjoin},
1141 {"LEAVE", net_ads_leave},
1142 {"STATUS", net_ads_status},
1143 {"USER", net_ads_user},
1144 {"GROUP", net_ads_group},
1145 {"PASSWORD", net_ads_password},
1146 {"CHANGETRUSTPW", net_ads_changetrustpw},
1147 {"PRINTER", net_ads_printer},
1148 {"SEARCH", net_ads_search},
1150 {"WORKGROUP", net_ads_workgroup},
1151 {"LOOKUP", net_ads_lookup},
1152 {"HELP", net_ads_help},
1156 return net_run_function(argc, argv, func, net_ads_usage);
1161 static int net_ads_noads(void)
1163 d_printf("ADS support not compiled in\n");
1167 int net_ads_usage(int argc, const char **argv)
1169 return net_ads_noads();
1172 int net_ads_help(int argc, const char **argv)
1174 return net_ads_noads();
1177 int net_ads_changetrustpw(int argc, const char **argv)
1179 return net_ads_noads();
1182 int net_ads_join(int argc, const char **argv)
1184 return net_ads_noads();
1187 int net_ads_user(int argc, const char **argv)
1189 return net_ads_noads();
1192 int net_ads_group(int argc, const char **argv)
1194 return net_ads_noads();
1197 /* this one shouldn't display a message */
1198 int net_ads_check(void)
1203 int net_ads(int argc, const char **argv)
1205 return net_ads_usage(argc, argv);