r14507: Re-disable accidentially re-enabled paranoia check. This should make
[Samba/gebeck_regimport.git] / source / utils / net_ads.c
bloba55bc4fe5675018aee6e4af329ff03e49509ad6f
1 /*
2 Samba Unix/Linux SMB client library
3 net ads commands
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.
23 #include "includes.h"
24 #include "utils/net.h"
26 #ifdef HAVE_ADS
28 int net_ads_usage(int argc, const char **argv)
30 d_printf(
31 "\nnet ads join <org_unit>"\
32 "\n\tjoins the local machine to a ADS realm\n"\
33 "\nnet ads leave"\
34 "\n\tremoves the local machine from a ADS realm\n"\
35 "\nnet ads testjoin"\
36 "\n\ttests that an exiting join is OK\n"\
37 "\nnet ads user"\
38 "\n\tlist, add, or delete users in the realm\n"\
39 "\nnet ads group"\
40 "\n\tlist, add, or delete groups in the realm\n"\
41 "\nnet ads info"\
42 "\n\tshows some info on the server\n"\
43 "\nnet ads status"\
44 "\n\tdump the machine account details to stdout\n"
45 "\nnet ads lookup"\
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"\
54 "\nnet ads search"\
55 "\n\tperform a raw LDAP search and dump the results\n"
56 "\nnet ads dn"\
57 "\n\tperform a raw LDAP search and dump attributes of a particular DN\n"
58 "\nnet ads keytab"\
59 "\n\tcreates and updates the kerberos system keytab file\n"
61 return -1;
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)
71 ADS_STRUCT *ads;
73 ads = ads_init(NULL, opt_target_workgroup, opt_host);
74 if (ads) {
75 ads->auth.flags |= ADS_AUTH_NO_BIND;
78 ads_connect(ads);
80 if (!ads) {
81 d_fprintf(stderr, "Didn't find the cldap server!\n");
82 return -1;
83 } if (!ads->config.realm) {
84 ads->config.realm = CONST_DISCARD(char *, opt_target_workgroup);
85 ads->ldap_port = 389;
88 return ads_cldap_netlogon(ads);
93 static int net_ads_info(int argc, const char **argv)
95 ADS_STRUCT *ads;
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);
101 else
102 ads = ads_init(NULL, opt_target_workgroup, opt_host);
104 if (ads) {
105 ads->auth.flags |= ADS_AUTH_NO_BIND;
108 ads_connect(ads);
110 if (!ads || !ads->config.realm) {
111 d_fprintf(stderr, "Didn't find the ldap server!\n");
112 return -1;
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 );
125 return 0;
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)
136 ADS_STRUCT *ads;
137 ADS_STATUS status;
138 BOOL need_password = False;
139 BOOL second_time = False;
140 char *cp;
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;
157 retry:
158 if (!opt_password && need_password && !opt_machine_pass) {
159 char *prompt;
160 asprintf(&prompt,"%s's password: ", opt_user_name);
161 opt_password = getpass(prompt);
162 free(prompt);
165 if (opt_password) {
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) {
178 *cp++ = '\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;
188 second_time = True;
189 goto retry;
190 } else {
191 DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
192 return NULL;
195 return ads;
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)
206 ADS_STRUCT *ads;
208 ads = ads_startup();
209 if (!ads)
210 return -1;
211 ads_destroy(&ads);
212 return 0;
216 determine the netbios workgroup name for a domain
218 static int net_ads_workgroup(int argc, const char **argv)
220 ADS_STRUCT *ads;
221 TALLOC_CTX *ctx;
222 const char *workgroup;
224 if (!(ads = ads_startup())) return -1;
226 if (!(ctx = talloc_init("net_ads_workgroup"))) {
227 ads_destroy(&ads);
228 return -1;
231 if (!ADS_ERR_OK(ads_workgroup_name(ads, ctx, &workgroup))) {
232 d_fprintf(stderr, "Failed to find workgroup for realm '%s'\n",
233 ads->config.realm);
234 talloc_destroy(ctx);
235 ads_destroy(&ads);
236 return -1;
239 d_printf("Workgroup: %s\n", workgroup);
241 talloc_destroy(ctx);
242 ads_destroy(&ads);
243 return 0;
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], '$')) {
255 if (disp_fields[1])
256 d_printf("%-21.21s %s\n",
257 disp_fields[0], disp_fields[1]);
258 else
259 d_printf("%s\n", disp_fields[0]);
262 SAFE_FREE(disp_fields[0]);
263 SAFE_FREE(disp_fields[1]);
264 return True;
266 if (!values) /* must be new field, indicate string field */
267 return True;
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]);
273 return True;
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)
283 ADS_STRUCT *ads;
284 ADS_STATUS status;
285 char *upn, *userdn;
286 void *res=NULL;
287 int rc = -1;
289 if (argc < 1) return net_ads_user_usage(argc, argv);
291 if (!(ads = ads_startup())) {
292 return -1;
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));
299 goto done;
302 if (ads_count_replies(ads, res)) {
303 d_fprintf(stderr, "ads_user_add: User %s already exists\n", argv[0]);
304 goto done;
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],
315 ads_errstr(status));
316 goto done;
319 /* if no password is to be set, we're done */
320 if (argc == 1) {
321 d_printf("User %s added\n", argv[0]);
322 rc = 0;
323 goto done;
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);
330 safe_free(upn);
331 if (ADS_ERR_OK(status)) {
332 d_printf("User %s added\n", argv[0]);
333 rc = 0;
334 goto done;
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);
348 done:
349 if (res)
350 ads_msgfree(ads, res);
351 ads_destroy(&ads);
352 return rc;
355 static int ads_user_info(int argc, const char **argv)
357 ADS_STRUCT *ads;
358 ADS_STATUS rc;
359 void *res;
360 const char *attrs[] = {"memberOf", NULL};
361 char *searchstring=NULL;
362 char **grouplist;
363 char *escaped_user;
365 if (argc < 1) {
366 return net_ads_user_usage(argc, argv);
369 escaped_user = escape_ldap_string_alloc(argv[0]);
371 if (!escaped_user) {
372 d_fprintf(stderr, "ads_user_info: failed to escape user %s\n", argv[0]);
373 return -1;
376 if (!(ads = ads_startup())) {
377 SAFE_FREE(escaped_user);
378 return -1;
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));
387 ads_destroy(&ads);
388 SAFE_FREE(escaped_user);
389 return -1;
392 grouplist = ldap_get_values(ads->ld, res, "memberOf");
394 if (grouplist) {
395 int i;
396 char **groupname;
397 for (i=0;grouplist[i];i++) {
398 groupname = ldap_explode_dn(grouplist[i], 1);
399 d_printf("%s\n", groupname[0]);
400 ldap_value_free(groupname);
402 ldap_value_free(grouplist);
405 ads_msgfree(ads, res);
406 ads_destroy(&ads);
407 SAFE_FREE(escaped_user);
408 return 0;
411 static int ads_user_delete(int argc, const char **argv)
413 ADS_STRUCT *ads;
414 ADS_STATUS rc;
415 void *res;
416 char *userdn;
418 if (argc < 1) {
419 return net_ads_user_usage(argc, argv);
422 if (!(ads = ads_startup())) {
423 return -1;
426 rc = ads_find_user_acct(ads, &res, argv[0]);
427 if (!ADS_ERR_OK(rc)) {
428 DEBUG(0, ("User %s does not exist\n", argv[0]));
429 ads_destroy(&ads);
430 return -1;
432 userdn = ads_get_dn(ads, res);
433 ads_msgfree(ads, res);
434 rc = ads_del_dn(ads, userdn);
435 ads_memfree(ads, userdn);
436 if (!ADS_ERR_OK(rc)) {
437 d_printf("User %s deleted\n", argv[0]);
438 ads_destroy(&ads);
439 return 0;
441 d_fprintf(stderr, "Error deleting user %s: %s\n", argv[0],
442 ads_errstr(rc));
443 ads_destroy(&ads);
444 return -1;
447 int net_ads_user(int argc, const char **argv)
449 struct functable func[] = {
450 {"ADD", ads_user_add},
451 {"INFO", ads_user_info},
452 {"DELETE", ads_user_delete},
453 {NULL, NULL}
455 ADS_STRUCT *ads;
456 ADS_STATUS rc;
457 const char *shortattrs[] = {"sAMAccountName", NULL};
458 const char *longattrs[] = {"sAMAccountName", "description", NULL};
459 char *disp_fields[2] = {NULL, NULL};
461 if (argc == 0) {
462 if (!(ads = ads_startup())) {
463 return -1;
466 if (opt_long_list_entries)
467 d_printf("\nUser name Comment"\
468 "\n-----------------------------\n");
470 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
471 LDAP_SCOPE_SUBTREE,
472 "(objectclass=user)",
473 opt_long_list_entries ? longattrs :
474 shortattrs, usergrp_display,
475 disp_fields);
476 ads_destroy(&ads);
477 return 0;
480 return net_run_function(argc, argv, func, net_ads_user_usage);
483 static int net_ads_group_usage(int argc, const char **argv)
485 return net_help_group(argc, argv);
488 static int ads_group_add(int argc, const char **argv)
490 ADS_STRUCT *ads;
491 ADS_STATUS status;
492 void *res=NULL;
493 int rc = -1;
495 if (argc < 1) {
496 return net_ads_group_usage(argc, argv);
499 if (!(ads = ads_startup())) {
500 return -1;
503 status = ads_find_user_acct(ads, &res, argv[0]);
505 if (!ADS_ERR_OK(status)) {
506 d_fprintf(stderr, "ads_group_add: %s\n", ads_errstr(status));
507 goto done;
510 if (ads_count_replies(ads, res)) {
511 d_fprintf(stderr, "ads_group_add: Group %s already exists\n", argv[0]);
512 ads_msgfree(ads, res);
513 goto done;
516 if (opt_container == NULL) {
517 opt_container = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS);
520 status = ads_add_group_acct(ads, argv[0], opt_container, opt_comment);
522 if (ADS_ERR_OK(status)) {
523 d_printf("Group %s added\n", argv[0]);
524 rc = 0;
525 } else {
526 d_fprintf(stderr, "Could not add group %s: %s\n", argv[0],
527 ads_errstr(status));
530 done:
531 if (res)
532 ads_msgfree(ads, res);
533 ads_destroy(&ads);
534 return rc;
537 static int ads_group_delete(int argc, const char **argv)
539 ADS_STRUCT *ads;
540 ADS_STATUS rc;
541 void *res;
542 char *groupdn;
544 if (argc < 1) {
545 return net_ads_group_usage(argc, argv);
548 if (!(ads = ads_startup())) {
549 return -1;
552 rc = ads_find_user_acct(ads, &res, argv[0]);
553 if (!ADS_ERR_OK(rc)) {
554 DEBUG(0, ("Group %s does not exist\n", argv[0]));
555 ads_destroy(&ads);
556 return -1;
558 groupdn = ads_get_dn(ads, res);
559 ads_msgfree(ads, res);
560 rc = ads_del_dn(ads, groupdn);
561 ads_memfree(ads, groupdn);
562 if (!ADS_ERR_OK(rc)) {
563 d_printf("Group %s deleted\n", argv[0]);
564 ads_destroy(&ads);
565 return 0;
567 d_fprintf(stderr, "Error deleting group %s: %s\n", argv[0],
568 ads_errstr(rc));
569 ads_destroy(&ads);
570 return -1;
573 int net_ads_group(int argc, const char **argv)
575 struct functable func[] = {
576 {"ADD", ads_group_add},
577 {"DELETE", ads_group_delete},
578 {NULL, NULL}
580 ADS_STRUCT *ads;
581 ADS_STATUS rc;
582 const char *shortattrs[] = {"sAMAccountName", NULL};
583 const char *longattrs[] = {"sAMAccountName", "description", NULL};
584 char *disp_fields[2] = {NULL, NULL};
586 if (argc == 0) {
587 if (!(ads = ads_startup())) {
588 return -1;
591 if (opt_long_list_entries)
592 d_printf("\nGroup name Comment"\
593 "\n-----------------------------\n");
594 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
595 LDAP_SCOPE_SUBTREE,
596 "(objectclass=group)",
597 opt_long_list_entries ? longattrs :
598 shortattrs, usergrp_display,
599 disp_fields);
601 ads_destroy(&ads);
602 return 0;
604 return net_run_function(argc, argv, func, net_ads_group_usage);
607 static int net_ads_status(int argc, const char **argv)
609 ADS_STRUCT *ads;
610 ADS_STATUS rc;
611 void *res;
613 if (!(ads = ads_startup())) {
614 return -1;
617 rc = ads_find_machine_acct(ads, &res, global_myname());
618 if (!ADS_ERR_OK(rc)) {
619 d_fprintf(stderr, "ads_find_machine_acct: %s\n", ads_errstr(rc));
620 ads_destroy(&ads);
621 return -1;
624 if (ads_count_replies(ads, res) == 0) {
625 d_fprintf(stderr, "No machine account for '%s' found\n", global_myname());
626 ads_destroy(&ads);
627 return -1;
630 ads_dump(ads, res);
631 ads_destroy(&ads);
632 return 0;
635 static int net_ads_leave(int argc, const char **argv)
637 ADS_STRUCT *ads = NULL;
638 ADS_STATUS rc;
640 if (!secrets_init()) {
641 DEBUG(1,("Failed to initialise secrets database\n"));
642 return -1;
645 if (!opt_password) {
646 net_use_machine_password();
649 if (!(ads = ads_startup())) {
650 return -1;
653 rc = ads_leave_realm(ads, global_myname());
654 if (!ADS_ERR_OK(rc)) {
655 d_fprintf(stderr, "Failed to delete host '%s' from the '%s' realm.\n",
656 global_myname(), ads->config.realm);
657 ads_destroy(&ads);
658 return -1;
661 d_printf("Removed '%s' from realm '%s'\n", global_myname(), ads->config.realm);
662 ads_destroy(&ads);
663 return 0;
666 static int net_ads_join_ok(void)
668 ADS_STRUCT *ads = NULL;
670 if (!secrets_init()) {
671 DEBUG(1,("Failed to initialise secrets database\n"));
672 return -1;
675 net_use_machine_password();
677 if (!(ads = ads_startup())) {
678 return -1;
681 ads_destroy(&ads);
682 return 0;
686 check that an existing join is OK
688 int net_ads_testjoin(int argc, const char **argv)
690 use_in_memory_ccache();
692 /* Display success or failure */
693 if (net_ads_join_ok() != 0) {
694 fprintf(stderr,"Join to domain is not valid\n");
695 return -1;
698 printf("Join is OK\n");
699 return 0;
703 join a domain using ADS
705 int net_ads_join(int argc, const char **argv)
707 ADS_STRUCT *ads;
708 ADS_STATUS rc;
709 char *password;
710 char *machine_account = NULL;
711 char *tmp_password;
712 const char *org_unit = NULL;
713 char *dn;
714 void *res;
715 DOM_SID dom_sid;
716 char *ou_str;
717 uint32 sec_channel_type = SEC_CHAN_WKSTA;
718 uint32 account_type = UF_WORKSTATION_TRUST_ACCOUNT;
719 const char *short_domain_name = NULL;
720 TALLOC_CTX *ctx = NULL;
722 if (argc > 0) {
723 org_unit = argv[0];
726 if (!secrets_init()) {
727 DEBUG(1,("Failed to initialise secrets database\n"));
728 return -1;
731 tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
732 password = SMB_STRDUP(tmp_password);
734 if (!(ads = ads_startup())) {
735 return -1;
738 if (!*lp_realm()) {
739 d_fprintf(stderr, "realm must be set in in smb.conf for ADS join to succeed.\n");
740 ads_destroy(&ads);
741 return -1;
744 if (strcmp(ads->config.realm, lp_realm()) != 0) {
745 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());
746 ads_destroy(&ads);
747 return -1;
750 ou_str = ads_ou_string(ads,org_unit);
751 asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path);
752 free(ou_str);
754 rc = ads_search_dn(ads, &res, dn, NULL);
755 ads_msgfree(ads, res);
757 if (rc.error_type == ENUM_ADS_ERROR_LDAP && rc.err.rc == LDAP_NO_SUCH_OBJECT) {
758 d_fprintf(stderr, "ads_join_realm: organizational unit %s does not exist (dn:%s)\n",
759 org_unit, dn);
760 ads_destroy(&ads);
761 return -1;
763 free(dn);
765 if (!ADS_ERR_OK(rc)) {
766 d_fprintf(stderr, "ads_join_realm: %s\n", ads_errstr(rc));
767 ads_destroy(&ads);
768 return -1;
771 rc = ads_join_realm(ads, global_myname(), account_type, org_unit);
772 if (!ADS_ERR_OK(rc)) {
773 d_fprintf(stderr, "ads_join_realm: %s\n", ads_errstr(rc));
774 ads_destroy(&ads);
775 return -1;
778 rc = ads_domain_sid(ads, &dom_sid);
779 if (!ADS_ERR_OK(rc)) {
780 d_fprintf(stderr, "ads_domain_sid: %s\n", ads_errstr(rc));
781 ads_destroy(&ads);
782 return -1;
785 if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
786 d_fprintf(stderr, "asprintf failed\n");
787 ads_destroy(&ads);
788 return -1;
791 rc = ads_set_machine_password(ads, machine_account, password);
792 if (!ADS_ERR_OK(rc)) {
793 d_fprintf(stderr, "ads_set_machine_password: %s\n", ads_errstr(rc));
794 ads_destroy(&ads);
795 return -1;
798 /* make sure we get the right workgroup */
800 if ( !(ctx = talloc_init("net ads join")) ) {
801 d_fprintf(stderr, "talloc_init() failed!\n");
802 ads_destroy(&ads);
803 return -1;
806 rc = ads_workgroup_name(ads, ctx, &short_domain_name);
807 if ( ADS_ERR_OK(rc) ) {
808 if ( !strequal(lp_workgroup(), short_domain_name) ) {
809 d_printf("The workgroup in smb.conf does not match the short\n");
810 d_printf("domain name obtained from the server.\n");
811 d_printf("Using the name [%s] from the server.\n", short_domain_name);
812 d_printf("You should set \"workgroup = %s\" in smb.conf.\n", short_domain_name);
814 } else {
815 short_domain_name = lp_workgroup();
818 d_printf("Using short domain name -- %s\n", short_domain_name);
820 /* HACK ALRET! Store the sid and password under bother the lp_workgroup()
821 value from smb.conf and the string returned from the server. The former is
822 neede to bootstrap winbindd's first connection to the DC to get the real
823 short domain name --jerry */
825 if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) {
826 DEBUG(1,("Failed to save domain sid\n"));
827 ads_destroy(&ads);
828 return -1;
831 if (!secrets_store_machine_password(password, lp_workgroup(), sec_channel_type)) {
832 DEBUG(1,("Failed to save machine password\n"));
833 ads_destroy(&ads);
834 return -1;
837 #ifdef HAVE_KRB5
838 if (!kerberos_derive_salting_principal(machine_account)) {
839 DEBUG(1,("Failed to determine salting principal\n"));
840 ads_destroy(&ads);
841 return -1;
844 if (!kerberos_derive_cifs_salting_principals()) {
845 DEBUG(1,("Failed to determine salting principals\n"));
846 ads_destroy(&ads);
847 return -1;
849 #endif
851 if (!secrets_store_domain_sid(short_domain_name, &dom_sid)) {
852 DEBUG(1,("Failed to save domain sid\n"));
853 ads_destroy(&ads);
854 return -1;
857 if (!secrets_store_machine_password(password, short_domain_name, sec_channel_type)) {
858 DEBUG(1,("Failed to save machine password\n"));
859 ads_destroy(&ads);
860 return -1;
863 /* Now build the keytab, using the same ADS connection */
864 if (lp_use_kerberos_keytab() && ads_keytab_create_default(ads)) {
865 DEBUG(1,("Error creating host keytab!\n"));
868 d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm);
870 SAFE_FREE(password);
871 SAFE_FREE(machine_account);
872 if ( ctx ) {
873 talloc_destroy(ctx);
875 ads_destroy(&ads);
876 return 0;
879 int net_ads_printer_usage(int argc, const char **argv)
881 d_printf(
882 "\nnet ads printer search <printer>"
883 "\n\tsearch for a printer in the directory\n"
884 "\nnet ads printer info <printer> <server>"
885 "\n\tlookup info in directory for printer on server"
886 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
887 "\nnet ads printer publish <printername>"
888 "\n\tpublish printer in directory"
889 "\n\t(note: printer name is required)\n"
890 "\nnet ads printer remove <printername>"
891 "\n\tremove printer from directory"
892 "\n\t(note: printer name is required)\n");
893 return -1;
896 static int net_ads_printer_search(int argc, const char **argv)
898 ADS_STRUCT *ads;
899 ADS_STATUS rc;
900 void *res = NULL;
902 if (!(ads = ads_startup())) {
903 return -1;
906 rc = ads_find_printers(ads, &res);
908 if (!ADS_ERR_OK(rc)) {
909 d_fprintf(stderr, "ads_find_printer: %s\n", ads_errstr(rc));
910 ads_msgfree(ads, res);
911 ads_destroy(&ads);
912 return -1;
915 if (ads_count_replies(ads, res) == 0) {
916 d_fprintf(stderr, "No results found\n");
917 ads_msgfree(ads, res);
918 ads_destroy(&ads);
919 return -1;
922 ads_dump(ads, res);
923 ads_msgfree(ads, res);
924 ads_destroy(&ads);
925 return 0;
928 static int net_ads_printer_info(int argc, const char **argv)
930 ADS_STRUCT *ads;
931 ADS_STATUS rc;
932 const char *servername, *printername;
933 void *res = NULL;
935 if (!(ads = ads_startup())) {
936 return -1;
939 if (argc > 0) {
940 printername = argv[0];
941 } else {
942 printername = "*";
945 if (argc > 1) {
946 servername = argv[1];
947 } else {
948 servername = global_myname();
951 rc = ads_find_printer_on_server(ads, &res, printername, servername);
953 if (!ADS_ERR_OK(rc)) {
954 d_fprintf(stderr, "ads_find_printer_on_server: %s\n", ads_errstr(rc));
955 ads_msgfree(ads, res);
956 ads_destroy(&ads);
957 return -1;
960 if (ads_count_replies(ads, res) == 0) {
961 d_fprintf(stderr, "Printer '%s' not found\n", printername);
962 ads_msgfree(ads, res);
963 ads_destroy(&ads);
964 return -1;
967 ads_dump(ads, res);
968 ads_msgfree(ads, res);
969 ads_destroy(&ads);
971 return 0;
974 void do_drv_upgrade_printer(int msg_type, struct process_id src,
975 void *buf, size_t len)
977 return;
980 static int net_ads_printer_publish(int argc, const char **argv)
982 ADS_STRUCT *ads;
983 ADS_STATUS rc;
984 const char *servername, *printername;
985 struct cli_state *cli;
986 struct rpc_pipe_client *pipe_hnd;
987 struct in_addr server_ip;
988 NTSTATUS nt_status;
989 TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
990 ADS_MODLIST mods = ads_init_mods(mem_ctx);
991 char *prt_dn, *srv_dn, **srv_cn;
992 void *res = NULL;
994 if (!(ads = ads_startup())) {
995 return -1;
998 if (argc < 1) {
999 return net_ads_printer_usage(argc, argv);
1002 printername = argv[0];
1004 if (argc == 2) {
1005 servername = argv[1];
1006 } else {
1007 servername = global_myname();
1010 /* Get printer data from SPOOLSS */
1012 resolve_name(servername, &server_ip, 0x20);
1014 nt_status = cli_full_connection(&cli, global_myname(), servername,
1015 &server_ip, 0,
1016 "IPC$", "IPC",
1017 opt_user_name, opt_workgroup,
1018 opt_password ? opt_password : "",
1019 CLI_FULL_CONNECTION_USE_KERBEROS,
1020 Undefined, NULL);
1022 if (NT_STATUS_IS_ERR(nt_status)) {
1023 d_fprintf(stderr, "Unable to open a connnection to %s to obtain data "
1024 "for %s\n", servername, printername);
1025 ads_destroy(&ads);
1026 return -1;
1029 /* Publish on AD server */
1031 ads_find_machine_acct(ads, &res, servername);
1033 if (ads_count_replies(ads, res) == 0) {
1034 d_fprintf(stderr, "Could not find machine account for server %s\n",
1035 servername);
1036 ads_destroy(&ads);
1037 return -1;
1040 srv_dn = ldap_get_dn(ads->ld, res);
1041 srv_cn = ldap_explode_dn(srv_dn, 1);
1043 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], printername, srv_dn);
1045 pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SPOOLSS, &nt_status);
1046 get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
1047 printername);
1049 rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
1050 if (!ADS_ERR_OK(rc)) {
1051 d_fprintf(stderr, "ads_publish_printer: %s\n", ads_errstr(rc));
1052 ads_destroy(&ads);
1053 return -1;
1056 d_printf("published printer\n");
1057 ads_destroy(&ads);
1059 return 0;
1062 static int net_ads_printer_remove(int argc, const char **argv)
1064 ADS_STRUCT *ads;
1065 ADS_STATUS rc;
1066 const char *servername;
1067 char *prt_dn;
1068 void *res = NULL;
1070 if (!(ads = ads_startup())) {
1071 return -1;
1074 if (argc < 1) {
1075 return net_ads_printer_usage(argc, argv);
1078 if (argc > 1) {
1079 servername = argv[1];
1080 } else {
1081 servername = global_myname();
1084 rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
1086 if (!ADS_ERR_OK(rc)) {
1087 d_fprintf(stderr, "ads_find_printer_on_server: %s\n", ads_errstr(rc));
1088 ads_msgfree(ads, res);
1089 ads_destroy(&ads);
1090 return -1;
1093 if (ads_count_replies(ads, res) == 0) {
1094 d_fprintf(stderr, "Printer '%s' not found\n", argv[1]);
1095 ads_msgfree(ads, res);
1096 ads_destroy(&ads);
1097 return -1;
1100 prt_dn = ads_get_dn(ads, res);
1101 ads_msgfree(ads, res);
1102 rc = ads_del_dn(ads, prt_dn);
1103 ads_memfree(ads, prt_dn);
1105 if (!ADS_ERR_OK(rc)) {
1106 d_fprintf(stderr, "ads_del_dn: %s\n", ads_errstr(rc));
1107 ads_destroy(&ads);
1108 return -1;
1111 ads_destroy(&ads);
1112 return 0;
1115 static int net_ads_printer(int argc, const char **argv)
1117 struct functable func[] = {
1118 {"SEARCH", net_ads_printer_search},
1119 {"INFO", net_ads_printer_info},
1120 {"PUBLISH", net_ads_printer_publish},
1121 {"REMOVE", net_ads_printer_remove},
1122 {NULL, NULL}
1125 return net_run_function(argc, argv, func, net_ads_printer_usage);
1129 static int net_ads_password(int argc, const char **argv)
1131 ADS_STRUCT *ads;
1132 const char *auth_principal = opt_user_name;
1133 const char *auth_password = opt_password;
1134 char *realm = NULL;
1135 char *new_password = NULL;
1136 char *c, *prompt;
1137 const char *user;
1138 ADS_STATUS ret;
1140 if (opt_user_name == NULL || opt_password == NULL) {
1141 d_fprintf(stderr, "You must supply an administrator username/password\n");
1142 return -1;
1145 if (argc < 1) {
1146 d_fprintf(stderr, "ERROR: You must say which username to change password for\n");
1147 return -1;
1150 user = argv[0];
1151 if (!strchr_m(user, '@')) {
1152 asprintf(&c, "%s@%s", argv[0], lp_realm());
1153 user = c;
1156 use_in_memory_ccache();
1157 c = strchr_m(auth_principal, '@');
1158 if (c) {
1159 realm = ++c;
1160 } else {
1161 realm = lp_realm();
1164 /* use the realm so we can eventually change passwords for users
1165 in realms other than default */
1166 if (!(ads = ads_init(realm, NULL, NULL))) {
1167 return -1;
1170 /* we don't actually need a full connect, but it's the easy way to
1171 fill in the KDC's addresss */
1172 ads_connect(ads);
1174 if (!ads || !ads->config.realm) {
1175 d_fprintf(stderr, "Didn't find the kerberos server!\n");
1176 return -1;
1179 if (argv[1]) {
1180 new_password = (char *)argv[1];
1181 } else {
1182 asprintf(&prompt, "Enter new password for %s:", user);
1183 new_password = getpass(prompt);
1184 free(prompt);
1187 ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
1188 auth_password, user, new_password, ads->auth.time_offset);
1189 if (!ADS_ERR_OK(ret)) {
1190 d_fprintf(stderr, "Password change failed :-( ...\n");
1191 ads_destroy(&ads);
1192 return -1;
1195 d_printf("Password change for %s completed.\n", user);
1196 ads_destroy(&ads);
1198 return 0;
1201 int net_ads_changetrustpw(int argc, const char **argv)
1203 ADS_STRUCT *ads;
1204 char *host_principal;
1205 fstring my_name;
1206 ADS_STATUS ret;
1208 if (!secrets_init()) {
1209 DEBUG(1,("Failed to initialise secrets database\n"));
1210 return -1;
1213 net_use_machine_password();
1215 use_in_memory_ccache();
1217 if (!(ads = ads_startup())) {
1218 return -1;
1221 fstrcpy(my_name, global_myname());
1222 strlower_m(my_name);
1223 asprintf(&host_principal, "%s@%s", my_name, ads->config.realm);
1224 d_printf("Changing password for principal: HOST/%s\n", host_principal);
1226 ret = ads_change_trust_account_password(ads, host_principal);
1228 if (!ADS_ERR_OK(ret)) {
1229 d_fprintf(stderr, "Password change failed :-( ...\n");
1230 ads_destroy(&ads);
1231 SAFE_FREE(host_principal);
1232 return -1;
1235 d_printf("Password change for principal HOST/%s succeeded.\n", host_principal);
1237 if (lp_use_kerberos_keytab()) {
1238 d_printf("Attempting to update system keytab with new password.\n");
1239 if (ads_keytab_create_default(ads)) {
1240 d_printf("Failed to update system keytab.\n");
1244 ads_destroy(&ads);
1245 SAFE_FREE(host_principal);
1247 return 0;
1251 help for net ads search
1253 static int net_ads_search_usage(int argc, const char **argv)
1255 d_printf(
1256 "\nnet ads search <expression> <attributes...>\n"\
1257 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
1258 "The expression is a standard LDAP search expression, and the\n"\
1259 "attributes are a list of LDAP fields to show in the results\n\n"\
1260 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
1262 net_common_flags_usage(argc, argv);
1263 return -1;
1268 general ADS search function. Useful in diagnosing problems in ADS
1270 static int net_ads_search(int argc, const char **argv)
1272 ADS_STRUCT *ads;
1273 ADS_STATUS rc;
1274 const char *ldap_exp;
1275 const char **attrs;
1276 void *res = NULL;
1278 if (argc < 1) {
1279 return net_ads_search_usage(argc, argv);
1282 if (!(ads = ads_startup())) {
1283 return -1;
1286 ldap_exp = argv[0];
1287 attrs = (argv + 1);
1289 rc = ads_do_search_all(ads, ads->config.bind_path,
1290 LDAP_SCOPE_SUBTREE,
1291 ldap_exp, attrs, &res);
1292 if (!ADS_ERR_OK(rc)) {
1293 d_fprintf(stderr, "search failed: %s\n", ads_errstr(rc));
1294 ads_destroy(&ads);
1295 return -1;
1298 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
1300 /* dump the results */
1301 ads_dump(ads, res);
1303 ads_msgfree(ads, res);
1304 ads_destroy(&ads);
1306 return 0;
1311 help for net ads search
1313 static int net_ads_dn_usage(int argc, const char **argv)
1315 d_printf(
1316 "\nnet ads dn <dn> <attributes...>\n"\
1317 "\nperform a raw LDAP search on a ADS server and dump the results\n"\
1318 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"\
1319 "to show in the results\n\n"\
1320 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
1322 net_common_flags_usage(argc, argv);
1323 return -1;
1328 general ADS search function. Useful in diagnosing problems in ADS
1330 static int net_ads_dn(int argc, const char **argv)
1332 ADS_STRUCT *ads;
1333 ADS_STATUS rc;
1334 const char *dn;
1335 const char **attrs;
1336 void *res = NULL;
1338 if (argc < 1) {
1339 return net_ads_dn_usage(argc, argv);
1342 if (!(ads = ads_startup())) {
1343 return -1;
1346 dn = argv[0];
1347 attrs = (argv + 1);
1349 rc = ads_do_search_all(ads, dn,
1350 LDAP_SCOPE_BASE,
1351 "(objectclass=*)", attrs, &res);
1352 if (!ADS_ERR_OK(rc)) {
1353 d_fprintf(stderr, "search failed: %s\n", ads_errstr(rc));
1354 ads_destroy(&ads);
1355 return -1;
1358 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
1360 /* dump the results */
1361 ads_dump(ads, res);
1363 ads_msgfree(ads, res);
1364 ads_destroy(&ads);
1366 return 0;
1369 static int net_ads_keytab_usage(int argc, const char **argv)
1371 d_printf(
1372 "net ads keytab <COMMAND>\n"\
1373 "<COMMAND> can be either:\n"\
1374 " CREATE Creates a fresh keytab\n"\
1375 " ADD Adds new service principal\n"\
1376 " FLUSH Flushes out all keytab entries\n"\
1377 " HELP Prints this help message\n"\
1378 "The ADD command will take arguments, the other commands\n"\
1379 "will not take any arguments. The arguments given to ADD\n"\
1380 "should be a list of principals to add. For example, \n"\
1381 " net ads keytab add srv1 srv2\n"\
1382 "will add principals for the services srv1 and srv2 to the\n"\
1383 "system's keytab.\n"\
1384 "\n"
1386 return -1;
1389 static int net_ads_keytab_flush(int argc, const char **argv)
1391 int ret;
1392 ADS_STRUCT *ads;
1394 if (!(ads = ads_startup())) {
1395 return -1;
1397 ret = ads_keytab_flush(ads);
1398 ads_destroy(&ads);
1399 return ret;
1402 static int net_ads_keytab_add(int argc, const char **argv)
1404 int i;
1405 int ret = 0;
1406 ADS_STRUCT *ads;
1408 d_printf("Processing principals to add...\n");
1409 if (!(ads = ads_startup())) {
1410 return -1;
1412 for (i = 0; i < argc; i++) {
1413 ret |= ads_keytab_add_entry(ads, argv[i]);
1415 ads_destroy(&ads);
1416 return ret;
1419 static int net_ads_keytab_create(int argc, const char **argv)
1421 ADS_STRUCT *ads;
1422 int ret;
1424 if (!(ads = ads_startup())) {
1425 return -1;
1427 ret = ads_keytab_create_default(ads);
1428 ads_destroy(&ads);
1429 return ret;
1432 int net_ads_keytab(int argc, const char **argv)
1434 struct functable func[] = {
1435 {"CREATE", net_ads_keytab_create},
1436 {"ADD", net_ads_keytab_add},
1437 {"FLUSH", net_ads_keytab_flush},
1438 {"HELP", net_ads_keytab_usage},
1439 {NULL, NULL}
1442 if (!lp_use_kerberos_keytab()) {
1443 d_printf("\nWarning: \"use kerberos keytab\" must be set to \"true\" in order to \
1444 use keytab functions.\n");
1447 return net_run_function(argc, argv, func, net_ads_keytab_usage);
1450 int net_ads_help(int argc, const char **argv)
1452 struct functable func[] = {
1453 {"USER", net_ads_user_usage},
1454 {"GROUP", net_ads_group_usage},
1455 {"PRINTER", net_ads_printer_usage},
1456 {"SEARCH", net_ads_search_usage},
1457 #if 0
1458 {"INFO", net_ads_info},
1459 {"JOIN", net_ads_join},
1460 {"LEAVE", net_ads_leave},
1461 {"STATUS", net_ads_status},
1462 {"PASSWORD", net_ads_password},
1463 {"CHANGETRUSTPW", net_ads_changetrustpw},
1464 #endif
1465 {NULL, NULL}
1468 return net_run_function(argc, argv, func, net_ads_usage);
1471 int net_ads(int argc, const char **argv)
1473 struct functable func[] = {
1474 {"INFO", net_ads_info},
1475 {"JOIN", net_ads_join},
1476 {"TESTJOIN", net_ads_testjoin},
1477 {"LEAVE", net_ads_leave},
1478 {"STATUS", net_ads_status},
1479 {"USER", net_ads_user},
1480 {"GROUP", net_ads_group},
1481 {"PASSWORD", net_ads_password},
1482 {"CHANGETRUSTPW", net_ads_changetrustpw},
1483 {"PRINTER", net_ads_printer},
1484 {"SEARCH", net_ads_search},
1485 {"DN", net_ads_dn},
1486 {"WORKGROUP", net_ads_workgroup},
1487 {"LOOKUP", net_ads_lookup},
1488 {"KEYTAB", net_ads_keytab},
1489 {"HELP", net_ads_help},
1490 {NULL, NULL}
1493 return net_run_function(argc, argv, func, net_ads_usage);
1496 #else
1498 static int net_ads_noads(void)
1500 d_fprintf(stderr, "ADS support not compiled in\n");
1501 return -1;
1504 int net_ads_keytab(int argc, const char **argv)
1506 return net_ads_noads();
1509 int net_ads_usage(int argc, const char **argv)
1511 return net_ads_noads();
1514 int net_ads_help(int argc, const char **argv)
1516 return net_ads_noads();
1519 int net_ads_changetrustpw(int argc, const char **argv)
1521 return net_ads_noads();
1524 int net_ads_join(int argc, const char **argv)
1526 return net_ads_noads();
1529 int net_ads_user(int argc, const char **argv)
1531 return net_ads_noads();
1534 int net_ads_group(int argc, const char **argv)
1536 return net_ads_noads();
1539 /* this one shouldn't display a message */
1540 int net_ads_check(void)
1542 return -1;
1545 int net_ads(int argc, const char **argv)
1547 return net_ads_usage(argc, argv);
1550 #endif