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 = (char *) opt_target_workgroup;
88 return ads_cldap_netlogon(ads);
93 static int net_ads_info(int argc, const char **argv)
97 /* if netbios is disabled we have to default to the realm from smb.conf */
99 if ( lp_disable_netbios() && *lp_realm() )
100 ads = ads_init(lp_realm(), opt_target_workgroup, opt_host);
102 ads = ads_init(NULL, opt_target_workgroup, opt_host);
105 ads->auth.flags |= ADS_AUTH_NO_BIND;
110 if (!ads || !ads->config.realm) {
111 d_printf("Didn't find the ldap server!\n");
115 d_printf("LDAP server: %s\n", inet_ntoa(ads->ldap_ip));
116 d_printf("LDAP server name: %s\n", ads->config.ldap_server_name);
117 d_printf("Realm: %s\n", ads->config.realm);
118 d_printf("Bind Path: %s\n", ads->config.bind_path);
119 d_printf("LDAP port: %d\n", ads->ldap_port);
120 d_printf("Server time: %s\n", http_timestring(ads->config.current_time));
122 d_printf("KDC server: %s\n", ads->auth.kdc_server );
123 d_printf("Server time offset: %d\n", ads->auth.time_offset );
128 static void use_in_memory_ccache(void) {
129 /* Use in-memory credentials cache so we do not interfere with
130 * existing credentials */
131 setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
134 static ADS_STRUCT *ads_startup(void)
138 BOOL need_password = False;
139 BOOL second_time = False;
142 /* lp_realm() should be handled by a command line param,
143 However, the join requires that realm be set in smb.conf
144 and compares our realm with the remote server's so this is
145 ok until someone needs more flexibility */
147 ads = ads_init(lp_realm(), opt_target_workgroup, opt_host);
149 if (!opt_user_name) {
150 opt_user_name = "administrator";
153 if (opt_user_specified) {
154 need_password = True;
158 if (!opt_password && need_password && !opt_machine_pass) {
160 asprintf(&prompt,"%s's password: ", opt_user_name);
161 opt_password = getpass(prompt);
166 use_in_memory_ccache();
167 ads->auth.password = smb_xstrdup(opt_password);
170 ads->auth.user_name = smb_xstrdup(opt_user_name);
173 * If the username is of the form "name@realm",
174 * extract the realm and convert to upper case.
175 * This is only used to establish the connection.
177 if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
179 ads->auth.realm = smb_xstrdup(cp);
180 strupper_m(ads->auth.realm);
183 status = ads_connect(ads);
185 if (!ADS_ERR_OK(status)) {
186 if (!need_password && !second_time) {
187 need_password = True;
191 DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
200 Check to see if connection can be made via ads.
201 ads_startup() stores the password in opt_password if it needs to so
202 that rpc or rap can use it without re-prompting.
204 int net_ads_check(void)
216 determine the netbios workgroup name for a domain
218 static int net_ads_workgroup(int argc, const char **argv)
222 const char *workgroup;
224 if (!(ads = ads_startup())) return -1;
226 if (!(ctx = talloc_init("net_ads_workgroup"))) {
231 if (!ADS_ERR_OK(ads_workgroup_name(ads, ctx, &workgroup))) {
232 d_printf("Failed to find workgroup for realm '%s'\n",
239 d_printf("Workgroup: %s\n", workgroup);
248 static BOOL usergrp_display(char *field, void **values, void *data_area)
250 char **disp_fields = (char **) data_area;
252 if (!field) { /* must be end of record */
253 if (!strchr_m(disp_fields[0], '$')) {
255 d_printf("%-21.21s %s\n",
256 disp_fields[0], disp_fields[1]);
258 d_printf("%s\n", disp_fields[0]);
260 SAFE_FREE(disp_fields[0]);
261 SAFE_FREE(disp_fields[1]);
264 if (!values) /* must be new field, indicate string field */
266 if (StrCaseCmp(field, "sAMAccountName") == 0) {
267 disp_fields[0] = SMB_STRDUP((char *) values[0]);
269 if (StrCaseCmp(field, "description") == 0)
270 disp_fields[1] = SMB_STRDUP((char *) values[0]);
274 static int net_ads_user_usage(int argc, const char **argv)
276 return net_help_user(argc, argv);
279 static int ads_user_add(int argc, const char **argv)
287 if (argc < 1) return net_ads_user_usage(argc, argv);
289 if (!(ads = ads_startup())) {
293 status = ads_find_user_acct(ads, &res, argv[0]);
295 if (!ADS_ERR_OK(status)) {
296 d_printf("ads_user_add: %s\n", ads_errstr(status));
300 if (ads_count_replies(ads, res)) {
301 d_printf("ads_user_add: User %s already exists\n", argv[0]);
305 if (opt_container == NULL) {
306 opt_container = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS);
309 status = ads_add_user_acct(ads, argv[0], opt_container, opt_comment);
311 if (!ADS_ERR_OK(status)) {
312 d_printf("Could not add user %s: %s\n", argv[0],
317 /* if no password is to be set, we're done */
319 d_printf("User %s added\n", argv[0]);
324 /* try setting the password */
325 asprintf(&upn, "%s@%s", argv[0], ads->config.realm);
326 status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
327 ads->auth.time_offset);
329 if (ADS_ERR_OK(status)) {
330 d_printf("User %s added\n", argv[0]);
335 /* password didn't set, delete account */
336 d_printf("Could not add user %s. Error setting password %s\n",
337 argv[0], ads_errstr(status));
338 ads_msgfree(ads, res);
339 status=ads_find_user_acct(ads, &res, argv[0]);
340 if (ADS_ERR_OK(status)) {
341 userdn = ads_get_dn(ads, res);
342 ads_del_dn(ads, userdn);
343 ads_memfree(ads, userdn);
348 ads_msgfree(ads, res);
353 static int ads_user_info(int argc, const char **argv)
358 const char *attrs[] = {"memberOf", NULL};
359 char *searchstring=NULL;
361 char *escaped_user = escape_ldap_string_alloc(argv[0]);
364 return net_ads_user_usage(argc, argv);
367 if (!(ads = ads_startup())) {
372 d_printf("ads_user_info: failed to escape user %s\n", argv[0]);
377 asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user);
378 rc = ads_search(ads, &res, searchstring, attrs);
379 safe_free(searchstring);
381 if (!ADS_ERR_OK(rc)) {
382 d_printf("ads_search: %s\n", ads_errstr(rc));
387 grouplist = ldap_get_values(ads->ld, res, "memberOf");
392 for (i=0;grouplist[i];i++) {
393 groupname = ldap_explode_dn(grouplist[i], 1);
394 d_printf("%s\n", groupname[0]);
395 ldap_value_free(groupname);
397 ldap_value_free(grouplist);
400 ads_msgfree(ads, res);
405 static int ads_user_delete(int argc, const char **argv)
413 return net_ads_user_usage(argc, argv);
416 if (!(ads = ads_startup())) {
420 rc = ads_find_user_acct(ads, &res, argv[0]);
421 if (!ADS_ERR_OK(rc)) {
422 DEBUG(0, ("User %s does not exist\n", argv[0]));
426 userdn = ads_get_dn(ads, res);
427 ads_msgfree(ads, res);
428 rc = ads_del_dn(ads, userdn);
429 ads_memfree(ads, userdn);
430 if (!ADS_ERR_OK(rc)) {
431 d_printf("User %s deleted\n", argv[0]);
435 d_printf("Error deleting user %s: %s\n", argv[0],
441 int net_ads_user(int argc, const char **argv)
443 struct functable func[] = {
444 {"ADD", ads_user_add},
445 {"INFO", ads_user_info},
446 {"DELETE", ads_user_delete},
451 const char *shortattrs[] = {"sAMAccountName", NULL};
452 const char *longattrs[] = {"sAMAccountName", "description", NULL};
453 char *disp_fields[2] = {NULL, NULL};
456 if (!(ads = ads_startup())) {
460 if (opt_long_list_entries)
461 d_printf("\nUser name Comment"\
462 "\n-----------------------------\n");
464 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
466 "(objectclass=user)",
467 opt_long_list_entries ? longattrs :
468 shortattrs, usergrp_display,
474 return net_run_function(argc, argv, func, net_ads_user_usage);
477 static int net_ads_group_usage(int argc, const char **argv)
479 return net_help_group(argc, argv);
482 static int ads_group_add(int argc, const char **argv)
490 return net_ads_group_usage(argc, argv);
493 if (!(ads = ads_startup())) {
497 status = ads_find_user_acct(ads, &res, argv[0]);
499 if (!ADS_ERR_OK(status)) {
500 d_printf("ads_group_add: %s\n", ads_errstr(status));
504 if (ads_count_replies(ads, res)) {
505 d_printf("ads_group_add: Group %s already exists\n", argv[0]);
506 ads_msgfree(ads, res);
510 if (opt_container == NULL) {
511 opt_container = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS);
514 status = ads_add_group_acct(ads, argv[0], opt_container, opt_comment);
516 if (ADS_ERR_OK(status)) {
517 d_printf("Group %s added\n", argv[0]);
520 d_printf("Could not add group %s: %s\n", argv[0],
526 ads_msgfree(ads, res);
531 static int ads_group_delete(int argc, const char **argv)
539 return net_ads_group_usage(argc, argv);
542 if (!(ads = ads_startup())) {
546 rc = ads_find_user_acct(ads, &res, argv[0]);
547 if (!ADS_ERR_OK(rc)) {
548 DEBUG(0, ("Group %s does not exist\n", argv[0]));
552 groupdn = ads_get_dn(ads, res);
553 ads_msgfree(ads, res);
554 rc = ads_del_dn(ads, groupdn);
555 ads_memfree(ads, groupdn);
556 if (!ADS_ERR_OK(rc)) {
557 d_printf("Group %s deleted\n", argv[0]);
561 d_printf("Error deleting group %s: %s\n", argv[0],
567 int net_ads_group(int argc, const char **argv)
569 struct functable func[] = {
570 {"ADD", ads_group_add},
571 {"DELETE", ads_group_delete},
576 const char *shortattrs[] = {"sAMAccountName", NULL};
577 const char *longattrs[] = {"sAMAccountName", "description", NULL};
578 char *disp_fields[2] = {NULL, NULL};
581 if (!(ads = ads_startup())) {
585 if (opt_long_list_entries)
586 d_printf("\nGroup name Comment"\
587 "\n-----------------------------\n");
588 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
590 "(objectclass=group)",
591 opt_long_list_entries ? longattrs :
592 shortattrs, usergrp_display,
598 return net_run_function(argc, argv, func, net_ads_group_usage);
601 static int net_ads_status(int argc, const char **argv)
607 if (!(ads = ads_startup())) {
611 rc = ads_find_machine_acct(ads, &res, global_myname());
612 if (!ADS_ERR_OK(rc)) {
613 d_printf("ads_find_machine_acct: %s\n", ads_errstr(rc));
618 if (ads_count_replies(ads, res) == 0) {
619 d_printf("No machine account for '%s' found\n", global_myname());
629 static int net_ads_leave(int argc, const char **argv)
631 ADS_STRUCT *ads = NULL;
634 if (!secrets_init()) {
635 DEBUG(1,("Failed to initialise secrets database\n"));
640 net_use_machine_password();
643 if (!(ads = ads_startup())) {
647 rc = ads_leave_realm(ads, global_myname());
648 if (!ADS_ERR_OK(rc)) {
649 d_printf("Failed to delete host '%s' from the '%s' realm.\n",
650 global_myname(), ads->config.realm);
655 d_printf("Removed '%s' from realm '%s'\n", global_myname(), ads->config.realm);
660 static int net_ads_join_ok(void)
662 ADS_STRUCT *ads = NULL;
664 if (!secrets_init()) {
665 DEBUG(1,("Failed to initialise secrets database\n"));
669 net_use_machine_password();
671 if (!(ads = ads_startup())) {
680 check that an existing join is OK
682 int net_ads_testjoin(int argc, const char **argv)
684 use_in_memory_ccache();
686 /* Display success or failure */
687 if (net_ads_join_ok() != 0) {
688 fprintf(stderr,"Join to domain is not valid\n");
692 printf("Join is OK\n");
697 join a domain using ADS
699 int net_ads_join(int argc, const char **argv)
704 char *machine_account = NULL;
706 const char *org_unit = NULL;
711 uint32 sec_channel_type = SEC_CHAN_WKSTA;
712 uint32 account_type = UF_WORKSTATION_TRUST_ACCOUNT;
713 const char *short_domain_name = NULL;
714 TALLOC_CTX *ctx = NULL;
720 if (!secrets_init()) {
721 DEBUG(1,("Failed to initialise secrets database\n"));
725 tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
726 password = SMB_STRDUP(tmp_password);
728 if (!(ads = ads_startup())) {
733 d_printf("realm must be set in in smb.conf for ADS join to succeed.\n");
738 if (strcmp(ads->config.realm, lp_realm()) != 0) {
739 d_printf("realm of remote server (%s) and realm in smb.conf (%s) DO NOT match. Aborting join\n", ads->config.realm, lp_realm());
744 ou_str = ads_ou_string(ads,org_unit);
745 asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path);
748 rc = ads_search_dn(ads, &res, dn, NULL);
749 ads_msgfree(ads, res);
751 if (rc.error_type == ENUM_ADS_ERROR_LDAP && rc.err.rc == LDAP_NO_SUCH_OBJECT) {
752 d_printf("ads_join_realm: organizational unit %s does not exist (dn:%s)\n",
759 if (!ADS_ERR_OK(rc)) {
760 d_printf("ads_join_realm: %s\n", ads_errstr(rc));
765 rc = ads_join_realm(ads, global_myname(), account_type, org_unit);
766 if (!ADS_ERR_OK(rc)) {
767 d_printf("ads_join_realm: %s\n", ads_errstr(rc));
772 rc = ads_domain_sid(ads, &dom_sid);
773 if (!ADS_ERR_OK(rc)) {
774 d_printf("ads_domain_sid: %s\n", ads_errstr(rc));
779 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
780 d_printf("asprintf failed\n");
785 rc = ads_set_machine_password(ads, machine_account, password);
786 if (!ADS_ERR_OK(rc)) {
787 d_printf("ads_set_machine_password: %s\n", ads_errstr(rc));
792 /* make sure we get the right workgroup */
794 if ( !(ctx = talloc_init("net ads join")) ) {
795 d_printf("talloc_init() failed!\n");
800 rc = ads_workgroup_name(ads, ctx, &short_domain_name);
801 if ( ADS_ERR_OK(rc) ) {
802 if ( !strequal(lp_workgroup(), short_domain_name) ) {
803 d_printf("The workgroup in smb.conf does not match the short\n");
804 d_printf("domain name obtained from the server.\n");
805 d_printf("Using the name [%s] from the server.\n", short_domain_name);
806 d_printf("You should set \"workgroup = %s\" in smb.conf.\n", short_domain_name);
809 short_domain_name = lp_workgroup();
812 d_printf("Using short domain name -- %s\n", short_domain_name);
814 /* HACK ALRET! Store the sid and password under bother the lp_workgroup()
815 value from smb.conf and the string returned from the server. The former is
816 neede to bootstrap winbindd's first connection to the DC to get the real
817 short domain name --jerry */
819 if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) {
820 DEBUG(1,("Failed to save domain sid\n"));
825 if (!secrets_store_machine_password(password, lp_workgroup(), sec_channel_type)) {
826 DEBUG(1,("Failed to save machine password\n"));
832 if (!kerberos_derive_salting_principal(machine_account)) {
833 DEBUG(1,("Failed to determine salting principal\n"));
838 if (!kerberos_derive_cifs_salting_principals()) {
839 DEBUG(1,("Failed to determine salting principals\n"));
845 if (!secrets_store_domain_sid(short_domain_name, &dom_sid)) {
846 DEBUG(1,("Failed to save domain sid\n"));
851 if (!secrets_store_machine_password(password, short_domain_name, sec_channel_type)) {
852 DEBUG(1,("Failed to save machine password\n"));
857 /* Now build the keytab, using the same ADS connection */
858 if (lp_use_kerberos_keytab() && ads_keytab_create_default(ads)) {
859 DEBUG(1,("Error creating host keytab!\n"));
862 d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm);
865 SAFE_FREE(machine_account);
873 int net_ads_printer_usage(int argc, const char **argv)
876 "\nnet ads printer search <printer>"
877 "\n\tsearch for a printer in the directory\n"
878 "\nnet ads printer info <printer> <server>"
879 "\n\tlookup info in directory for printer on server"
880 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
881 "\nnet ads printer publish <printername>"
882 "\n\tpublish printer in directory"
883 "\n\t(note: printer name is required)\n"
884 "\nnet ads printer remove <printername>"
885 "\n\tremove printer from directory"
886 "\n\t(note: printer name is required)\n");
890 static int net_ads_printer_search(int argc, const char **argv)
896 if (!(ads = ads_startup())) {
900 rc = ads_find_printers(ads, &res);
902 if (!ADS_ERR_OK(rc)) {
903 d_printf("ads_find_printer: %s\n", ads_errstr(rc));
904 ads_msgfree(ads, res);
909 if (ads_count_replies(ads, res) == 0) {
910 d_printf("No results found\n");
911 ads_msgfree(ads, res);
917 ads_msgfree(ads, res);
922 static int net_ads_printer_info(int argc, const char **argv)
926 const char *servername, *printername;
929 if (!(ads = ads_startup())) {
934 printername = argv[0];
940 servername = argv[1];
942 servername = global_myname();
945 rc = ads_find_printer_on_server(ads, &res, printername, servername);
947 if (!ADS_ERR_OK(rc)) {
948 d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc));
949 ads_msgfree(ads, res);
954 if (ads_count_replies(ads, res) == 0) {
955 d_printf("Printer '%s' not found\n", printername);
956 ads_msgfree(ads, res);
962 ads_msgfree(ads, res);
968 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
973 static int net_ads_printer_publish(int argc, const char **argv)
977 const char *servername, *printername;
978 struct cli_state *cli;
979 struct in_addr server_ip;
981 TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
982 ADS_MODLIST mods = ads_init_mods(mem_ctx);
983 char *prt_dn, *srv_dn, **srv_cn;
986 if (!(ads = ads_startup())) {
991 return net_ads_printer_usage(argc, argv);
994 printername = argv[0];
997 servername = argv[1];
999 servername = global_myname();
1002 /* Get printer data from SPOOLSS */
1004 resolve_name(servername, &server_ip, 0x20);
1006 nt_status = cli_full_connection(&cli, global_myname(), servername,
1009 opt_user_name, opt_workgroup,
1010 opt_password ? opt_password : "",
1011 CLI_FULL_CONNECTION_USE_KERBEROS,
1014 if (NT_STATUS_IS_ERR(nt_status)) {
1015 d_printf("Unable to open a connnection to %s to obtain data "
1016 "for %s\n", servername, printername);
1021 /* Publish on AD server */
1023 ads_find_machine_acct(ads, &res, servername);
1025 if (ads_count_replies(ads, res) == 0) {
1026 d_printf("Could not find machine account for server %s\n",
1032 srv_dn = ldap_get_dn(ads->ld, res);
1033 srv_cn = ldap_explode_dn(srv_dn, 1);
1035 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], printername, srv_dn);
1037 cli_nt_session_open(cli, PI_SPOOLSS);
1038 get_remote_printer_publishing_data(cli, mem_ctx, &mods, printername);
1040 rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
1041 if (!ADS_ERR_OK(rc)) {
1042 d_printf("ads_publish_printer: %s\n", ads_errstr(rc));
1047 d_printf("published printer\n");
1053 static int net_ads_printer_remove(int argc, const char **argv)
1057 const char *servername;
1061 if (!(ads = ads_startup())) {
1066 return net_ads_printer_usage(argc, argv);
1070 servername = argv[1];
1072 servername = global_myname();
1075 rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
1077 if (!ADS_ERR_OK(rc)) {
1078 d_printf("ads_find_printer_on_server: %s\n", ads_errstr(rc));
1079 ads_msgfree(ads, res);
1084 if (ads_count_replies(ads, res) == 0) {
1085 d_printf("Printer '%s' not found\n", argv[1]);
1086 ads_msgfree(ads, res);
1091 prt_dn = ads_get_dn(ads, res);
1092 ads_msgfree(ads, res);
1093 rc = ads_del_dn(ads, prt_dn);
1094 ads_memfree(ads, prt_dn);
1096 if (!ADS_ERR_OK(rc)) {
1097 d_printf("ads_del_dn: %s\n", ads_errstr(rc));
1106 static int net_ads_printer(int argc, const char **argv)
1108 struct functable func[] = {
1109 {"SEARCH", net_ads_printer_search},
1110 {"INFO", net_ads_printer_info},
1111 {"PUBLISH", net_ads_printer_publish},
1112 {"REMOVE", net_ads_printer_remove},
1116 return net_run_function(argc, argv, func, net_ads_printer_usage);
1120 static int net_ads_password(int argc, const char **argv)
1123 const char *auth_principal = opt_user_name;
1124 const char *auth_password = opt_password;
1126 char *new_password = NULL;
1131 if (opt_user_name == NULL || opt_password == NULL) {
1132 d_printf("You must supply an administrator username/password\n");
1137 d_printf("ERROR: You must say which username to change password for\n");
1142 if (!strchr_m(user, '@')) {
1143 asprintf(&c, "%s@%s", argv[0], lp_realm());
1147 use_in_memory_ccache();
1148 c = strchr_m(auth_principal, '@');
1155 /* use the realm so we can eventually change passwords for users
1156 in realms other than default */
1157 if (!(ads = ads_init(realm, NULL, NULL))) {
1161 /* we don't actually need a full connect, but it's the easy way to
1162 fill in the KDC's addresss */
1165 if (!ads || !ads->config.realm) {
1166 d_printf("Didn't find the kerberos server!\n");
1171 new_password = (char *)argv[1];
1173 asprintf(&prompt, "Enter new password for %s:", user);
1174 new_password = getpass(prompt);
1178 ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
1179 auth_password, user, new_password, ads->auth.time_offset);
1180 if (!ADS_ERR_OK(ret)) {
1181 d_printf("Password change failed :-( ...\n");
1186 d_printf("Password change for %s completed.\n", user);
1192 int net_ads_changetrustpw(int argc, const char **argv)
1195 char *host_principal;
1199 if (!secrets_init()) {
1200 DEBUG(1,("Failed to initialise secrets database\n"));
1204 net_use_machine_password();
1206 use_in_memory_ccache();
1208 if (!(ads = ads_startup())) {
1212 fstrcpy(my_name, global_myname());
1213 strlower_m(my_name);
1214 asprintf(&host_principal, "%s@%s", my_name, ads->config.realm);
1215 d_printf("Changing password for principal: HOST/%s\n", host_principal);
1217 ret = ads_change_trust_account_password(ads, host_principal);
1219 if (!ADS_ERR_OK(ret)) {
1220 d_printf("Password change failed :-( ...\n");
1222 SAFE_FREE(host_principal);
1226 d_printf("Password change for principal HOST/%s succeeded.\n", host_principal);
1228 if (lp_use_kerberos_keytab()) {
1229 d_printf("Attempting to update system keytab with new password.\n");
1230 if (ads_keytab_create_default(ads)) {
1231 d_printf("Failed to update system keytab.\n");
1236 SAFE_FREE(host_principal);
1242 help for net ads search
1244 static int net_ads_search_usage(int argc, const char **argv)
1247 "\nnet ads search <expression> <attributes...>\n"\
1248 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
1249 "The expression is a standard LDAP search expression, and the\n"\
1250 "attributes are a list of LDAP fields to show in the results\n\n"\
1251 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
1253 net_common_flags_usage(argc, argv);
1259 general ADS search function. Useful in diagnosing problems in ADS
1261 static int net_ads_search(int argc, const char **argv)
1265 const char *ldap_exp;
1270 return net_ads_search_usage(argc, argv);
1273 if (!(ads = ads_startup())) {
1280 rc = ads_do_search_all(ads, ads->config.bind_path,
1282 ldap_exp, attrs, &res);
1283 if (!ADS_ERR_OK(rc)) {
1284 d_printf("search failed: %s\n", ads_errstr(rc));
1289 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
1291 /* dump the results */
1294 ads_msgfree(ads, res);
1302 help for net ads search
1304 static int net_ads_dn_usage(int argc, const char **argv)
1307 "\nnet ads dn <dn> <attributes...>\n"\
1308 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
1309 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"\
1310 "to show in the results\n\n"\
1311 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
1313 net_common_flags_usage(argc, argv);
1319 general ADS search function. Useful in diagnosing problems in ADS
1321 static int net_ads_dn(int argc, const char **argv)
1330 return net_ads_dn_usage(argc, argv);
1333 if (!(ads = ads_startup())) {
1340 rc = ads_do_search_all(ads, dn,
1342 "(objectclass=*)", attrs, &res);
1343 if (!ADS_ERR_OK(rc)) {
1344 d_printf("search failed: %s\n", ads_errstr(rc));
1349 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
1351 /* dump the results */
1354 ads_msgfree(ads, res);
1360 static int net_ads_keytab_usage(int argc, const char **argv)
1363 "net ads keytab <COMMAND>\n"\
1364 "<COMMAND> can be either:\n"\
1365 " CREATE Creates a fresh keytab\n"\
1366 " ADD Adds new service principal\n"\
1367 " FLUSH Flushes out all keytab entries\n"\
1368 " HELP Prints this help message\n"\
1369 "The ADD command will take arguments, the other commands\n"\
1370 "will not take any arguments. The arguments given to ADD\n"\
1371 "should be a list of principals to add. For example, \n"\
1372 " net ads keytab add srv1 srv2\n"\
1373 "will add principals for the services srv1 and srv2 to the\n"\
1374 "system's keytab.\n"\
1380 static int net_ads_keytab_flush(int argc, const char **argv)
1385 if (!(ads = ads_startup())) {
1388 ret = ads_keytab_flush(ads);
1393 static int net_ads_keytab_add(int argc, const char **argv)
1399 d_printf("Processing principals to add...\n");
1400 if (!(ads = ads_startup())) {
1403 for (i = 0; i < argc; i++) {
1404 ret |= ads_keytab_add_entry(ads, argv[i]);
1410 static int net_ads_keytab_create(int argc, const char **argv)
1415 if (!(ads = ads_startup())) {
1418 ret = ads_keytab_create_default(ads);
1423 int net_ads_keytab(int argc, const char **argv)
1425 struct functable func[] = {
1426 {"CREATE", net_ads_keytab_create},
1427 {"ADD", net_ads_keytab_add},
1428 {"FLUSH", net_ads_keytab_flush},
1429 {"HELP", net_ads_keytab_usage},
1433 if (!lp_use_kerberos_keytab()) {
1434 d_printf("\nWarning: \"use kerberos keytab\" must be set to \"true\" in order to \
1435 use keytab functions.\n");
1438 return net_run_function(argc, argv, func, net_ads_keytab_usage);
1441 int net_ads_help(int argc, const char **argv)
1443 struct functable func[] = {
1444 {"USER", net_ads_user_usage},
1445 {"GROUP", net_ads_group_usage},
1446 {"PRINTER", net_ads_printer_usage},
1447 {"SEARCH", net_ads_search_usage},
1449 {"INFO", net_ads_info},
1450 {"JOIN", net_ads_join},
1451 {"LEAVE", net_ads_leave},
1452 {"STATUS", net_ads_status},
1453 {"PASSWORD", net_ads_password},
1454 {"CHANGETRUSTPW", net_ads_changetrustpw},
1459 return net_run_function(argc, argv, func, net_ads_usage);
1462 int net_ads(int argc, const char **argv)
1464 struct functable func[] = {
1465 {"INFO", net_ads_info},
1466 {"JOIN", net_ads_join},
1467 {"TESTJOIN", net_ads_testjoin},
1468 {"LEAVE", net_ads_leave},
1469 {"STATUS", net_ads_status},
1470 {"USER", net_ads_user},
1471 {"GROUP", net_ads_group},
1472 {"PASSWORD", net_ads_password},
1473 {"CHANGETRUSTPW", net_ads_changetrustpw},
1474 {"PRINTER", net_ads_printer},
1475 {"SEARCH", net_ads_search},
1477 {"WORKGROUP", net_ads_workgroup},
1478 {"LOOKUP", net_ads_lookup},
1479 {"KEYTAB", net_ads_keytab},
1480 {"HELP", net_ads_help},
1484 return net_run_function(argc, argv, func, net_ads_usage);
1489 static int net_ads_noads(void)
1491 d_printf("ADS support not compiled in\n");
1495 int net_ads_keytab(int argc, const char **argv)
1497 return net_ads_noads();
1500 int net_ads_usage(int argc, const char **argv)
1502 return net_ads_noads();
1505 int net_ads_help(int argc, const char **argv)
1507 return net_ads_noads();
1510 int net_ads_changetrustpw(int argc, const char **argv)
1512 return net_ads_noads();
1515 int net_ads_join(int argc, const char **argv)
1517 return net_ads_noads();
1520 int net_ads_user(int argc, const char **argv)
1522 return net_ads_noads();
1525 int net_ads_group(int argc, const char **argv)
1527 return net_ads_noads();
1530 /* this one shouldn't display a message */
1531 int net_ads_check(void)
1536 int net_ads(int argc, const char **argv)
1538 return net_ads_usage(argc, argv);