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> <password> -Uadmin_username@realm%%admin_pass"\
48 "\n\tchange a user's password using an admin account"\
49 "\n\t(note: use realm in UPPERCASE, prompts if password is obmitted)\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"
59 "\n\tperform a raw LDAP search and dump attributes of a particular SID\n"
61 "\n\tcreates and updates the kerberos system keytab file\n"
68 this implements the CLDAP based netlogon lookup requests
69 for finding the domain controller of a ADS domain
71 static int net_ads_lookup(int argc, const char **argv)
76 ads = ads_init(NULL, opt_target_workgroup, opt_host);
78 ads->auth.flags |= ADS_AUTH_NO_BIND;
81 status = ads_connect(ads);
82 if (!ADS_ERR_OK(status) || !ads) {
83 d_fprintf(stderr, "Didn't find the cldap server!\n");
87 if (!ads->config.realm) {
88 ads->config.realm = CONST_DISCARD(char *, opt_target_workgroup);
92 return ads_cldap_netlogon(ads);
97 static int net_ads_info(int argc, const char **argv)
101 /* if netbios is disabled we have to default to the realm from smb.conf */
103 if ( lp_disable_netbios() && *lp_realm() )
104 ads = ads_init(lp_realm(), opt_target_workgroup, opt_host);
106 ads = ads_init(NULL, opt_target_workgroup, opt_host);
109 ads->auth.flags |= ADS_AUTH_NO_BIND;
114 if (!ads || !ads->config.realm) {
115 d_fprintf(stderr, "Didn't find the ldap server!\n");
119 d_printf("LDAP server: %s\n", inet_ntoa(ads->ldap_ip));
120 d_printf("LDAP server name: %s\n", ads->config.ldap_server_name);
121 d_printf("Realm: %s\n", ads->config.realm);
122 d_printf("Bind Path: %s\n", ads->config.bind_path);
123 d_printf("LDAP port: %d\n", ads->ldap_port);
124 d_printf("Server time: %s\n", http_timestring(ads->config.current_time));
126 d_printf("KDC server: %s\n", ads->auth.kdc_server );
127 d_printf("Server time offset: %d\n", ads->auth.time_offset );
132 static void use_in_memory_ccache(void) {
133 /* Use in-memory credentials cache so we do not interfere with
134 * existing credentials */
135 setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
138 static ADS_STRUCT *ads_startup(void)
142 BOOL need_password = False;
143 BOOL second_time = False;
146 /* lp_realm() should be handled by a command line param,
147 However, the join requires that realm be set in smb.conf
148 and compares our realm with the remote server's so this is
149 ok until someone needs more flexibility */
151 ads = ads_init(lp_realm(), opt_target_workgroup, opt_host);
153 if (!opt_user_name) {
154 opt_user_name = "administrator";
157 if (opt_user_specified) {
158 need_password = True;
162 if (!opt_password && need_password && !opt_machine_pass) {
164 asprintf(&prompt,"%s's password: ", opt_user_name);
165 opt_password = getpass(prompt);
170 use_in_memory_ccache();
171 ads->auth.password = smb_xstrdup(opt_password);
174 ads->auth.user_name = smb_xstrdup(opt_user_name);
177 * If the username is of the form "name@realm",
178 * extract the realm and convert to upper case.
179 * This is only used to establish the connection.
181 if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
183 ads->auth.realm = smb_xstrdup(cp);
184 strupper_m(ads->auth.realm);
187 status = ads_connect(ads);
189 if (!ADS_ERR_OK(status)) {
190 if (!need_password && !second_time) {
191 need_password = True;
195 DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
204 Check to see if connection can be made via ads.
205 ads_startup() stores the password in opt_password if it needs to so
206 that rpc or rap can use it without re-prompting.
208 int net_ads_check(void)
220 determine the netbios workgroup name for a domain
222 static int net_ads_workgroup(int argc, const char **argv)
226 const char *workgroup;
228 if (!(ads = ads_startup())) return -1;
230 if (!(ctx = talloc_init("net_ads_workgroup"))) {
235 if (!ADS_ERR_OK(ads_workgroup_name(ads, ctx, &workgroup))) {
236 d_fprintf(stderr, "Failed to find workgroup for realm '%s'\n",
243 d_printf("Workgroup: %s\n", workgroup);
252 static BOOL usergrp_display(char *field, void **values, void *data_area)
254 char **disp_fields = (char **) data_area;
256 if (!field) { /* must be end of record */
257 if (disp_fields[0]) {
258 if (!strchr_m(disp_fields[0], '$')) {
260 d_printf("%-21.21s %s\n",
261 disp_fields[0], disp_fields[1]);
263 d_printf("%s\n", disp_fields[0]);
266 SAFE_FREE(disp_fields[0]);
267 SAFE_FREE(disp_fields[1]);
270 if (!values) /* must be new field, indicate string field */
272 if (StrCaseCmp(field, "sAMAccountName") == 0) {
273 disp_fields[0] = SMB_STRDUP((char *) values[0]);
275 if (StrCaseCmp(field, "description") == 0)
276 disp_fields[1] = SMB_STRDUP((char *) values[0]);
280 static int net_ads_user_usage(int argc, const char **argv)
282 return net_help_user(argc, argv);
285 static int ads_user_add(int argc, const char **argv)
293 if (argc < 1) return net_ads_user_usage(argc, argv);
295 if (!(ads = ads_startup())) {
299 status = ads_find_user_acct(ads, &res, argv[0]);
301 if (!ADS_ERR_OK(status)) {
302 d_fprintf(stderr, "ads_user_add: %s\n", ads_errstr(status));
306 if (ads_count_replies(ads, res)) {
307 d_fprintf(stderr, "ads_user_add: User %s already exists\n", argv[0]);
311 if (opt_container == NULL) {
312 opt_container = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS);
315 status = ads_add_user_acct(ads, argv[0], opt_container, opt_comment);
317 if (!ADS_ERR_OK(status)) {
318 d_fprintf(stderr, "Could not add user %s: %s\n", argv[0],
323 /* if no password is to be set, we're done */
325 d_printf("User %s added\n", argv[0]);
330 /* try setting the password */
331 asprintf(&upn, "%s@%s", argv[0], ads->config.realm);
332 status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
333 ads->auth.time_offset);
335 if (ADS_ERR_OK(status)) {
336 d_printf("User %s added\n", argv[0]);
341 /* password didn't set, delete account */
342 d_fprintf(stderr, "Could not add user %s. Error setting password %s\n",
343 argv[0], ads_errstr(status));
344 ads_msgfree(ads, res);
345 status=ads_find_user_acct(ads, &res, argv[0]);
346 if (ADS_ERR_OK(status)) {
347 userdn = ads_get_dn(ads, res);
348 ads_del_dn(ads, userdn);
349 ads_memfree(ads, userdn);
354 ads_msgfree(ads, res);
359 static int ads_user_info(int argc, const char **argv)
364 const char *attrs[] = {"memberOf", NULL};
365 char *searchstring=NULL;
370 return net_ads_user_usage(argc, argv);
373 escaped_user = escape_ldap_string_alloc(argv[0]);
376 d_fprintf(stderr, "ads_user_info: failed to escape user %s\n", argv[0]);
380 if (!(ads = ads_startup())) {
381 SAFE_FREE(escaped_user);
385 asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user);
386 rc = ads_search(ads, &res, searchstring, attrs);
387 safe_free(searchstring);
389 if (!ADS_ERR_OK(rc)) {
390 d_fprintf(stderr, "ads_search: %s\n", ads_errstr(rc));
392 SAFE_FREE(escaped_user);
396 grouplist = ldap_get_values(ads->ld, res, "memberOf");
401 for (i=0;grouplist[i];i++) {
402 groupname = ldap_explode_dn(grouplist[i], 1);
403 d_printf("%s\n", groupname[0]);
404 ldap_value_free(groupname);
406 ldap_value_free(grouplist);
409 ads_msgfree(ads, res);
411 SAFE_FREE(escaped_user);
415 static int ads_user_delete(int argc, const char **argv)
423 return net_ads_user_usage(argc, argv);
426 if (!(ads = ads_startup())) {
430 rc = ads_find_user_acct(ads, &res, argv[0]);
431 if (!ADS_ERR_OK(rc)) {
432 DEBUG(0, ("User %s does not exist\n", argv[0]));
436 userdn = ads_get_dn(ads, res);
437 ads_msgfree(ads, res);
438 rc = ads_del_dn(ads, userdn);
439 ads_memfree(ads, userdn);
440 if (!ADS_ERR_OK(rc)) {
441 d_printf("User %s deleted\n", argv[0]);
445 d_fprintf(stderr, "Error deleting user %s: %s\n", argv[0],
451 int net_ads_user(int argc, const char **argv)
453 struct functable func[] = {
454 {"ADD", ads_user_add},
455 {"INFO", ads_user_info},
456 {"DELETE", ads_user_delete},
461 const char *shortattrs[] = {"sAMAccountName", NULL};
462 const char *longattrs[] = {"sAMAccountName", "description", NULL};
463 char *disp_fields[2] = {NULL, NULL};
466 if (!(ads = ads_startup())) {
470 if (opt_long_list_entries)
471 d_printf("\nUser name Comment"\
472 "\n-----------------------------\n");
474 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
476 "(objectCategory=user)",
477 opt_long_list_entries ? longattrs :
478 shortattrs, usergrp_display,
484 return net_run_function(argc, argv, func, net_ads_user_usage);
487 static int net_ads_group_usage(int argc, const char **argv)
489 return net_help_group(argc, argv);
492 static int ads_group_add(int argc, const char **argv)
500 return net_ads_group_usage(argc, argv);
503 if (!(ads = ads_startup())) {
507 status = ads_find_user_acct(ads, &res, argv[0]);
509 if (!ADS_ERR_OK(status)) {
510 d_fprintf(stderr, "ads_group_add: %s\n", ads_errstr(status));
514 if (ads_count_replies(ads, res)) {
515 d_fprintf(stderr, "ads_group_add: Group %s already exists\n", argv[0]);
516 ads_msgfree(ads, res);
520 if (opt_container == NULL) {
521 opt_container = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS);
524 status = ads_add_group_acct(ads, argv[0], opt_container, opt_comment);
526 if (ADS_ERR_OK(status)) {
527 d_printf("Group %s added\n", argv[0]);
530 d_fprintf(stderr, "Could not add group %s: %s\n", argv[0],
536 ads_msgfree(ads, res);
541 static int ads_group_delete(int argc, const char **argv)
549 return net_ads_group_usage(argc, argv);
552 if (!(ads = ads_startup())) {
556 rc = ads_find_user_acct(ads, &res, argv[0]);
557 if (!ADS_ERR_OK(rc)) {
558 DEBUG(0, ("Group %s does not exist\n", argv[0]));
562 groupdn = ads_get_dn(ads, res);
563 ads_msgfree(ads, res);
564 rc = ads_del_dn(ads, groupdn);
565 ads_memfree(ads, groupdn);
566 if (!ADS_ERR_OK(rc)) {
567 d_printf("Group %s deleted\n", argv[0]);
571 d_fprintf(stderr, "Error deleting group %s: %s\n", argv[0],
577 int net_ads_group(int argc, const char **argv)
579 struct functable func[] = {
580 {"ADD", ads_group_add},
581 {"DELETE", ads_group_delete},
586 const char *shortattrs[] = {"sAMAccountName", NULL};
587 const char *longattrs[] = {"sAMAccountName", "description", NULL};
588 char *disp_fields[2] = {NULL, NULL};
591 if (!(ads = ads_startup())) {
595 if (opt_long_list_entries)
596 d_printf("\nGroup name Comment"\
597 "\n-----------------------------\n");
598 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
600 "(objectCategory=group)",
601 opt_long_list_entries ? longattrs :
602 shortattrs, usergrp_display,
608 return net_run_function(argc, argv, func, net_ads_group_usage);
611 static int net_ads_status(int argc, const char **argv)
617 if (!(ads = ads_startup())) {
621 rc = ads_find_machine_acct(ads, &res, global_myname());
622 if (!ADS_ERR_OK(rc)) {
623 d_fprintf(stderr, "ads_find_machine_acct: %s\n", ads_errstr(rc));
628 if (ads_count_replies(ads, res) == 0) {
629 d_fprintf(stderr, "No machine account for '%s' found\n", global_myname());
639 static int net_ads_leave(int argc, const char **argv)
641 ADS_STRUCT *ads = NULL;
644 if (!secrets_init()) {
645 DEBUG(1,("Failed to initialise secrets database\n"));
650 net_use_machine_password();
653 if (!(ads = ads_startup())) {
657 rc = ads_leave_realm(ads, global_myname());
658 if (!ADS_ERR_OK(rc)) {
659 d_fprintf(stderr, "Failed to delete host '%s' from the '%s' realm.\n",
660 global_myname(), ads->config.realm);
665 d_printf("Removed '%s' from realm '%s'\n", global_myname(), ads->config.realm);
670 static int net_ads_join_ok(void)
672 ADS_STRUCT *ads = NULL;
674 if (!secrets_init()) {
675 DEBUG(1,("Failed to initialise secrets database\n"));
679 net_use_machine_password();
681 if (!(ads = ads_startup())) {
690 check that an existing join is OK
692 int net_ads_testjoin(int argc, const char **argv)
694 use_in_memory_ccache();
696 /* Display success or failure */
697 if (net_ads_join_ok() != 0) {
698 fprintf(stderr,"Join to domain is not valid\n");
702 printf("Join is OK\n");
707 join a domain using ADS
709 int net_ads_join(int argc, const char **argv)
714 char *machine_account = NULL;
716 const char *org_unit = NULL;
721 uint32 sec_channel_type = SEC_CHAN_WKSTA;
722 uint32 account_type = UF_WORKSTATION_TRUST_ACCOUNT;
723 const char *short_domain_name = NULL;
724 TALLOC_CTX *ctx = NULL;
726 if (lp_server_role() == ROLE_STANDALONE) {
727 d_printf("cannot join as standalone machine\n");
731 if (strlen(global_myname()) > 15) {
732 d_printf("Our netbios name can only be 15 chars long, \"%s\""
733 " is %d chars long\n",
734 global_myname(), strlen(global_myname()));
742 if (!secrets_init()) {
743 DEBUG(1,("Failed to initialise secrets database\n"));
747 tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
748 password = SMB_STRDUP(tmp_password);
750 if (!(ads = ads_startup())) {
755 d_fprintf(stderr, "realm must be set in in smb.conf for ADS join to succeed.\n");
760 if (strcmp(ads->config.realm, lp_realm()) != 0) {
761 d_fprintf(stderr, "realm of remote server (%s) and realm in smb.conf (%s) DO NOT match. Aborting join\n", ads->config.realm, lp_realm());
766 ou_str = ads_ou_string(ads,org_unit);
767 asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path);
770 rc = ads_search_dn(ads, &res, dn, NULL);
771 ads_msgfree(ads, res);
773 if (rc.error_type == ENUM_ADS_ERROR_LDAP && rc.err.rc == LDAP_NO_SUCH_OBJECT) {
774 d_fprintf(stderr, "ads_join_realm: organizational unit %s does not exist (dn:%s)\n",
781 if (!ADS_ERR_OK(rc)) {
782 d_fprintf(stderr, "ads_join_realm: %s\n", ads_errstr(rc));
787 rc = ads_join_realm(ads, global_myname(), account_type, org_unit);
788 if (!ADS_ERR_OK(rc)) {
789 d_fprintf(stderr, "ads_join_realm: %s\n", ads_errstr(rc));
794 rc = ads_domain_sid(ads, &dom_sid);
795 if (!ADS_ERR_OK(rc)) {
796 d_fprintf(stderr, "ads_domain_sid: %s\n", ads_errstr(rc));
801 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
802 d_fprintf(stderr, "asprintf failed\n");
807 rc = ads_set_machine_password(ads, machine_account, password);
808 if (!ADS_ERR_OK(rc)) {
809 d_fprintf(stderr, "ads_set_machine_password: %s\n", ads_errstr(rc));
814 /* make sure we get the right workgroup */
816 if ( !(ctx = talloc_init("net ads join")) ) {
817 d_fprintf(stderr, "talloc_init() failed!\n");
822 rc = ads_workgroup_name(ads, ctx, &short_domain_name);
823 if ( ADS_ERR_OK(rc) ) {
824 if ( !strequal(lp_workgroup(), short_domain_name) ) {
825 d_printf("The workgroup in smb.conf does not match the short\n");
826 d_printf("domain name obtained from the server.\n");
827 d_printf("Using the name [%s] from the server.\n", short_domain_name);
828 d_printf("You should set \"workgroup = %s\" in smb.conf.\n", short_domain_name);
831 short_domain_name = lp_workgroup();
834 d_printf("Using short domain name -- %s\n", short_domain_name);
836 /* HACK ALRET! Store the sid and password under bother the lp_workgroup()
837 value from smb.conf and the string returned from the server. The former is
838 neede to bootstrap winbindd's first connection to the DC to get the real
839 short domain name --jerry */
841 if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) {
842 DEBUG(1,("Failed to save domain sid\n"));
847 if (!secrets_store_machine_password(password, lp_workgroup(), sec_channel_type)) {
848 DEBUG(1,("Failed to save machine password\n"));
854 if (!kerberos_derive_salting_principal(machine_account)) {
855 DEBUG(1,("Failed to determine salting principal\n"));
860 if (!kerberos_derive_cifs_salting_principals()) {
861 DEBUG(1,("Failed to determine salting principals\n"));
867 if (!secrets_store_domain_sid(short_domain_name, &dom_sid)) {
868 DEBUG(1,("Failed to save domain sid\n"));
873 if (!secrets_store_machine_password(password, short_domain_name, sec_channel_type)) {
874 DEBUG(1,("Failed to save machine password\n"));
879 /* Now build the keytab, using the same ADS connection */
880 if (lp_use_kerberos_keytab() && ads_keytab_create_default(ads)) {
881 DEBUG(1,("Error creating host keytab!\n"));
884 d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm);
887 SAFE_FREE(machine_account);
895 int net_ads_printer_usage(int argc, const char **argv)
898 "\nnet ads printer search <printer>"
899 "\n\tsearch for a printer in the directory\n"
900 "\nnet ads printer info <printer> <server>"
901 "\n\tlookup info in directory for printer on server"
902 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
903 "\nnet ads printer publish <printername>"
904 "\n\tpublish printer in directory"
905 "\n\t(note: printer name is required)\n"
906 "\nnet ads printer remove <printername>"
907 "\n\tremove printer from directory"
908 "\n\t(note: printer name is required)\n");
912 static int net_ads_printer_search(int argc, const char **argv)
918 if (!(ads = ads_startup())) {
922 rc = ads_find_printers(ads, &res);
924 if (!ADS_ERR_OK(rc)) {
925 d_fprintf(stderr, "ads_find_printer: %s\n", ads_errstr(rc));
926 ads_msgfree(ads, res);
931 if (ads_count_replies(ads, res) == 0) {
932 d_fprintf(stderr, "No results found\n");
933 ads_msgfree(ads, res);
939 ads_msgfree(ads, res);
944 static int net_ads_printer_info(int argc, const char **argv)
948 const char *servername, *printername;
951 if (!(ads = ads_startup())) {
956 printername = argv[0];
962 servername = argv[1];
964 servername = global_myname();
967 rc = ads_find_printer_on_server(ads, &res, printername, servername);
969 if (!ADS_ERR_OK(rc)) {
970 d_fprintf(stderr, "ads_find_printer_on_server: %s\n", ads_errstr(rc));
971 ads_msgfree(ads, res);
976 if (ads_count_replies(ads, res) == 0) {
977 d_fprintf(stderr, "Printer '%s' not found\n", printername);
978 ads_msgfree(ads, res);
984 ads_msgfree(ads, res);
990 void do_drv_upgrade_printer(int msg_type, struct process_id src,
991 void *buf, size_t len)
996 static int net_ads_printer_publish(int argc, const char **argv)
1000 const char *servername, *printername;
1001 struct cli_state *cli;
1002 struct rpc_pipe_client *pipe_hnd;
1003 struct in_addr server_ip;
1005 TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
1006 ADS_MODLIST mods = ads_init_mods(mem_ctx);
1007 char *prt_dn, *srv_dn, **srv_cn;
1010 if (!(ads = ads_startup())) {
1015 return net_ads_printer_usage(argc, argv);
1018 printername = argv[0];
1021 servername = argv[1];
1023 servername = global_myname();
1026 /* Get printer data from SPOOLSS */
1028 resolve_name(servername, &server_ip, 0x20);
1030 nt_status = cli_full_connection(&cli, global_myname(), servername,
1033 opt_user_name, opt_workgroup,
1034 opt_password ? opt_password : "",
1035 CLI_FULL_CONNECTION_USE_KERBEROS,
1038 if (NT_STATUS_IS_ERR(nt_status)) {
1039 d_fprintf(stderr, "Unable to open a connnection to %s to obtain data "
1040 "for %s\n", servername, printername);
1045 /* Publish on AD server */
1047 ads_find_machine_acct(ads, &res, servername);
1049 if (ads_count_replies(ads, res) == 0) {
1050 d_fprintf(stderr, "Could not find machine account for server %s\n",
1056 srv_dn = ldap_get_dn(ads->ld, res);
1057 srv_cn = ldap_explode_dn(srv_dn, 1);
1059 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], printername, srv_dn);
1061 pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SPOOLSS, &nt_status);
1063 d_fprintf(stderr, "Unable to open a connnection to the spoolss pipe on %s\n",
1069 get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
1072 rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
1073 if (!ADS_ERR_OK(rc)) {
1074 d_fprintf(stderr, "ads_publish_printer: %s\n", ads_errstr(rc));
1079 d_printf("published printer\n");
1085 static int net_ads_printer_remove(int argc, const char **argv)
1089 const char *servername;
1093 if (!(ads = ads_startup())) {
1098 return net_ads_printer_usage(argc, argv);
1102 servername = argv[1];
1104 servername = global_myname();
1107 rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
1109 if (!ADS_ERR_OK(rc)) {
1110 d_fprintf(stderr, "ads_find_printer_on_server: %s\n", ads_errstr(rc));
1111 ads_msgfree(ads, res);
1116 if (ads_count_replies(ads, res) == 0) {
1117 d_fprintf(stderr, "Printer '%s' not found\n", argv[1]);
1118 ads_msgfree(ads, res);
1123 prt_dn = ads_get_dn(ads, res);
1124 ads_msgfree(ads, res);
1125 rc = ads_del_dn(ads, prt_dn);
1126 ads_memfree(ads, prt_dn);
1128 if (!ADS_ERR_OK(rc)) {
1129 d_fprintf(stderr, "ads_del_dn: %s\n", ads_errstr(rc));
1138 static int net_ads_printer(int argc, const char **argv)
1140 struct functable func[] = {
1141 {"SEARCH", net_ads_printer_search},
1142 {"INFO", net_ads_printer_info},
1143 {"PUBLISH", net_ads_printer_publish},
1144 {"REMOVE", net_ads_printer_remove},
1148 return net_run_function(argc, argv, func, net_ads_printer_usage);
1152 static int net_ads_password(int argc, const char **argv)
1155 const char *auth_principal = opt_user_name;
1156 const char *auth_password = opt_password;
1158 char *new_password = NULL;
1163 if (opt_user_name == NULL || opt_password == NULL) {
1164 d_fprintf(stderr, "You must supply an administrator username/password\n");
1169 d_fprintf(stderr, "ERROR: You must say which username to change password for\n");
1174 if (!strchr_m(user, '@')) {
1175 asprintf(&c, "%s@%s", argv[0], lp_realm());
1179 use_in_memory_ccache();
1180 c = strchr_m(auth_principal, '@');
1187 /* use the realm so we can eventually change passwords for users
1188 in realms other than default */
1189 if (!(ads = ads_init(realm, NULL, NULL))) {
1193 /* we don't actually need a full connect, but it's the easy way to
1194 fill in the KDC's addresss */
1197 if (!ads || !ads->config.realm) {
1198 d_fprintf(stderr, "Didn't find the kerberos server!\n");
1203 new_password = (char *)argv[1];
1205 asprintf(&prompt, "Enter new password for %s:", user);
1206 new_password = getpass(prompt);
1210 ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
1211 auth_password, user, new_password, ads->auth.time_offset);
1212 if (!ADS_ERR_OK(ret)) {
1213 d_fprintf(stderr, "Password change failed :-( ...\n");
1218 d_printf("Password change for %s completed.\n", user);
1224 int net_ads_changetrustpw(int argc, const char **argv)
1227 char *host_principal;
1231 if (!secrets_init()) {
1232 DEBUG(1,("Failed to initialise secrets database\n"));
1236 net_use_machine_password();
1238 use_in_memory_ccache();
1240 if (!(ads = ads_startup())) {
1244 fstrcpy(my_name, global_myname());
1245 strlower_m(my_name);
1246 asprintf(&host_principal, "%s@%s", my_name, ads->config.realm);
1247 d_printf("Changing password for principal: HOST/%s\n", host_principal);
1249 ret = ads_change_trust_account_password(ads, host_principal);
1251 if (!ADS_ERR_OK(ret)) {
1252 d_fprintf(stderr, "Password change failed :-( ...\n");
1254 SAFE_FREE(host_principal);
1258 d_printf("Password change for principal HOST/%s succeeded.\n", host_principal);
1260 if (lp_use_kerberos_keytab()) {
1261 d_printf("Attempting to update system keytab with new password.\n");
1262 if (ads_keytab_create_default(ads)) {
1263 d_printf("Failed to update system keytab.\n");
1268 SAFE_FREE(host_principal);
1274 help for net ads search
1276 static int net_ads_search_usage(int argc, const char **argv)
1279 "\nnet ads search <expression> <attributes...>\n"\
1280 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
1281 "The expression is a standard LDAP search expression, and the\n"\
1282 "attributes are a list of LDAP fields to show in the results\n\n"\
1283 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
1285 net_common_flags_usage(argc, argv);
1291 general ADS search function. Useful in diagnosing problems in ADS
1293 static int net_ads_search(int argc, const char **argv)
1297 const char *ldap_exp;
1302 return net_ads_search_usage(argc, argv);
1305 if (!(ads = ads_startup())) {
1312 rc = ads_do_search_all(ads, ads->config.bind_path,
1314 ldap_exp, attrs, &res);
1315 if (!ADS_ERR_OK(rc)) {
1316 d_fprintf(stderr, "search failed: %s\n", ads_errstr(rc));
1321 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
1323 /* dump the results */
1326 ads_msgfree(ads, res);
1334 help for net ads search
1336 static int net_ads_dn_usage(int argc, const char **argv)
1339 "\nnet ads dn <dn> <attributes...>\n"\
1340 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
1341 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"\
1342 "to show in the results\n\n"\
1343 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
1345 net_common_flags_usage(argc, argv);
1351 general ADS search function. Useful in diagnosing problems in ADS
1353 static int net_ads_dn(int argc, const char **argv)
1362 return net_ads_dn_usage(argc, argv);
1365 if (!(ads = ads_startup())) {
1372 rc = ads_do_search_all(ads, dn,
1374 "(objectclass=*)", attrs, &res);
1375 if (!ADS_ERR_OK(rc)) {
1376 d_fprintf(stderr, "search failed: %s\n", ads_errstr(rc));
1381 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
1383 /* dump the results */
1386 ads_msgfree(ads, res);
1393 help for net ads sid search
1395 static int net_ads_sid_usage(int argc, const char **argv)
1398 "\nnet ads sid <sid> <attributes...>\n"\
1399 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
1400 "The SID is in string format, and the attributes are a list of LDAP fields \n"\
1401 "to show in the results\n\n"\
1402 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
1404 net_common_flags_usage(argc, argv);
1410 general ADS search function. Useful in diagnosing problems in ADS
1412 static int net_ads_sid(int argc, const char **argv)
1416 const char *sid_string;
1422 return net_ads_sid_usage(argc, argv);
1425 if (!(ads = ads_startup())) {
1429 sid_string = argv[0];
1432 if (!string_to_sid(&sid, sid_string)) {
1433 d_fprintf(stderr, "could not convert sid\n");
1438 rc = ads_search_retry_sid(ads, &res, &sid, attrs);
1439 if (!ADS_ERR_OK(rc)) {
1440 d_fprintf(stderr, "search failed: %s\n", ads_errstr(rc));
1445 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
1447 /* dump the results */
1450 ads_msgfree(ads, res);
1457 static int net_ads_keytab_usage(int argc, const char **argv)
1460 "net ads keytab <COMMAND>\n"\
1461 "<COMMAND> can be either:\n"\
1462 " CREATE Creates a fresh keytab\n"\
1463 " ADD Adds new service principal\n"\
1464 " FLUSH Flushes out all keytab entries\n"\
1465 " HELP Prints this help message\n"\
1466 "The ADD command will take arguments, the other commands\n"\
1467 "will not take any arguments. The arguments given to ADD\n"\
1468 "should be a list of principals to add. For example, \n"\
1469 " net ads keytab add srv1 srv2\n"\
1470 "will add principals for the services srv1 and srv2 to the\n"\
1471 "system's keytab.\n"\
1477 static int net_ads_keytab_flush(int argc, const char **argv)
1482 if (!(ads = ads_startup())) {
1485 ret = ads_keytab_flush(ads);
1490 static int net_ads_keytab_add(int argc, const char **argv)
1496 d_printf("Processing principals to add...\n");
1497 if (!(ads = ads_startup())) {
1500 for (i = 0; i < argc; i++) {
1501 ret |= ads_keytab_add_entry(ads, argv[i]);
1507 static int net_ads_keytab_create(int argc, const char **argv)
1512 if (!(ads = ads_startup())) {
1515 ret = ads_keytab_create_default(ads);
1520 int net_ads_keytab(int argc, const char **argv)
1522 struct functable func[] = {
1523 {"CREATE", net_ads_keytab_create},
1524 {"ADD", net_ads_keytab_add},
1525 {"FLUSH", net_ads_keytab_flush},
1526 {"HELP", net_ads_keytab_usage},
1530 if (!lp_use_kerberos_keytab()) {
1531 d_printf("\nWarning: \"use kerberos keytab\" must be set to \"true\" in order to \
1532 use keytab functions.\n");
1535 return net_run_function(argc, argv, func, net_ads_keytab_usage);
1538 int net_ads_help(int argc, const char **argv)
1540 struct functable func[] = {
1541 {"USER", net_ads_user_usage},
1542 {"GROUP", net_ads_group_usage},
1543 {"PRINTER", net_ads_printer_usage},
1544 {"SEARCH", net_ads_search_usage},
1546 {"INFO", net_ads_info},
1547 {"JOIN", net_ads_join},
1548 {"LEAVE", net_ads_leave},
1549 {"STATUS", net_ads_status},
1550 {"PASSWORD", net_ads_password},
1551 {"CHANGETRUSTPW", net_ads_changetrustpw},
1556 return net_run_function(argc, argv, func, net_ads_usage);
1559 int net_ads(int argc, const char **argv)
1561 struct functable func[] = {
1562 {"INFO", net_ads_info},
1563 {"JOIN", net_ads_join},
1564 {"TESTJOIN", net_ads_testjoin},
1565 {"LEAVE", net_ads_leave},
1566 {"STATUS", net_ads_status},
1567 {"USER", net_ads_user},
1568 {"GROUP", net_ads_group},
1569 {"PASSWORD", net_ads_password},
1570 {"CHANGETRUSTPW", net_ads_changetrustpw},
1571 {"PRINTER", net_ads_printer},
1572 {"SEARCH", net_ads_search},
1574 {"SID", net_ads_sid},
1575 {"WORKGROUP", net_ads_workgroup},
1576 {"LOOKUP", net_ads_lookup},
1577 {"KEYTAB", net_ads_keytab},
1578 {"HELP", net_ads_help},
1582 return net_run_function(argc, argv, func, net_ads_usage);
1587 static int net_ads_noads(void)
1589 d_fprintf(stderr, "ADS support not compiled in\n");
1593 int net_ads_keytab(int argc, const char **argv)
1595 return net_ads_noads();
1598 int net_ads_usage(int argc, const char **argv)
1600 return net_ads_noads();
1603 int net_ads_help(int argc, const char **argv)
1605 return net_ads_noads();
1608 int net_ads_changetrustpw(int argc, const char **argv)
1610 return net_ads_noads();
1613 int net_ads_join(int argc, const char **argv)
1615 return net_ads_noads();
1618 int net_ads_user(int argc, const char **argv)
1620 return net_ads_noads();
1623 int net_ads_group(int argc, const char **argv)
1625 return net_ads_noads();
1628 /* this one shouldn't display a message */
1629 int net_ads_check(void)
1634 int net_ads(int argc, const char **argv)
1636 return net_ads_usage(argc, argv);