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_fprintf(stderr, "Didn't find the cldap server!\n");
83 } if (!ads->config.realm) {
84 ads->config.realm = CONST_DISCARD(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_fprintf(stderr, "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_fprintf(stderr, "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 (disp_fields[0]) {
254 if (!strchr_m(disp_fields[0], '$')) {
256 d_printf("%-21.21s %s\n",
257 disp_fields[0], disp_fields[1]);
259 d_printf("%s\n", disp_fields[0]);
262 SAFE_FREE(disp_fields[0]);
263 SAFE_FREE(disp_fields[1]);
266 if (!values) /* must be new field, indicate string field */
268 if (StrCaseCmp(field, "sAMAccountName") == 0) {
269 disp_fields[0] = SMB_STRDUP((char *) values[0]);
271 if (StrCaseCmp(field, "description") == 0)
272 disp_fields[1] = SMB_STRDUP((char *) values[0]);
276 static int net_ads_user_usage(int argc, const char **argv)
278 return net_help_user(argc, argv);
281 static int ads_user_add(int argc, const char **argv)
289 if (argc < 1) return net_ads_user_usage(argc, argv);
291 if (!(ads = ads_startup())) {
295 status = ads_find_user_acct(ads, &res, argv[0]);
297 if (!ADS_ERR_OK(status)) {
298 d_fprintf(stderr, "ads_user_add: %s\n", ads_errstr(status));
302 if (ads_count_replies(ads, res)) {
303 d_fprintf(stderr, "ads_user_add: User %s already exists\n", argv[0]);
307 if (opt_container == NULL) {
308 opt_container = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS);
311 status = ads_add_user_acct(ads, argv[0], opt_container, opt_comment);
313 if (!ADS_ERR_OK(status)) {
314 d_fprintf(stderr, "Could not add user %s: %s\n", argv[0],
319 /* if no password is to be set, we're done */
321 d_printf("User %s added\n", argv[0]);
326 /* try setting the password */
327 asprintf(&upn, "%s@%s", argv[0], ads->config.realm);
328 status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
329 ads->auth.time_offset);
331 if (ADS_ERR_OK(status)) {
332 d_printf("User %s added\n", argv[0]);
337 /* password didn't set, delete account */
338 d_fprintf(stderr, "Could not add user %s. Error setting password %s\n",
339 argv[0], ads_errstr(status));
340 ads_msgfree(ads, res);
341 status=ads_find_user_acct(ads, &res, argv[0]);
342 if (ADS_ERR_OK(status)) {
343 userdn = ads_get_dn(ads, res);
344 ads_del_dn(ads, userdn);
345 ads_memfree(ads, userdn);
350 ads_msgfree(ads, res);
355 static int ads_user_info(int argc, const char **argv)
360 const char *attrs[] = {"memberOf", NULL};
361 char *searchstring=NULL;
366 return net_ads_user_usage(argc, argv);
369 escaped_user = escape_ldap_string_alloc(argv[0]);
371 if (!(ads = ads_startup())) {
376 d_fprintf(stderr, "ads_user_info: failed to escape user %s\n", argv[0]);
381 asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user);
382 rc = ads_search(ads, &res, searchstring, attrs);
383 safe_free(searchstring);
385 if (!ADS_ERR_OK(rc)) {
386 d_fprintf(stderr, "ads_search: %s\n", ads_errstr(rc));
391 grouplist = ldap_get_values(ads->ld, res, "memberOf");
396 for (i=0;grouplist[i];i++) {
397 groupname = ldap_explode_dn(grouplist[i], 1);
398 d_printf("%s\n", groupname[0]);
399 ldap_value_free(groupname);
401 ldap_value_free(grouplist);
404 ads_msgfree(ads, res);
409 static int ads_user_delete(int argc, const char **argv)
417 return net_ads_user_usage(argc, argv);
420 if (!(ads = ads_startup())) {
424 rc = ads_find_user_acct(ads, &res, argv[0]);
425 if (!ADS_ERR_OK(rc)) {
426 DEBUG(0, ("User %s does not exist\n", argv[0]));
430 userdn = ads_get_dn(ads, res);
431 ads_msgfree(ads, res);
432 rc = ads_del_dn(ads, userdn);
433 ads_memfree(ads, userdn);
434 if (!ADS_ERR_OK(rc)) {
435 d_printf("User %s deleted\n", argv[0]);
439 d_fprintf(stderr, "Error deleting user %s: %s\n", argv[0],
445 int net_ads_user(int argc, const char **argv)
447 struct functable func[] = {
448 {"ADD", ads_user_add},
449 {"INFO", ads_user_info},
450 {"DELETE", ads_user_delete},
455 const char *shortattrs[] = {"sAMAccountName", NULL};
456 const char *longattrs[] = {"sAMAccountName", "description", NULL};
457 char *disp_fields[2] = {NULL, NULL};
460 if (!(ads = ads_startup())) {
464 if (opt_long_list_entries)
465 d_printf("\nUser name Comment"\
466 "\n-----------------------------\n");
468 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
470 "(objectclass=user)",
471 opt_long_list_entries ? longattrs :
472 shortattrs, usergrp_display,
478 return net_run_function(argc, argv, func, net_ads_user_usage);
481 static int net_ads_group_usage(int argc, const char **argv)
483 return net_help_group(argc, argv);
486 static int ads_group_add(int argc, const char **argv)
494 return net_ads_group_usage(argc, argv);
497 if (!(ads = ads_startup())) {
501 status = ads_find_user_acct(ads, &res, argv[0]);
503 if (!ADS_ERR_OK(status)) {
504 d_fprintf(stderr, "ads_group_add: %s\n", ads_errstr(status));
508 if (ads_count_replies(ads, res)) {
509 d_fprintf(stderr, "ads_group_add: Group %s already exists\n", argv[0]);
510 ads_msgfree(ads, res);
514 if (opt_container == NULL) {
515 opt_container = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS);
518 status = ads_add_group_acct(ads, argv[0], opt_container, opt_comment);
520 if (ADS_ERR_OK(status)) {
521 d_printf("Group %s added\n", argv[0]);
524 d_fprintf(stderr, "Could not add group %s: %s\n", argv[0],
530 ads_msgfree(ads, res);
535 static int ads_group_delete(int argc, const char **argv)
543 return net_ads_group_usage(argc, argv);
546 if (!(ads = ads_startup())) {
550 rc = ads_find_user_acct(ads, &res, argv[0]);
551 if (!ADS_ERR_OK(rc)) {
552 DEBUG(0, ("Group %s does not exist\n", argv[0]));
556 groupdn = ads_get_dn(ads, res);
557 ads_msgfree(ads, res);
558 rc = ads_del_dn(ads, groupdn);
559 ads_memfree(ads, groupdn);
560 if (!ADS_ERR_OK(rc)) {
561 d_printf("Group %s deleted\n", argv[0]);
565 d_fprintf(stderr, "Error deleting group %s: %s\n", argv[0],
571 int net_ads_group(int argc, const char **argv)
573 struct functable func[] = {
574 {"ADD", ads_group_add},
575 {"DELETE", ads_group_delete},
580 const char *shortattrs[] = {"sAMAccountName", NULL};
581 const char *longattrs[] = {"sAMAccountName", "description", NULL};
582 char *disp_fields[2] = {NULL, NULL};
585 if (!(ads = ads_startup())) {
589 if (opt_long_list_entries)
590 d_printf("\nGroup name Comment"\
591 "\n-----------------------------\n");
592 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
594 "(objectclass=group)",
595 opt_long_list_entries ? longattrs :
596 shortattrs, usergrp_display,
602 return net_run_function(argc, argv, func, net_ads_group_usage);
605 static int net_ads_status(int argc, const char **argv)
611 if (!(ads = ads_startup())) {
615 rc = ads_find_machine_acct(ads, &res, global_myname());
616 if (!ADS_ERR_OK(rc)) {
617 d_fprintf(stderr, "ads_find_machine_acct: %s\n", ads_errstr(rc));
622 if (ads_count_replies(ads, res) == 0) {
623 d_fprintf(stderr, "No machine account for '%s' found\n", global_myname());
633 static int net_ads_leave(int argc, const char **argv)
635 ADS_STRUCT *ads = NULL;
638 if (!secrets_init()) {
639 DEBUG(1,("Failed to initialise secrets database\n"));
644 net_use_machine_password();
647 if (!(ads = ads_startup())) {
651 rc = ads_leave_realm(ads, global_myname());
652 if (!ADS_ERR_OK(rc)) {
653 d_fprintf(stderr, "Failed to delete host '%s' from the '%s' realm.\n",
654 global_myname(), ads->config.realm);
659 d_printf("Removed '%s' from realm '%s'\n", global_myname(), ads->config.realm);
664 static int net_ads_join_ok(void)
666 ADS_STRUCT *ads = NULL;
668 if (!secrets_init()) {
669 DEBUG(1,("Failed to initialise secrets database\n"));
673 net_use_machine_password();
675 if (!(ads = ads_startup())) {
684 check that an existing join is OK
686 int net_ads_testjoin(int argc, const char **argv)
688 use_in_memory_ccache();
690 /* Display success or failure */
691 if (net_ads_join_ok() != 0) {
692 fprintf(stderr,"Join to domain is not valid\n");
696 printf("Join is OK\n");
701 join a domain using ADS
703 int net_ads_join(int argc, const char **argv)
708 char *machine_account = NULL;
710 const char *org_unit = NULL;
715 uint32 sec_channel_type = SEC_CHAN_WKSTA;
716 uint32 account_type = UF_WORKSTATION_TRUST_ACCOUNT;
717 const char *short_domain_name = NULL;
718 TALLOC_CTX *ctx = NULL;
724 if (!secrets_init()) {
725 DEBUG(1,("Failed to initialise secrets database\n"));
729 tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
730 password = SMB_STRDUP(tmp_password);
732 if (!(ads = ads_startup())) {
737 d_fprintf(stderr, "realm must be set in in smb.conf for ADS join to succeed.\n");
742 if (strcmp(ads->config.realm, lp_realm()) != 0) {
743 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());
748 ou_str = ads_ou_string(ads,org_unit);
749 asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path);
752 rc = ads_search_dn(ads, &res, dn, NULL);
753 ads_msgfree(ads, res);
755 if (rc.error_type == ENUM_ADS_ERROR_LDAP && rc.err.rc == LDAP_NO_SUCH_OBJECT) {
756 d_fprintf(stderr, "ads_join_realm: organizational unit %s does not exist (dn:%s)\n",
763 if (!ADS_ERR_OK(rc)) {
764 d_fprintf(stderr, "ads_join_realm: %s\n", ads_errstr(rc));
769 rc = ads_join_realm(ads, global_myname(), account_type, org_unit);
770 if (!ADS_ERR_OK(rc)) {
771 d_fprintf(stderr, "ads_join_realm: %s\n", ads_errstr(rc));
776 rc = ads_domain_sid(ads, &dom_sid);
777 if (!ADS_ERR_OK(rc)) {
778 d_fprintf(stderr, "ads_domain_sid: %s\n", ads_errstr(rc));
783 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
784 d_fprintf(stderr, "asprintf failed\n");
789 rc = ads_set_machine_password(ads, machine_account, password);
790 if (!ADS_ERR_OK(rc)) {
791 d_fprintf(stderr, "ads_set_machine_password: %s\n", ads_errstr(rc));
796 /* make sure we get the right workgroup */
798 if ( !(ctx = talloc_init("net ads join")) ) {
799 d_fprintf(stderr, "talloc_init() failed!\n");
804 rc = ads_workgroup_name(ads, ctx, &short_domain_name);
805 if ( ADS_ERR_OK(rc) ) {
806 if ( !strequal(lp_workgroup(), short_domain_name) ) {
807 d_printf("The workgroup in smb.conf does not match the short\n");
808 d_printf("domain name obtained from the server.\n");
809 d_printf("Using the name [%s] from the server.\n", short_domain_name);
810 d_printf("You should set \"workgroup = %s\" in smb.conf.\n", short_domain_name);
813 short_domain_name = lp_workgroup();
816 d_printf("Using short domain name -- %s\n", short_domain_name);
818 /* HACK ALRET! Store the sid and password under bother the lp_workgroup()
819 value from smb.conf and the string returned from the server. The former is
820 neede to bootstrap winbindd's first connection to the DC to get the real
821 short domain name --jerry */
823 if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) {
824 DEBUG(1,("Failed to save domain sid\n"));
829 if (!secrets_store_machine_password(password, lp_workgroup(), sec_channel_type)) {
830 DEBUG(1,("Failed to save machine password\n"));
836 if (!kerberos_derive_salting_principal(machine_account)) {
837 DEBUG(1,("Failed to determine salting principal\n"));
842 if (!kerberos_derive_cifs_salting_principals()) {
843 DEBUG(1,("Failed to determine salting principals\n"));
849 if (!secrets_store_domain_sid(short_domain_name, &dom_sid)) {
850 DEBUG(1,("Failed to save domain sid\n"));
855 if (!secrets_store_machine_password(password, short_domain_name, sec_channel_type)) {
856 DEBUG(1,("Failed to save machine password\n"));
861 /* Now build the keytab, using the same ADS connection */
862 if (lp_use_kerberos_keytab() && ads_keytab_create_default(ads)) {
863 DEBUG(1,("Error creating host keytab!\n"));
866 d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm);
869 SAFE_FREE(machine_account);
877 int net_ads_printer_usage(int argc, const char **argv)
880 "\nnet ads printer search <printer>"
881 "\n\tsearch for a printer in the directory\n"
882 "\nnet ads printer info <printer> <server>"
883 "\n\tlookup info in directory for printer on server"
884 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
885 "\nnet ads printer publish <printername>"
886 "\n\tpublish printer in directory"
887 "\n\t(note: printer name is required)\n"
888 "\nnet ads printer remove <printername>"
889 "\n\tremove printer from directory"
890 "\n\t(note: printer name is required)\n");
894 static int net_ads_printer_search(int argc, const char **argv)
900 if (!(ads = ads_startup())) {
904 rc = ads_find_printers(ads, &res);
906 if (!ADS_ERR_OK(rc)) {
907 d_fprintf(stderr, "ads_find_printer: %s\n", ads_errstr(rc));
908 ads_msgfree(ads, res);
913 if (ads_count_replies(ads, res) == 0) {
914 d_fprintf(stderr, "No results found\n");
915 ads_msgfree(ads, res);
921 ads_msgfree(ads, res);
926 static int net_ads_printer_info(int argc, const char **argv)
930 const char *servername, *printername;
933 if (!(ads = ads_startup())) {
938 printername = argv[0];
944 servername = argv[1];
946 servername = global_myname();
949 rc = ads_find_printer_on_server(ads, &res, printername, servername);
951 if (!ADS_ERR_OK(rc)) {
952 d_fprintf(stderr, "ads_find_printer_on_server: %s\n", ads_errstr(rc));
953 ads_msgfree(ads, res);
958 if (ads_count_replies(ads, res) == 0) {
959 d_fprintf(stderr, "Printer '%s' not found\n", printername);
960 ads_msgfree(ads, res);
966 ads_msgfree(ads, res);
972 void do_drv_upgrade_printer(int msg_type, struct process_id src,
973 void *buf, size_t len)
978 static int net_ads_printer_publish(int argc, const char **argv)
982 const char *servername, *printername;
983 struct cli_state *cli;
984 struct rpc_pipe_client *pipe_hnd;
985 struct in_addr server_ip;
987 TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
988 ADS_MODLIST mods = ads_init_mods(mem_ctx);
989 char *prt_dn, *srv_dn, **srv_cn;
992 if (!(ads = ads_startup())) {
997 return net_ads_printer_usage(argc, argv);
1000 printername = argv[0];
1003 servername = argv[1];
1005 servername = global_myname();
1008 /* Get printer data from SPOOLSS */
1010 resolve_name(servername, &server_ip, 0x20);
1012 nt_status = cli_full_connection(&cli, global_myname(), servername,
1015 opt_user_name, opt_workgroup,
1016 opt_password ? opt_password : "",
1017 CLI_FULL_CONNECTION_USE_KERBEROS,
1020 if (NT_STATUS_IS_ERR(nt_status)) {
1021 d_fprintf(stderr, "Unable to open a connnection to %s to obtain data "
1022 "for %s\n", servername, printername);
1027 /* Publish on AD server */
1029 ads_find_machine_acct(ads, &res, servername);
1031 if (ads_count_replies(ads, res) == 0) {
1032 d_fprintf(stderr, "Could not find machine account for server %s\n",
1038 srv_dn = ldap_get_dn(ads->ld, res);
1039 srv_cn = ldap_explode_dn(srv_dn, 1);
1041 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], printername, srv_dn);
1043 pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SPOOLSS, &nt_status);
1044 get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
1047 rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
1048 if (!ADS_ERR_OK(rc)) {
1049 d_fprintf(stderr, "ads_publish_printer: %s\n", ads_errstr(rc));
1054 d_printf("published printer\n");
1060 static int net_ads_printer_remove(int argc, const char **argv)
1064 const char *servername;
1068 if (!(ads = ads_startup())) {
1073 return net_ads_printer_usage(argc, argv);
1077 servername = argv[1];
1079 servername = global_myname();
1082 rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
1084 if (!ADS_ERR_OK(rc)) {
1085 d_fprintf(stderr, "ads_find_printer_on_server: %s\n", ads_errstr(rc));
1086 ads_msgfree(ads, res);
1091 if (ads_count_replies(ads, res) == 0) {
1092 d_fprintf(stderr, "Printer '%s' not found\n", argv[1]);
1093 ads_msgfree(ads, res);
1098 prt_dn = ads_get_dn(ads, res);
1099 ads_msgfree(ads, res);
1100 rc = ads_del_dn(ads, prt_dn);
1101 ads_memfree(ads, prt_dn);
1103 if (!ADS_ERR_OK(rc)) {
1104 d_fprintf(stderr, "ads_del_dn: %s\n", ads_errstr(rc));
1113 static int net_ads_printer(int argc, const char **argv)
1115 struct functable func[] = {
1116 {"SEARCH", net_ads_printer_search},
1117 {"INFO", net_ads_printer_info},
1118 {"PUBLISH", net_ads_printer_publish},
1119 {"REMOVE", net_ads_printer_remove},
1123 return net_run_function(argc, argv, func, net_ads_printer_usage);
1127 static int net_ads_password(int argc, const char **argv)
1130 const char *auth_principal = opt_user_name;
1131 const char *auth_password = opt_password;
1133 char *new_password = NULL;
1138 if (opt_user_name == NULL || opt_password == NULL) {
1139 d_fprintf(stderr, "You must supply an administrator username/password\n");
1144 d_fprintf(stderr, "ERROR: You must say which username to change password for\n");
1149 if (!strchr_m(user, '@')) {
1150 asprintf(&c, "%s@%s", argv[0], lp_realm());
1154 use_in_memory_ccache();
1155 c = strchr_m(auth_principal, '@');
1162 /* use the realm so we can eventually change passwords for users
1163 in realms other than default */
1164 if (!(ads = ads_init(realm, NULL, NULL))) {
1168 /* we don't actually need a full connect, but it's the easy way to
1169 fill in the KDC's addresss */
1172 if (!ads || !ads->config.realm) {
1173 d_fprintf(stderr, "Didn't find the kerberos server!\n");
1178 new_password = (char *)argv[1];
1180 asprintf(&prompt, "Enter new password for %s:", user);
1181 new_password = getpass(prompt);
1185 ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
1186 auth_password, user, new_password, ads->auth.time_offset);
1187 if (!ADS_ERR_OK(ret)) {
1188 d_fprintf(stderr, "Password change failed :-( ...\n");
1193 d_printf("Password change for %s completed.\n", user);
1199 int net_ads_changetrustpw(int argc, const char **argv)
1202 char *host_principal;
1206 if (!secrets_init()) {
1207 DEBUG(1,("Failed to initialise secrets database\n"));
1211 net_use_machine_password();
1213 use_in_memory_ccache();
1215 if (!(ads = ads_startup())) {
1219 fstrcpy(my_name, global_myname());
1220 strlower_m(my_name);
1221 asprintf(&host_principal, "%s@%s", my_name, ads->config.realm);
1222 d_printf("Changing password for principal: HOST/%s\n", host_principal);
1224 ret = ads_change_trust_account_password(ads, host_principal);
1226 if (!ADS_ERR_OK(ret)) {
1227 d_fprintf(stderr, "Password change failed :-( ...\n");
1229 SAFE_FREE(host_principal);
1233 d_printf("Password change for principal HOST/%s succeeded.\n", host_principal);
1235 if (lp_use_kerberos_keytab()) {
1236 d_printf("Attempting to update system keytab with new password.\n");
1237 if (ads_keytab_create_default(ads)) {
1238 d_printf("Failed to update system keytab.\n");
1243 SAFE_FREE(host_principal);
1249 help for net ads search
1251 static int net_ads_search_usage(int argc, const char **argv)
1254 "\nnet ads search <expression> <attributes...>\n"\
1255 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
1256 "The expression is a standard LDAP search expression, and the\n"\
1257 "attributes are a list of LDAP fields to show in the results\n\n"\
1258 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
1260 net_common_flags_usage(argc, argv);
1266 general ADS search function. Useful in diagnosing problems in ADS
1268 static int net_ads_search(int argc, const char **argv)
1272 const char *ldap_exp;
1277 return net_ads_search_usage(argc, argv);
1280 if (!(ads = ads_startup())) {
1287 rc = ads_do_search_all(ads, ads->config.bind_path,
1289 ldap_exp, attrs, &res);
1290 if (!ADS_ERR_OK(rc)) {
1291 d_fprintf(stderr, "search failed: %s\n", ads_errstr(rc));
1296 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
1298 /* dump the results */
1301 ads_msgfree(ads, res);
1309 help for net ads search
1311 static int net_ads_dn_usage(int argc, const char **argv)
1314 "\nnet ads dn <dn> <attributes...>\n"\
1315 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
1316 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"\
1317 "to show in the results\n\n"\
1318 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
1320 net_common_flags_usage(argc, argv);
1326 general ADS search function. Useful in diagnosing problems in ADS
1328 static int net_ads_dn(int argc, const char **argv)
1337 return net_ads_dn_usage(argc, argv);
1340 if (!(ads = ads_startup())) {
1347 rc = ads_do_search_all(ads, dn,
1349 "(objectclass=*)", attrs, &res);
1350 if (!ADS_ERR_OK(rc)) {
1351 d_fprintf(stderr, "search failed: %s\n", ads_errstr(rc));
1356 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
1358 /* dump the results */
1361 ads_msgfree(ads, res);
1367 static int net_ads_keytab_usage(int argc, const char **argv)
1370 "net ads keytab <COMMAND>\n"\
1371 "<COMMAND> can be either:\n"\
1372 " CREATE Creates a fresh keytab\n"\
1373 " ADD Adds new service principal\n"\
1374 " FLUSH Flushes out all keytab entries\n"\
1375 " HELP Prints this help message\n"\
1376 "The ADD command will take arguments, the other commands\n"\
1377 "will not take any arguments. The arguments given to ADD\n"\
1378 "should be a list of principals to add. For example, \n"\
1379 " net ads keytab add srv1 srv2\n"\
1380 "will add principals for the services srv1 and srv2 to the\n"\
1381 "system's keytab.\n"\
1387 static int net_ads_keytab_flush(int argc, const char **argv)
1392 if (!(ads = ads_startup())) {
1395 ret = ads_keytab_flush(ads);
1400 static int net_ads_keytab_add(int argc, const char **argv)
1406 d_printf("Processing principals to add...\n");
1407 if (!(ads = ads_startup())) {
1410 for (i = 0; i < argc; i++) {
1411 ret |= ads_keytab_add_entry(ads, argv[i]);
1417 static int net_ads_keytab_create(int argc, const char **argv)
1422 if (!(ads = ads_startup())) {
1425 ret = ads_keytab_create_default(ads);
1430 int net_ads_keytab(int argc, const char **argv)
1432 struct functable func[] = {
1433 {"CREATE", net_ads_keytab_create},
1434 {"ADD", net_ads_keytab_add},
1435 {"FLUSH", net_ads_keytab_flush},
1436 {"HELP", net_ads_keytab_usage},
1440 if (!lp_use_kerberos_keytab()) {
1441 d_printf("\nWarning: \"use kerberos keytab\" must be set to \"true\" in order to \
1442 use keytab functions.\n");
1445 return net_run_function(argc, argv, func, net_ads_keytab_usage);
1448 int net_ads_help(int argc, const char **argv)
1450 struct functable func[] = {
1451 {"USER", net_ads_user_usage},
1452 {"GROUP", net_ads_group_usage},
1453 {"PRINTER", net_ads_printer_usage},
1454 {"SEARCH", net_ads_search_usage},
1456 {"INFO", net_ads_info},
1457 {"JOIN", net_ads_join},
1458 {"LEAVE", net_ads_leave},
1459 {"STATUS", net_ads_status},
1460 {"PASSWORD", net_ads_password},
1461 {"CHANGETRUSTPW", net_ads_changetrustpw},
1466 return net_run_function(argc, argv, func, net_ads_usage);
1469 int net_ads(int argc, const char **argv)
1471 struct functable func[] = {
1472 {"INFO", net_ads_info},
1473 {"JOIN", net_ads_join},
1474 {"TESTJOIN", net_ads_testjoin},
1475 {"LEAVE", net_ads_leave},
1476 {"STATUS", net_ads_status},
1477 {"USER", net_ads_user},
1478 {"GROUP", net_ads_group},
1479 {"PASSWORD", net_ads_password},
1480 {"CHANGETRUSTPW", net_ads_changetrustpw},
1481 {"PRINTER", net_ads_printer},
1482 {"SEARCH", net_ads_search},
1484 {"WORKGROUP", net_ads_workgroup},
1485 {"LOOKUP", net_ads_lookup},
1486 {"KEYTAB", net_ads_keytab},
1487 {"HELP", net_ads_help},
1491 return net_run_function(argc, argv, func, net_ads_usage);
1496 static int net_ads_noads(void)
1498 d_fprintf(stderr, "ADS support not compiled in\n");
1502 int net_ads_keytab(int argc, const char **argv)
1504 return net_ads_noads();
1507 int net_ads_usage(int argc, const char **argv)
1509 return net_ads_noads();
1512 int net_ads_help(int argc, const char **argv)
1514 return net_ads_noads();
1517 int net_ads_changetrustpw(int argc, const char **argv)
1519 return net_ads_noads();
1522 int net_ads_join(int argc, const char **argv)
1524 return net_ads_noads();
1527 int net_ads_user(int argc, const char **argv)
1529 return net_ads_noads();
1532 int net_ads_group(int argc, const char **argv)
1534 return net_ads_noads();
1537 /* this one shouldn't display a message */
1538 int net_ads_check(void)
1543 int net_ads(int argc, const char **argv)
1545 return net_ads_usage(argc, argv);