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\tcreates and updates the kerberos system keytab file\n"
66 this implements the CLDAP based netlogon lookup requests
67 for finding the domain controller of a ADS domain
69 static int net_ads_lookup(int argc
, const char **argv
)
73 ads
= ads_init(NULL
, opt_target_workgroup
, opt_host
);
75 ads
->auth
.flags
|= ADS_AUTH_NO_BIND
;
81 d_printf("Didn't find the cldap server!\n");
83 } if (!ads
->config
.realm
) {
84 ads
->config
.realm
= opt_target_workgroup
;
88 return ads_cldap_netlogon(ads
);
93 static int net_ads_info(int argc
, const char **argv
)
97 ads
= ads_init(NULL
, opt_target_workgroup
, opt_host
);
100 ads
->auth
.flags
|= ADS_AUTH_NO_BIND
;
105 if (!ads
|| !ads
->config
.realm
) {
106 d_printf("Didn't find the ldap server!\n");
110 d_printf("LDAP server: %s\n", inet_ntoa(ads
->ldap_ip
));
111 d_printf("LDAP server name: %s\n", ads
->config
.ldap_server_name
);
112 d_printf("Realm: %s\n", ads
->config
.realm
);
113 d_printf("Bind Path: %s\n", ads
->config
.bind_path
);
114 d_printf("LDAP port: %d\n", ads
->ldap_port
);
115 d_printf("Server time: %s\n", http_timestring(ads
->config
.current_time
));
117 d_printf("KDC server: %s\n", ads
->auth
.kdc_server
);
118 d_printf("Server time offset: %d\n", ads
->auth
.time_offset
);
123 static void use_in_memory_ccache(void) {
124 /* Use in-memory credentials cache so we do not interfere with
125 * existing credentials */
126 setenv(KRB5_ENV_CCNAME
, "MEMORY:net_ads", 1);
129 static ADS_STRUCT
*ads_startup(void)
133 BOOL need_password
= False
;
134 BOOL second_time
= False
;
137 /* lp_realm() should be handled by a command line param,
138 However, the join requires that realm be set in smb.conf
139 and compares our realm with the remote server's so this is
140 ok until someone needs more flexibility */
142 ads
= ads_init(lp_realm(), opt_target_workgroup
, opt_host
);
144 if (!opt_user_name
) {
145 opt_user_name
= "administrator";
148 if (opt_user_specified
) {
149 need_password
= True
;
153 if (!opt_password
&& need_password
&& !opt_machine_pass
) {
155 asprintf(&prompt
,"%s's password: ", opt_user_name
);
156 opt_password
= getpass(prompt
);
161 use_in_memory_ccache();
162 ads
->auth
.password
= smb_xstrdup(opt_password
);
165 ads
->auth
.user_name
= smb_xstrdup(opt_user_name
);
168 * If the username is of the form "name@realm",
169 * extract the realm and convert to upper case.
170 * This is only used to establish the connection.
172 if ((cp
= strchr(ads
->auth
.user_name
, '@'))!=0) {
174 ads
->auth
.realm
= smb_xstrdup(cp
);
175 strupper_m(ads
->auth
.realm
);
178 status
= ads_connect(ads
);
180 if (!ADS_ERR_OK(status
)) {
181 if (!need_password
&& !second_time
) {
182 need_password
= True
;
186 DEBUG(0,("ads_connect: %s\n", ads_errstr(status
)));
195 Check to see if connection can be made via ads.
196 ads_startup() stores the password in opt_password if it needs to so
197 that rpc or rap can use it without re-prompting.
199 int net_ads_check(void)
211 determine the netbios workgroup name for a domain
213 static int net_ads_workgroup(int argc
, const char **argv
)
217 const char *workgroup
;
219 if (!(ads
= ads_startup())) return -1;
221 if (!(ctx
= talloc_init("net_ads_workgroup"))) {
226 if (!ADS_ERR_OK(ads_workgroup_name(ads
, ctx
, &workgroup
))) {
227 d_printf("Failed to find workgroup for realm '%s'\n",
234 d_printf("Workgroup: %s\n", workgroup
);
243 static BOOL
usergrp_display(char *field
, void **values
, void *data_area
)
245 char **disp_fields
= (char **) data_area
;
247 if (!field
) { /* must be end of record */
248 if (!strchr_m(disp_fields
[0], '$')) {
250 d_printf("%-21.21s %s\n",
251 disp_fields
[0], disp_fields
[1]);
253 d_printf("%s\n", disp_fields
[0]);
255 SAFE_FREE(disp_fields
[0]);
256 SAFE_FREE(disp_fields
[1]);
259 if (!values
) /* must be new field, indicate string field */
261 if (StrCaseCmp(field
, "sAMAccountName") == 0) {
262 disp_fields
[0] = strdup((char *) values
[0]);
264 if (StrCaseCmp(field
, "description") == 0)
265 disp_fields
[1] = strdup((char *) values
[0]);
269 static int net_ads_user_usage(int argc
, const char **argv
)
271 return net_help_user(argc
, argv
);
274 static int ads_user_add(int argc
, const char **argv
)
282 if (argc
< 1) return net_ads_user_usage(argc
, argv
);
284 if (!(ads
= ads_startup())) {
288 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
290 if (!ADS_ERR_OK(status
)) {
291 d_printf("ads_user_add: %s\n", ads_errstr(status
));
295 if (ads_count_replies(ads
, res
)) {
296 d_printf("ads_user_add: User %s already exists\n", argv
[0]);
300 if (opt_container
== NULL
) {
301 opt_container
= ads_default_ou_string(ads
, WELL_KNOWN_GUID_USERS
);
304 status
= ads_add_user_acct(ads
, argv
[0], opt_container
, opt_comment
);
306 if (!ADS_ERR_OK(status
)) {
307 d_printf("Could not add user %s: %s\n", argv
[0],
312 /* if no password is to be set, we're done */
314 d_printf("User %s added\n", argv
[0]);
319 /* try setting the password */
320 asprintf(&upn
, "%s@%s", argv
[0], ads
->config
.realm
);
321 status
= ads_krb5_set_password(ads
->auth
.kdc_server
, upn
, argv
[1],
322 ads
->auth
.time_offset
);
324 if (ADS_ERR_OK(status
)) {
325 d_printf("User %s added\n", argv
[0]);
330 /* password didn't set, delete account */
331 d_printf("Could not add user %s. Error setting password %s\n",
332 argv
[0], ads_errstr(status
));
333 ads_msgfree(ads
, res
);
334 status
=ads_find_user_acct(ads
, &res
, argv
[0]);
335 if (ADS_ERR_OK(status
)) {
336 userdn
= ads_get_dn(ads
, res
);
337 ads_del_dn(ads
, userdn
);
338 ads_memfree(ads
, userdn
);
343 ads_msgfree(ads
, res
);
348 static int ads_user_info(int argc
, const char **argv
)
353 const char *attrs
[] = {"memberOf", NULL
};
354 char *searchstring
=NULL
;
356 char *escaped_user
= escape_ldap_string_alloc(argv
[0]);
359 return net_ads_user_usage(argc
, argv
);
362 if (!(ads
= ads_startup())) {
367 d_printf("ads_user_info: failed to escape user %s\n", argv
[0]);
372 asprintf(&searchstring
, "(sAMAccountName=%s)", escaped_user
);
373 rc
= ads_search(ads
, &res
, searchstring
, attrs
);
374 safe_free(searchstring
);
376 if (!ADS_ERR_OK(rc
)) {
377 d_printf("ads_search: %s\n", ads_errstr(rc
));
382 grouplist
= ldap_get_values(ads
->ld
, res
, "memberOf");
387 for (i
=0;grouplist
[i
];i
++) {
388 groupname
= ldap_explode_dn(grouplist
[i
], 1);
389 d_printf("%s\n", groupname
[0]);
390 ldap_value_free(groupname
);
392 ldap_value_free(grouplist
);
395 ads_msgfree(ads
, res
);
400 static int ads_user_delete(int argc
, const char **argv
)
408 return net_ads_user_usage(argc
, argv
);
411 if (!(ads
= ads_startup())) {
415 rc
= ads_find_user_acct(ads
, &res
, argv
[0]);
416 if (!ADS_ERR_OK(rc
)) {
417 DEBUG(0, ("User %s does not exist\n", argv
[0]));
421 userdn
= ads_get_dn(ads
, res
);
422 ads_msgfree(ads
, res
);
423 rc
= ads_del_dn(ads
, userdn
);
424 ads_memfree(ads
, userdn
);
425 if (!ADS_ERR_OK(rc
)) {
426 d_printf("User %s deleted\n", argv
[0]);
430 d_printf("Error deleting user %s: %s\n", argv
[0],
436 int net_ads_user(int argc
, const char **argv
)
438 struct functable func
[] = {
439 {"ADD", ads_user_add
},
440 {"INFO", ads_user_info
},
441 {"DELETE", ads_user_delete
},
446 const char *shortattrs
[] = {"sAMAccountName", NULL
};
447 const char *longattrs
[] = {"sAMAccountName", "description", NULL
};
448 char *disp_fields
[2] = {NULL
, NULL
};
451 if (!(ads
= ads_startup())) {
455 if (opt_long_list_entries
)
456 d_printf("\nUser name Comment"\
457 "\n-----------------------------\n");
459 rc
= ads_do_search_all_fn(ads
, ads
->config
.bind_path
,
461 "(objectclass=user)",
462 opt_long_list_entries
? longattrs
:
463 shortattrs
, usergrp_display
,
469 return net_run_function(argc
, argv
, func
, net_ads_user_usage
);
472 static int net_ads_group_usage(int argc
, const char **argv
)
474 return net_help_group(argc
, argv
);
477 static int ads_group_add(int argc
, const char **argv
)
485 return net_ads_group_usage(argc
, argv
);
488 if (!(ads
= ads_startup())) {
492 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
494 if (!ADS_ERR_OK(status
)) {
495 d_printf("ads_group_add: %s\n", ads_errstr(status
));
499 if (ads_count_replies(ads
, res
)) {
500 d_printf("ads_group_add: Group %s already exists\n", argv
[0]);
501 ads_msgfree(ads
, res
);
505 if (opt_container
== NULL
) {
506 opt_container
= ads_default_ou_string(ads
, WELL_KNOWN_GUID_USERS
);
509 status
= ads_add_group_acct(ads
, argv
[0], opt_container
, opt_comment
);
511 if (ADS_ERR_OK(status
)) {
512 d_printf("Group %s added\n", argv
[0]);
515 d_printf("Could not add group %s: %s\n", argv
[0],
521 ads_msgfree(ads
, res
);
526 static int ads_group_delete(int argc
, const char **argv
)
534 return net_ads_group_usage(argc
, argv
);
537 if (!(ads
= ads_startup())) {
541 rc
= ads_find_user_acct(ads
, &res
, argv
[0]);
542 if (!ADS_ERR_OK(rc
)) {
543 DEBUG(0, ("Group %s does not exist\n", argv
[0]));
547 groupdn
= ads_get_dn(ads
, res
);
548 ads_msgfree(ads
, res
);
549 rc
= ads_del_dn(ads
, groupdn
);
550 ads_memfree(ads
, groupdn
);
551 if (!ADS_ERR_OK(rc
)) {
552 d_printf("Group %s deleted\n", argv
[0]);
556 d_printf("Error deleting group %s: %s\n", argv
[0],
562 int net_ads_group(int argc
, const char **argv
)
564 struct functable func
[] = {
565 {"ADD", ads_group_add
},
566 {"DELETE", ads_group_delete
},
571 const char *shortattrs
[] = {"sAMAccountName", NULL
};
572 const char *longattrs
[] = {"sAMAccountName", "description", NULL
};
573 char *disp_fields
[2] = {NULL
, NULL
};
576 if (!(ads
= ads_startup())) {
580 if (opt_long_list_entries
)
581 d_printf("\nGroup name Comment"\
582 "\n-----------------------------\n");
583 rc
= ads_do_search_all_fn(ads
, ads
->config
.bind_path
,
585 "(objectclass=group)",
586 opt_long_list_entries
? longattrs
:
587 shortattrs
, usergrp_display
,
593 return net_run_function(argc
, argv
, func
, net_ads_group_usage
);
596 static int net_ads_status(int argc
, const char **argv
)
602 if (!(ads
= ads_startup())) {
606 rc
= ads_find_machine_acct(ads
, &res
, global_myname());
607 if (!ADS_ERR_OK(rc
)) {
608 d_printf("ads_find_machine_acct: %s\n", ads_errstr(rc
));
613 if (ads_count_replies(ads
, res
) == 0) {
614 d_printf("No machine account for '%s' found\n", global_myname());
624 static int net_ads_leave(int argc
, const char **argv
)
626 ADS_STRUCT
*ads
= NULL
;
629 if (!secrets_init()) {
630 DEBUG(1,("Failed to initialise secrets database\n"));
635 net_use_machine_password();
638 if (!(ads
= ads_startup())) {
642 rc
= ads_leave_realm(ads
, global_myname());
643 if (!ADS_ERR_OK(rc
)) {
644 d_printf("Failed to delete host '%s' from the '%s' realm.\n",
645 global_myname(), ads
->config
.realm
);
650 d_printf("Removed '%s' from realm '%s'\n", global_myname(), ads
->config
.realm
);
655 static int net_ads_join_ok(void)
657 ADS_STRUCT
*ads
= NULL
;
659 if (!secrets_init()) {
660 DEBUG(1,("Failed to initialise secrets database\n"));
664 net_use_machine_password();
666 if (!(ads
= ads_startup())) {
675 check that an existing join is OK
677 int net_ads_testjoin(int argc
, const char **argv
)
679 use_in_memory_ccache();
681 /* Display success or failure */
682 if (net_ads_join_ok() != 0) {
683 fprintf(stderr
,"Join to domain is not valid\n");
687 printf("Join is OK\n");
692 join a domain using ADS
694 int net_ads_join(int argc
, const char **argv
)
699 char *machine_account
= NULL
;
701 const char *org_unit
= NULL
;
706 uint32 sec_channel_type
= SEC_CHAN_WKSTA
;
707 uint32 account_type
= UF_WORKSTATION_TRUST_ACCOUNT
;
708 const char *short_domain_name
= NULL
;
709 TALLOC_CTX
*ctx
= NULL
;
715 if (!secrets_init()) {
716 DEBUG(1,("Failed to initialise secrets database\n"));
720 tmp_password
= generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH
);
721 password
= strdup(tmp_password
);
723 if (!(ads
= ads_startup())) {
728 d_printf("realm must be set in in smb.conf for ADS join to succeed.\n");
733 if (strcmp(ads
->config
.realm
, lp_realm()) != 0) {
734 d_printf("realm of remote server (%s) and realm in smb.conf (%s) DO NOT match. Aborting join\n", ads
->config
.realm
, lp_realm());
739 ou_str
= ads_ou_string(ads
,org_unit
);
740 asprintf(&dn
, "%s,%s", ou_str
, ads
->config
.bind_path
);
743 rc
= ads_search_dn(ads
, &res
, dn
, NULL
);
744 ads_msgfree(ads
, res
);
746 if (rc
.error_type
== ENUM_ADS_ERROR_LDAP
&& rc
.err
.rc
== LDAP_NO_SUCH_OBJECT
) {
747 d_printf("ads_join_realm: organizational unit %s does not exist (dn:%s)\n",
754 if (!ADS_ERR_OK(rc
)) {
755 d_printf("ads_join_realm: %s\n", ads_errstr(rc
));
760 rc
= ads_join_realm(ads
, global_myname(), account_type
, org_unit
);
761 if (!ADS_ERR_OK(rc
)) {
762 d_printf("ads_join_realm: %s\n", ads_errstr(rc
));
767 rc
= ads_domain_sid(ads
, &dom_sid
);
768 if (!ADS_ERR_OK(rc
)) {
769 d_printf("ads_domain_sid: %s\n", ads_errstr(rc
));
774 if (asprintf(&machine_account
, "%s$", global_myname()) == -1) {
775 d_printf("asprintf failed\n");
780 rc
= ads_set_machine_password(ads
, machine_account
, password
);
781 if (!ADS_ERR_OK(rc
)) {
782 d_printf("ads_set_machine_password: %s\n", ads_errstr(rc
));
787 /* make sure we get the right workgroup */
789 if ( !(ctx
= talloc_init("net ads join")) ) {
790 d_printf("talloc_init() failed!\n");
795 rc
= ads_workgroup_name(ads
, ctx
, &short_domain_name
);
796 if ( ADS_ERR_OK(rc
) ) {
797 if ( !strequal(lp_workgroup(), short_domain_name
) ) {
798 d_printf("The workgroup in smb.conf does not match the short\n");
799 d_printf("domain name obtained from the server.\n");
800 d_printf("Using the name [%s] from the server.\n", short_domain_name
);
801 d_printf("You should set \"workgroup = %s\" in smb.conf.\n", short_domain_name
);
804 short_domain_name
= lp_workgroup();
807 d_printf("Using short domain name -- %s\n", short_domain_name
);
809 /* HACK ALRET! Store the sid and password under bother the lp_workgroup()
810 value from smb.conf and the string returned from the server. The former is
811 neede to bootstrap winbindd's first connection to the DC to get the real
812 short domain name --jerry */
814 if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid
)) {
815 DEBUG(1,("Failed to save domain sid\n"));
820 if (!secrets_store_machine_password(password
, lp_workgroup(), sec_channel_type
)) {
821 DEBUG(1,("Failed to save machine password\n"));
826 if (!secrets_store_domain_sid(short_domain_name
, &dom_sid
)) {
827 DEBUG(1,("Failed to save domain sid\n"));
832 if (!secrets_store_machine_password(password
, short_domain_name
, sec_channel_type
)) {
833 DEBUG(1,("Failed to save machine password\n"));
838 /* Now build the keytab, using the same ADS connection */
839 if (lp_use_kerberos_keytab() && ads_keytab_create_default(ads
)) {
840 DEBUG(1,("Error creating host keytab!\n"));
843 d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads
->config
.realm
);
846 SAFE_FREE(machine_account
);
854 int net_ads_printer_usage(int argc
, const char **argv
)
857 "\nnet ads printer search <printer>"
858 "\n\tsearch for a printer in the directory\n"
859 "\nnet ads printer info <printer> <server>"
860 "\n\tlookup info in directory for printer on server"
861 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
862 "\nnet ads printer publish <printername>"
863 "\n\tpublish printer in directory"
864 "\n\t(note: printer name is required)\n"
865 "\nnet ads printer remove <printername>"
866 "\n\tremove printer from directory"
867 "\n\t(note: printer name is required)\n");
871 static int net_ads_printer_search(int argc
, const char **argv
)
877 if (!(ads
= ads_startup())) {
881 rc
= ads_find_printers(ads
, &res
);
883 if (!ADS_ERR_OK(rc
)) {
884 d_printf("ads_find_printer: %s\n", ads_errstr(rc
));
885 ads_msgfree(ads
, res
);
890 if (ads_count_replies(ads
, res
) == 0) {
891 d_printf("No results found\n");
892 ads_msgfree(ads
, res
);
898 ads_msgfree(ads
, res
);
903 static int net_ads_printer_info(int argc
, const char **argv
)
907 const char *servername
, *printername
;
910 if (!(ads
= ads_startup())) {
915 printername
= argv
[0];
921 servername
= argv
[1];
923 servername
= global_myname();
926 rc
= ads_find_printer_on_server(ads
, &res
, printername
, servername
);
928 if (!ADS_ERR_OK(rc
)) {
929 d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc
));
930 ads_msgfree(ads
, res
);
935 if (ads_count_replies(ads
, res
) == 0) {
936 d_printf("Printer '%s' not found\n", printername
);
937 ads_msgfree(ads
, res
);
943 ads_msgfree(ads
, res
);
949 void do_drv_upgrade_printer(int msg_type
, pid_t src
, void *buf
, size_t len
)
954 static int net_ads_printer_publish(int argc
, const char **argv
)
958 const char *servername
, *printername
;
959 struct cli_state
*cli
;
960 struct in_addr server_ip
;
962 TALLOC_CTX
*mem_ctx
= talloc_init("net_ads_printer_publish");
963 ADS_MODLIST mods
= ads_init_mods(mem_ctx
);
964 char *prt_dn
, *srv_dn
, **srv_cn
;
967 if (!(ads
= ads_startup())) {
972 return net_ads_printer_usage(argc
, argv
);
975 printername
= argv
[0];
978 servername
= argv
[1];
980 servername
= global_myname();
983 /* Get printer data from SPOOLSS */
985 resolve_name(servername
, &server_ip
, 0x20);
987 nt_status
= cli_full_connection(&cli
, global_myname(), servername
,
990 opt_user_name
, opt_workgroup
,
991 opt_password
? opt_password
: "",
992 CLI_FULL_CONNECTION_USE_KERBEROS
,
995 if (NT_STATUS_IS_ERR(nt_status
)) {
996 d_printf("Unable to open a connnection to %s to obtain data "
997 "for %s\n", servername
, printername
);
1002 /* Publish on AD server */
1004 ads_find_machine_acct(ads
, &res
, servername
);
1006 if (ads_count_replies(ads
, res
) == 0) {
1007 d_printf("Could not find machine account for server %s\n",
1013 srv_dn
= ldap_get_dn(ads
->ld
, res
);
1014 srv_cn
= ldap_explode_dn(srv_dn
, 1);
1016 asprintf(&prt_dn
, "cn=%s-%s,%s", srv_cn
[0], printername
, srv_dn
);
1018 cli_nt_session_open(cli
, PI_SPOOLSS
);
1019 get_remote_printer_publishing_data(cli
, mem_ctx
, &mods
, printername
);
1021 rc
= ads_add_printer_entry(ads
, prt_dn
, mem_ctx
, &mods
);
1022 if (!ADS_ERR_OK(rc
)) {
1023 d_printf("ads_publish_printer: %s\n", ads_errstr(rc
));
1028 d_printf("published printer\n");
1034 static int net_ads_printer_remove(int argc
, const char **argv
)
1038 const char *servername
;
1042 if (!(ads
= ads_startup())) {
1047 return net_ads_printer_usage(argc
, argv
);
1051 servername
= argv
[1];
1053 servername
= global_myname();
1056 rc
= ads_find_printer_on_server(ads
, &res
, argv
[0], servername
);
1058 if (!ADS_ERR_OK(rc
)) {
1059 d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc
));
1060 ads_msgfree(ads
, res
);
1065 if (ads_count_replies(ads
, res
) == 0) {
1066 d_printf("Printer '%s' not found\n", argv
[1]);
1067 ads_msgfree(ads
, res
);
1072 prt_dn
= ads_get_dn(ads
, res
);
1073 ads_msgfree(ads
, res
);
1074 rc
= ads_del_dn(ads
, prt_dn
);
1075 ads_memfree(ads
, prt_dn
);
1077 if (!ADS_ERR_OK(rc
)) {
1078 d_printf("ads_del_dn: %s\n", ads_errstr(rc
));
1087 static int net_ads_printer(int argc
, const char **argv
)
1089 struct functable func
[] = {
1090 {"SEARCH", net_ads_printer_search
},
1091 {"INFO", net_ads_printer_info
},
1092 {"PUBLISH", net_ads_printer_publish
},
1093 {"REMOVE", net_ads_printer_remove
},
1097 return net_run_function(argc
, argv
, func
, net_ads_printer_usage
);
1101 static int net_ads_password(int argc
, const char **argv
)
1104 const char *auth_principal
= opt_user_name
;
1105 const char *auth_password
= opt_password
;
1107 char *new_password
= NULL
;
1112 if (opt_user_name
== NULL
|| opt_password
== NULL
) {
1113 d_printf("You must supply an administrator username/password\n");
1118 d_printf("ERROR: You must say which username to change password for\n");
1123 if (!strchr_m(user
, '@')) {
1124 asprintf(&c
, "%s@%s", argv
[0], lp_realm());
1128 use_in_memory_ccache();
1129 c
= strchr(auth_principal
, '@');
1136 /* use the realm so we can eventually change passwords for users
1137 in realms other than default */
1138 if (!(ads
= ads_init(realm
, NULL
, NULL
))) {
1142 /* we don't actually need a full connect, but it's the easy way to
1143 fill in the KDC's addresss */
1146 if (!ads
|| !ads
->config
.realm
) {
1147 d_printf("Didn't find the kerberos server!\n");
1152 new_password
= (char *)argv
[1];
1154 asprintf(&prompt
, "Enter new password for %s:", user
);
1155 new_password
= getpass(prompt
);
1159 ret
= kerberos_set_password(ads
->auth
.kdc_server
, auth_principal
,
1160 auth_password
, user
, new_password
, ads
->auth
.time_offset
);
1161 if (!ADS_ERR_OK(ret
)) {
1162 d_printf("Password change failed :-( ...\n");
1167 d_printf("Password change for %s completed.\n", user
);
1173 int net_ads_changetrustpw(int argc
, const char **argv
)
1176 char *host_principal
;
1180 if (!secrets_init()) {
1181 DEBUG(1,("Failed to initialise secrets database\n"));
1185 net_use_machine_password();
1187 use_in_memory_ccache();
1189 if (!(ads
= ads_startup())) {
1193 fstrcpy(my_name
, global_myname());
1194 strlower_m(my_name
);
1195 asprintf(&host_principal
, "%s@%s", my_name
, ads
->config
.realm
);
1196 d_printf("Changing password for principal: HOST/%s\n", host_principal
);
1198 ret
= ads_change_trust_account_password(ads
, host_principal
);
1200 if (!ADS_ERR_OK(ret
)) {
1201 d_printf("Password change failed :-( ...\n");
1203 SAFE_FREE(host_principal
);
1207 d_printf("Password change for principal HOST/%s succeeded.\n", host_principal
);
1209 if (lp_use_kerberos_keytab()) {
1210 d_printf("Attempting to update system keytab with new password.\n");
1211 if (ads_keytab_create_default(ads
)) {
1212 d_printf("Failed to update system keytab.\n");
1217 SAFE_FREE(host_principal
);
1223 help for net ads search
1225 static int net_ads_search_usage(int argc
, const char **argv
)
1228 "\nnet ads search <expression> <attributes...>\n"\
1229 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
1230 "The expression is a standard LDAP search expression, and the\n"\
1231 "attributes are a list of LDAP fields to show in the results\n\n"\
1232 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
1234 net_common_flags_usage(argc
, argv
);
1240 general ADS search function. Useful in diagnosing problems in ADS
1242 static int net_ads_search(int argc
, const char **argv
)
1246 const char *ldap_exp
;
1251 return net_ads_search_usage(argc
, argv
);
1254 if (!(ads
= ads_startup())) {
1261 rc
= ads_do_search_all(ads
, ads
->config
.bind_path
,
1263 ldap_exp
, attrs
, &res
);
1264 if (!ADS_ERR_OK(rc
)) {
1265 d_printf("search failed: %s\n", ads_errstr(rc
));
1270 d_printf("Got %d replies\n\n", ads_count_replies(ads
, res
));
1272 /* dump the results */
1275 ads_msgfree(ads
, res
);
1283 help for net ads search
1285 static int net_ads_dn_usage(int argc
, const char **argv
)
1288 "\nnet ads dn <dn> <attributes...>\n"\
1289 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
1290 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"\
1291 "to show in the results\n\n"\
1292 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
1294 net_common_flags_usage(argc
, argv
);
1300 general ADS search function. Useful in diagnosing problems in ADS
1302 static int net_ads_dn(int argc
, const char **argv
)
1311 return net_ads_dn_usage(argc
, argv
);
1314 if (!(ads
= ads_startup())) {
1321 rc
= ads_do_search_all(ads
, dn
,
1323 "(objectclass=*)", attrs
, &res
);
1324 if (!ADS_ERR_OK(rc
)) {
1325 d_printf("search failed: %s\n", ads_errstr(rc
));
1330 d_printf("Got %d replies\n\n", ads_count_replies(ads
, res
));
1332 /* dump the results */
1335 ads_msgfree(ads
, res
);
1341 static int net_ads_keytab_usage(int argc
, const char **argv
)
1344 "net ads keytab <COMMAND>\n"\
1345 "<COMMAND> can be either:\n"\
1346 " CREATE Creates a fresh keytab\n"\
1347 " ADD Adds new service principal\n"\
1348 " FLUSH Flushes out all keytab entries\n"\
1349 " HELP Prints this help message\n"\
1350 "The ADD command will take arguments, the other commands\n"\
1351 "will not take any arguments. The arguments given to ADD\n"\
1352 "should be a list of principals to add. For example, \n"\
1353 " net ads keytab add srv1 srv2\n"\
1354 "will add principals for the services srv1 and srv2 to the\n"\
1355 "system's keytab.\n"\
1361 static int net_ads_keytab_flush(int argc
, const char **argv
)
1366 if (!(ads
= ads_startup())) {
1369 ret
= ads_keytab_flush(ads
);
1374 static int net_ads_keytab_add(int argc
, const char **argv
)
1380 d_printf("Processing principals to add...\n");
1381 if (!(ads
= ads_startup())) {
1384 for (i
= 0; i
< argc
; i
++) {
1385 ret
|= ads_keytab_add_entry(ads
, argv
[i
]);
1391 static int net_ads_keytab_create(int argc
, const char **argv
)
1396 if (!(ads
= ads_startup())) {
1399 ret
= ads_keytab_create_default(ads
);
1404 int net_ads_keytab(int argc
, const char **argv
)
1406 struct functable func
[] = {
1407 {"CREATE", net_ads_keytab_create
},
1408 {"ADD", net_ads_keytab_add
},
1409 {"FLUSH", net_ads_keytab_flush
},
1410 {"HELP", net_ads_keytab_usage
},
1414 if (!lp_use_kerberos_keytab()) {
1415 d_printf("\nWarning: \"use kerberos keytab\" must be set to \"true\" in order to \
1416 use keytab functions.\n");
1419 return net_run_function(argc
, argv
, func
, net_ads_keytab_usage
);
1422 int net_ads_help(int argc
, const char **argv
)
1424 struct functable func
[] = {
1425 {"USER", net_ads_user_usage
},
1426 {"GROUP", net_ads_group_usage
},
1427 {"PRINTER", net_ads_printer_usage
},
1428 {"SEARCH", net_ads_search_usage
},
1430 {"INFO", net_ads_info
},
1431 {"JOIN", net_ads_join
},
1432 {"LEAVE", net_ads_leave
},
1433 {"STATUS", net_ads_status
},
1434 {"PASSWORD", net_ads_password
},
1435 {"CHANGETRUSTPW", net_ads_changetrustpw
},
1440 return net_run_function(argc
, argv
, func
, net_ads_usage
);
1443 int net_ads(int argc
, const char **argv
)
1445 struct functable func
[] = {
1446 {"INFO", net_ads_info
},
1447 {"JOIN", net_ads_join
},
1448 {"TESTJOIN", net_ads_testjoin
},
1449 {"LEAVE", net_ads_leave
},
1450 {"STATUS", net_ads_status
},
1451 {"USER", net_ads_user
},
1452 {"GROUP", net_ads_group
},
1453 {"PASSWORD", net_ads_password
},
1454 {"CHANGETRUSTPW", net_ads_changetrustpw
},
1455 {"PRINTER", net_ads_printer
},
1456 {"SEARCH", net_ads_search
},
1458 {"WORKGROUP", net_ads_workgroup
},
1459 {"LOOKUP", net_ads_lookup
},
1460 {"KEYTAB", net_ads_keytab
},
1461 {"HELP", net_ads_help
},
1465 return net_run_function(argc
, argv
, func
, net_ads_usage
);
1470 static int net_ads_noads(void)
1472 d_printf("ADS support not compiled in\n");
1476 int net_ads_keytab(int argc
, const char **argv
)
1478 return net_ads_noads();
1481 int net_ads_usage(int argc
, const char **argv
)
1483 return net_ads_noads();
1486 int net_ads_help(int argc
, const char **argv
)
1488 return net_ads_noads();
1491 int net_ads_changetrustpw(int argc
, const char **argv
)
1493 return net_ads_noads();
1496 int net_ads_join(int argc
, const char **argv
)
1498 return net_ads_noads();
1501 int net_ads_user(int argc
, const char **argv
)
1503 return net_ads_noads();
1506 int net_ads_group(int argc
, const char **argv
)
1508 return net_ads_noads();
1511 /* this one shouldn't display a message */
1512 int net_ads_check(void)
1517 int net_ads(int argc
, const char **argv
)
1519 return net_ads_usage(argc
, argv
);