s3:net: disable dynamic dns updates at the end of "net ads join" in a cluster (bug...
[kamenim/samba.git] / source3 / utils / net_ads.c
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)
7    Copyright (C) 2006 Gerald (Jerry) Carter (jerry@samba.org)
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "utils/net.h"
25 #include "librpc/gen_ndr/ndr_krb5pac.h"
26 #include "../librpc/gen_ndr/cli_spoolss.h"
27 #include "nsswitch/libwbclient/wbclient.h"
28 #include "ads.h"
29 #include "libads/cldap.h"
30 #include "libads/dns.h"
31 #include "../libds/common/flags.h"
32 #include "librpc/gen_ndr/libnet_join.h"
33 #include "libnet/libnet_join.h"
34 #include "smb_krb5.h"
35 #include "secrets.h"
36 #include "krb5_env.h"
37 #include "../libcli/security/security.h"
38
39 #ifdef HAVE_ADS
40
41 /* when we do not have sufficient input parameters to contact a remote domain
42  * we always fall back to our own realm - Guenther*/
43
44 static const char *assume_own_realm(struct net_context *c)
45 {
46         if (!c->opt_host && strequal(lp_workgroup(), c->opt_target_workgroup)) {
47                 return lp_realm();
48         }
49
50         return NULL;
51 }
52
53 /*
54   do a cldap netlogon query
55 */
56 static int net_ads_cldap_netlogon(struct net_context *c, ADS_STRUCT *ads)
57 {
58         char addr[INET6_ADDRSTRLEN];
59         struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
60
61         print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
62         if ( !ads_cldap_netlogon_5(talloc_tos(), addr, ads->server.realm, &reply ) ) {
63                 d_fprintf(stderr, _("CLDAP query failed!\n"));
64                 return -1;
65         }
66
67         d_printf(_("Information for Domain Controller: %s\n\n"),
68                 addr);
69
70         d_printf(_("Response Type: "));
71         switch (reply.command) {
72         case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
73                 d_printf("LOGON_SAM_LOGON_USER_UNKNOWN_EX\n");
74                 break;
75         case LOGON_SAM_LOGON_RESPONSE_EX:
76                 d_printf("LOGON_SAM_LOGON_RESPONSE_EX\n");
77                 break;
78         default:
79                 d_printf("0x%x\n", reply.command);
80                 break;
81         }
82
83         d_printf(_("GUID: %s\n"), GUID_string(talloc_tos(),&reply.domain_uuid));
84
85         d_printf(_("Flags:\n"
86                    "\tIs a PDC:                                   %s\n"
87                    "\tIs a GC of the forest:                      %s\n"
88                    "\tIs an LDAP server:                          %s\n"
89                    "\tSupports DS:                                %s\n"
90                    "\tIs running a KDC:                           %s\n"
91                    "\tIs running time services:                   %s\n"
92                    "\tIs the closest DC:                          %s\n"
93                    "\tIs writable:                                %s\n"
94                    "\tHas a hardware clock:                       %s\n"
95                    "\tIs a non-domain NC serviced by LDAP server: %s\n"
96                    "\tIs NT6 DC that has some secrets:            %s\n"
97                    "\tIs NT6 DC that has all secrets:             %s\n"),
98                    (reply.server_type & NBT_SERVER_PDC) ? _("yes") : _("no"),
99                    (reply.server_type & NBT_SERVER_GC) ? _("yes") : _("no"),
100                    (reply.server_type & NBT_SERVER_LDAP) ? _("yes") : _("no"),
101                    (reply.server_type & NBT_SERVER_DS) ? _("yes") : _("no"),
102                    (reply.server_type & NBT_SERVER_KDC) ? _("yes") : _("no"),
103                    (reply.server_type & NBT_SERVER_TIMESERV) ? _("yes") : _("no"),
104                    (reply.server_type & NBT_SERVER_CLOSEST) ? _("yes") : _("no"),
105                    (reply.server_type & NBT_SERVER_WRITABLE) ? _("yes") : _("no"),
106                    (reply.server_type & NBT_SERVER_GOOD_TIMESERV) ? _("yes") : _("no"),
107                    (reply.server_type & NBT_SERVER_NDNC) ? _("yes") : _("no"),
108                    (reply.server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6) ? _("yes") : _("no"),
109                    (reply.server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6) ? _("yes") : _("no"));
110
111
112         printf(_("Forest:\t\t\t%s\n"), reply.forest);
113         printf(_("Domain:\t\t\t%s\n"), reply.dns_domain);
114         printf(_("Domain Controller:\t%s\n"), reply.pdc_dns_name);
115
116         printf(_("Pre-Win2k Domain:\t%s\n"), reply.domain_name);
117         printf(_("Pre-Win2k Hostname:\t%s\n"), reply.pdc_name);
118
119         if (*reply.user_name) printf(_("User name:\t%s\n"), reply.user_name);
120
121         printf(_("Server Site Name :\t\t%s\n"), reply.server_site);
122         printf(_("Client Site Name :\t\t%s\n"), reply.client_site);
123
124         d_printf(_("NT Version: %d\n"), reply.nt_version);
125         d_printf(_("LMNT Token: %.2x\n"), reply.lmnt_token);
126         d_printf(_("LM20 Token: %.2x\n"), reply.lm20_token);
127
128         return 0;
129 }
130
131 /*
132   this implements the CLDAP based netlogon lookup requests
133   for finding the domain controller of a ADS domain
134 */
135 static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
136 {
137         ADS_STRUCT *ads;
138         int ret;
139
140         if (c->display_usage) {
141                 d_printf("%s\n"
142                          "net ads lookup\n"
143                          "    %s",
144                          _("Usage:"),
145                          _("Find the ADS DC using CLDAP lookup.\n"));
146                 return 0;
147         }
148
149         if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
150                 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
151                 ads_destroy(&ads);
152                 return -1;
153         }
154
155         if (!ads->config.realm) {
156                 ads->config.realm = CONST_DISCARD(char *, c->opt_target_workgroup);
157                 ads->ldap.port = 389;
158         }
159
160         ret = net_ads_cldap_netlogon(c, ads);
161         ads_destroy(&ads);
162         return ret;
163 }
164
165
166
167 static int net_ads_info(struct net_context *c, int argc, const char **argv)
168 {
169         ADS_STRUCT *ads;
170         char addr[INET6_ADDRSTRLEN];
171
172         if (c->display_usage) {
173                 d_printf("%s\n"
174                          "net ads info\n"
175                          "    %s",
176                          _("Usage:"),
177                          _("Display information about an Active Directory "
178                            "server.\n"));
179                 return 0;
180         }
181
182         if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
183                 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
184                 return -1;
185         }
186
187         if (!ads || !ads->config.realm) {
188                 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
189                 ads_destroy(&ads);
190                 return -1;
191         }
192
193         /* Try to set the server's current time since we didn't do a full
194            TCP LDAP session initially */
195
196         if ( !ADS_ERR_OK(ads_current_time( ads )) ) {
197                 d_fprintf( stderr, _("Failed to get server's current time!\n"));
198         }
199
200         print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
201
202         d_printf(_("LDAP server: %s\n"), addr);
203         d_printf(_("LDAP server name: %s\n"), ads->config.ldap_server_name);
204         d_printf(_("Realm: %s\n"), ads->config.realm);
205         d_printf(_("Bind Path: %s\n"), ads->config.bind_path);
206         d_printf(_("LDAP port: %d\n"), ads->ldap.port);
207         d_printf(_("Server time: %s\n"),
208                          http_timestring(talloc_tos(), ads->config.current_time));
209
210         d_printf(_("KDC server: %s\n"), ads->auth.kdc_server );
211         d_printf(_("Server time offset: %d\n"), ads->auth.time_offset );
212
213         ads_destroy(&ads);
214         return 0;
215 }
216
217 static void use_in_memory_ccache(void) {
218         /* Use in-memory credentials cache so we do not interfere with
219          * existing credentials */
220         setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
221 }
222
223 static ADS_STATUS ads_startup_int(struct net_context *c, bool only_own_domain,
224                                   uint32 auth_flags, ADS_STRUCT **ads_ret)
225 {
226         ADS_STRUCT *ads = NULL;
227         ADS_STATUS status;
228         bool need_password = false;
229         bool second_time = false;
230         char *cp;
231         const char *realm = NULL;
232         bool tried_closest_dc = false;
233
234         /* lp_realm() should be handled by a command line param,
235            However, the join requires that realm be set in smb.conf
236            and compares our realm with the remote server's so this is
237            ok until someone needs more flexibility */
238
239         *ads_ret = NULL;
240
241 retry_connect:
242         if (only_own_domain) {
243                 realm = lp_realm();
244         } else {
245                 realm = assume_own_realm(c);
246         }
247
248         ads = ads_init(realm, c->opt_target_workgroup, c->opt_host);
249
250         if (!c->opt_user_name) {
251                 c->opt_user_name = "administrator";
252         }
253
254         if (c->opt_user_specified) {
255                 need_password = true;
256         }
257
258 retry:
259         if (!c->opt_password && need_password && !c->opt_machine_pass) {
260                 c->opt_password = net_prompt_pass(c, c->opt_user_name);
261                 if (!c->opt_password) {
262                         ads_destroy(&ads);
263                         return ADS_ERROR(LDAP_NO_MEMORY);
264                 }
265         }
266
267         if (c->opt_password) {
268                 use_in_memory_ccache();
269                 SAFE_FREE(ads->auth.password);
270                 ads->auth.password = smb_xstrdup(c->opt_password);
271         }
272
273         ads->auth.flags |= auth_flags;
274         SAFE_FREE(ads->auth.user_name);
275         ads->auth.user_name = smb_xstrdup(c->opt_user_name);
276
277        /*
278         * If the username is of the form "name@realm",
279         * extract the realm and convert to upper case.
280         * This is only used to establish the connection.
281         */
282        if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
283                 *cp++ = '\0';
284                 SAFE_FREE(ads->auth.realm);
285                 ads->auth.realm = smb_xstrdup(cp);
286                 strupper_m(ads->auth.realm);
287        }
288
289         status = ads_connect(ads);
290
291         if (!ADS_ERR_OK(status)) {
292
293                 if (NT_STATUS_EQUAL(ads_ntstatus(status),
294                                     NT_STATUS_NO_LOGON_SERVERS)) {
295                         DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
296                         ads_destroy(&ads);
297                         return status;
298                 }
299
300                 if (!need_password && !second_time && !(auth_flags & ADS_AUTH_NO_BIND)) {
301                         need_password = true;
302                         second_time = true;
303                         goto retry;
304                 } else {
305                         ads_destroy(&ads);
306                         return status;
307                 }
308         }
309
310         /* when contacting our own domain, make sure we use the closest DC.
311          * This is done by reconnecting to ADS because only the first call to
312          * ads_connect will give us our own sitename */
313
314         if ((only_own_domain || !c->opt_host) && !tried_closest_dc) {
315
316                 tried_closest_dc = true; /* avoid loop */
317
318                 if (!ads_closest_dc(ads)) {
319
320                         namecache_delete(ads->server.realm, 0x1C);
321                         namecache_delete(ads->server.workgroup, 0x1C);
322
323                         ads_destroy(&ads);
324                         ads = NULL;
325
326                         goto retry_connect;
327                 }
328         }
329
330         *ads_ret = ads;
331         return status;
332 }
333
334 ADS_STATUS ads_startup(struct net_context *c, bool only_own_domain, ADS_STRUCT **ads)
335 {
336         return ads_startup_int(c, only_own_domain, 0, ads);
337 }
338
339 ADS_STATUS ads_startup_nobind(struct net_context *c, bool only_own_domain, ADS_STRUCT **ads)
340 {
341         return ads_startup_int(c, only_own_domain, ADS_AUTH_NO_BIND, ads);
342 }
343
344 /*
345   Check to see if connection can be made via ads.
346   ads_startup() stores the password in opt_password if it needs to so
347   that rpc or rap can use it without re-prompting.
348 */
349 static int net_ads_check_int(const char *realm, const char *workgroup, const char *host)
350 {
351         ADS_STRUCT *ads;
352         ADS_STATUS status;
353
354         if ( (ads = ads_init( realm, workgroup, host )) == NULL ) {
355                 return -1;
356         }
357
358         ads->auth.flags |= ADS_AUTH_NO_BIND;
359
360         status = ads_connect(ads);
361         if ( !ADS_ERR_OK(status) ) {
362                 return -1;
363         }
364
365         ads_destroy(&ads);
366         return 0;
367 }
368
369 int net_ads_check_our_domain(struct net_context *c)
370 {
371         return net_ads_check_int(lp_realm(), lp_workgroup(), NULL);
372 }
373
374 int net_ads_check(struct net_context *c)
375 {
376         return net_ads_check_int(NULL, c->opt_workgroup, c->opt_host);
377 }
378
379 /*
380    determine the netbios workgroup name for a domain
381  */
382 static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
383 {
384         ADS_STRUCT *ads;
385         char addr[INET6_ADDRSTRLEN];
386         struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
387
388         if (c->display_usage) {
389                 d_printf  ("%s\n"
390                            "net ads workgroup\n"
391                            "    %s\n",
392                          _("Usage:"),
393                          _("Print the workgroup name"));
394                 return 0;
395         }
396
397         if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
398                 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
399                 return -1;
400         }
401
402         if (!ads->config.realm) {
403                 ads->config.realm = CONST_DISCARD(char *, c->opt_target_workgroup);
404                 ads->ldap.port = 389;
405         }
406
407         print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
408         if ( !ads_cldap_netlogon_5(talloc_tos(), addr, ads->server.realm, &reply ) ) {
409                 d_fprintf(stderr, _("CLDAP query failed!\n"));
410                 ads_destroy(&ads);
411                 return -1;
412         }
413
414         d_printf(_("Workgroup: %s\n"), reply.domain_name);
415
416         ads_destroy(&ads);
417
418         return 0;
419 }
420
421
422
423 static bool usergrp_display(ADS_STRUCT *ads, char *field, void **values, void *data_area)
424 {
425         char **disp_fields = (char **) data_area;
426
427         if (!field) { /* must be end of record */
428                 if (disp_fields[0]) {
429                         if (!strchr_m(disp_fields[0], '$')) {
430                                 if (disp_fields[1])
431                                         d_printf("%-21.21s %s\n",
432                                                disp_fields[0], disp_fields[1]);
433                                 else
434                                         d_printf("%s\n", disp_fields[0]);
435                         }
436                 }
437                 SAFE_FREE(disp_fields[0]);
438                 SAFE_FREE(disp_fields[1]);
439                 return true;
440         }
441         if (!values) /* must be new field, indicate string field */
442                 return true;
443         if (StrCaseCmp(field, "sAMAccountName") == 0) {
444                 disp_fields[0] = SMB_STRDUP((char *) values[0]);
445         }
446         if (StrCaseCmp(field, "description") == 0)
447                 disp_fields[1] = SMB_STRDUP((char *) values[0]);
448         return true;
449 }
450
451 static int net_ads_user_usage(struct net_context *c, int argc, const char **argv)
452 {
453         return net_user_usage(c, argc, argv);
454 }
455
456 static int ads_user_add(struct net_context *c, int argc, const char **argv)
457 {
458         ADS_STRUCT *ads;
459         ADS_STATUS status;
460         char *upn, *userdn;
461         LDAPMessage *res=NULL;
462         int rc = -1;
463         char *ou_str = NULL;
464
465         if (argc < 1 || c->display_usage)
466                 return net_ads_user_usage(c, argc, argv);
467
468         if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
469                 return -1;
470         }
471
472         status = ads_find_user_acct(ads, &res, argv[0]);
473
474         if (!ADS_ERR_OK(status)) {
475                 d_fprintf(stderr, _("ads_user_add: %s\n"), ads_errstr(status));
476                 goto done;
477         }
478
479         if (ads_count_replies(ads, res)) {
480                 d_fprintf(stderr, _("ads_user_add: User %s already exists\n"),
481                           argv[0]);
482                 goto done;
483         }
484
485         if (c->opt_container) {
486                 ou_str = SMB_STRDUP(c->opt_container);
487         } else {
488                 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
489         }
490
491         status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment);
492
493         if (!ADS_ERR_OK(status)) {
494                 d_fprintf(stderr, _("Could not add user %s: %s\n"), argv[0],
495                          ads_errstr(status));
496                 goto done;
497         }
498
499         /* if no password is to be set, we're done */
500         if (argc == 1) {
501                 d_printf(_("User %s added\n"), argv[0]);
502                 rc = 0;
503                 goto done;
504         }
505
506         /* try setting the password */
507         if (asprintf(&upn, "%s@%s", argv[0], ads->config.realm) == -1) {
508                 goto done;
509         }
510         status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
511                                        ads->auth.time_offset);
512         SAFE_FREE(upn);
513         if (ADS_ERR_OK(status)) {
514                 d_printf(_("User %s added\n"), argv[0]);
515                 rc = 0;
516                 goto done;
517         }
518
519         /* password didn't set, delete account */
520         d_fprintf(stderr, _("Could not add user %s. "
521                             "Error setting password %s\n"),
522                  argv[0], ads_errstr(status));
523         ads_msgfree(ads, res);
524         status=ads_find_user_acct(ads, &res, argv[0]);
525         if (ADS_ERR_OK(status)) {
526                 userdn = ads_get_dn(ads, talloc_tos(), res);
527                 ads_del_dn(ads, userdn);
528                 TALLOC_FREE(userdn);
529         }
530
531  done:
532         if (res)
533                 ads_msgfree(ads, res);
534         ads_destroy(&ads);
535         SAFE_FREE(ou_str);
536         return rc;
537 }
538
539 static int ads_user_info(struct net_context *c, int argc, const char **argv)
540 {
541         ADS_STRUCT *ads = NULL;
542         ADS_STATUS rc;
543         LDAPMessage *res = NULL;
544         TALLOC_CTX *frame;
545         int ret = 0;
546         wbcErr wbc_status;
547         const char *attrs[] = {"memberOf", "primaryGroupID", NULL};
548         char *searchstring=NULL;
549         char **grouplist;
550         char *primary_group;
551         char *escaped_user;
552         struct dom_sid primary_group_sid;
553         uint32_t group_rid;
554         enum wbcSidType type;
555
556         if (argc < 1 || c->display_usage) {
557                 return net_ads_user_usage(c, argc, argv);
558         }
559
560         frame = talloc_new(talloc_tos());
561         if (frame == NULL) {
562                 return -1;
563         }
564
565         escaped_user = escape_ldap_string(frame, argv[0]);
566         if (!escaped_user) {
567                 d_fprintf(stderr,
568                           _("ads_user_info: failed to escape user %s\n"),
569                           argv[0]);
570                 return -1;
571         }
572
573         if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
574                 ret = -1;
575                 goto error;
576         }
577
578         if (asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user) == -1) {
579                 ret =-1;
580                 goto error;
581         }
582         rc = ads_search(ads, &res, searchstring, attrs);
583         SAFE_FREE(searchstring);
584
585         if (!ADS_ERR_OK(rc)) {
586                 d_fprintf(stderr, _("ads_search: %s\n"), ads_errstr(rc));
587                 ret = -1;
588                 goto error;
589         }
590
591         if (!ads_pull_uint32(ads, res, "primaryGroupID", &group_rid)) {
592                 d_fprintf(stderr, _("ads_pull_uint32 failed\n"));
593                 ret = -1;
594                 goto error;
595         }
596
597         rc = ads_domain_sid(ads, &primary_group_sid);
598         if (!ADS_ERR_OK(rc)) {
599                 d_fprintf(stderr, _("ads_domain_sid: %s\n"), ads_errstr(rc));
600                 ret = -1;
601                 goto error;
602         }
603
604         sid_append_rid(&primary_group_sid, group_rid);
605
606         wbc_status = wbcLookupSid((struct wbcDomainSid *)&primary_group_sid,
607                                   NULL, /* don't look up domain */
608                                   &primary_group,
609                                   &type);
610         if (!WBC_ERROR_IS_OK(wbc_status)) {
611                 d_fprintf(stderr, "wbcLookupSid: %s\n",
612                           wbcErrorString(wbc_status));
613                 ret = -1;
614                 goto error;
615         }
616
617         d_printf("%s\n", primary_group);
618
619         wbcFreeMemory(primary_group);
620
621         grouplist = ldap_get_values((LDAP *)ads->ldap.ld,
622                                     (LDAPMessage *)res, "memberOf");
623
624         if (grouplist) {
625                 int i;
626                 char **groupname;
627                 for (i=0;grouplist[i];i++) {
628                         groupname = ldap_explode_dn(grouplist[i], 1);
629                         d_printf("%s\n", groupname[0]);
630                         ldap_value_free(groupname);
631                 }
632                 ldap_value_free(grouplist);
633         }
634
635 error:
636         if (res) ads_msgfree(ads, res);
637         if (ads) ads_destroy(&ads);
638         TALLOC_FREE(frame);
639         return ret;
640 }
641
642 static int ads_user_delete(struct net_context *c, int argc, const char **argv)
643 {
644         ADS_STRUCT *ads;
645         ADS_STATUS rc;
646         LDAPMessage *res = NULL;
647         char *userdn;
648
649         if (argc < 1) {
650                 return net_ads_user_usage(c, argc, argv);
651         }
652
653         if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
654                 return -1;
655         }
656
657         rc = ads_find_user_acct(ads, &res, argv[0]);
658         if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) {
659                 d_printf(_("User %s does not exist.\n"), argv[0]);
660                 ads_msgfree(ads, res);
661                 ads_destroy(&ads);
662                 return -1;
663         }
664         userdn = ads_get_dn(ads, talloc_tos(), res);
665         ads_msgfree(ads, res);
666         rc = ads_del_dn(ads, userdn);
667         TALLOC_FREE(userdn);
668         if (ADS_ERR_OK(rc)) {
669                 d_printf(_("User %s deleted\n"), argv[0]);
670                 ads_destroy(&ads);
671                 return 0;
672         }
673         d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
674                  ads_errstr(rc));
675         ads_destroy(&ads);
676         return -1;
677 }
678
679 int net_ads_user(struct net_context *c, int argc, const char **argv)
680 {
681         struct functable func[] = {
682                 {
683                         "add",
684                         ads_user_add,
685                         NET_TRANSPORT_ADS,
686                         N_("Add an AD user"),
687                         N_("net ads user add\n"
688                            "    Add an AD user")
689                 },
690                 {
691                         "info",
692                         ads_user_info,
693                         NET_TRANSPORT_ADS,
694                         N_("Display information about an AD user"),
695                         N_("net ads user info\n"
696                            "    Display information about an AD user")
697                 },
698                 {
699                         "delete",
700                         ads_user_delete,
701                         NET_TRANSPORT_ADS,
702                         N_("Delete an AD user"),
703                         N_("net ads user delete\n"
704                            "    Delete an AD user")
705                 },
706                 {NULL, NULL, 0, NULL, NULL}
707         };
708         ADS_STRUCT *ads;
709         ADS_STATUS rc;
710         const char *shortattrs[] = {"sAMAccountName", NULL};
711         const char *longattrs[] = {"sAMAccountName", "description", NULL};
712         char *disp_fields[2] = {NULL, NULL};
713
714         if (argc == 0) {
715                 if (c->display_usage) {
716                         d_printf(  "%s\n"
717                                    "net ads user\n"
718                                    "    %s\n",
719                                  _("Usage:"),
720                                  _("List AD users"));
721                         net_display_usage_from_functable(func);
722                         return 0;
723                 }
724
725                 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
726                         return -1;
727                 }
728
729                 if (c->opt_long_list_entries)
730                         d_printf(_("\nUser name             Comment"
731                                    "\n-----------------------------\n"));
732
733                 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
734                                           LDAP_SCOPE_SUBTREE,
735                                           "(objectCategory=user)",
736                                           c->opt_long_list_entries ? longattrs :
737                                           shortattrs, usergrp_display,
738                                           disp_fields);
739                 ads_destroy(&ads);
740                 return ADS_ERR_OK(rc) ? 0 : -1;
741         }
742
743         return net_run_function(c, argc, argv, "net ads user", func);
744 }
745
746 static int net_ads_group_usage(struct net_context *c, int argc, const char **argv)
747 {
748         return net_group_usage(c, argc, argv);
749 }
750
751 static int ads_group_add(struct net_context *c, int argc, const char **argv)
752 {
753         ADS_STRUCT *ads;
754         ADS_STATUS status;
755         LDAPMessage *res=NULL;
756         int rc = -1;
757         char *ou_str = NULL;
758
759         if (argc < 1 || c->display_usage) {
760                 return net_ads_group_usage(c, argc, argv);
761         }
762
763         if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
764                 return -1;
765         }
766
767         status = ads_find_user_acct(ads, &res, argv[0]);
768
769         if (!ADS_ERR_OK(status)) {
770                 d_fprintf(stderr, _("ads_group_add: %s\n"), ads_errstr(status));
771                 goto done;
772         }
773
774         if (ads_count_replies(ads, res)) {
775                 d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]);
776                 goto done;
777         }
778
779         if (c->opt_container) {
780                 ou_str = SMB_STRDUP(c->opt_container);
781         } else {
782                 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
783         }
784
785         status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
786
787         if (ADS_ERR_OK(status)) {
788                 d_printf(_("Group %s added\n"), argv[0]);
789                 rc = 0;
790         } else {
791                 d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0],
792                          ads_errstr(status));
793         }
794
795  done:
796         if (res)
797                 ads_msgfree(ads, res);
798         ads_destroy(&ads);
799         SAFE_FREE(ou_str);
800         return rc;
801 }
802
803 static int ads_group_delete(struct net_context *c, int argc, const char **argv)
804 {
805         ADS_STRUCT *ads;
806         ADS_STATUS rc;
807         LDAPMessage *res = NULL;
808         char *groupdn;
809
810         if (argc < 1 || c->display_usage) {
811                 return net_ads_group_usage(c, argc, argv);
812         }
813
814         if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
815                 return -1;
816         }
817
818         rc = ads_find_user_acct(ads, &res, argv[0]);
819         if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) {
820                 d_printf(_("Group %s does not exist.\n"), argv[0]);
821                 ads_msgfree(ads, res);
822                 ads_destroy(&ads);
823                 return -1;
824         }
825         groupdn = ads_get_dn(ads, talloc_tos(), res);
826         ads_msgfree(ads, res);
827         rc = ads_del_dn(ads, groupdn);
828         TALLOC_FREE(groupdn);
829         if (ADS_ERR_OK(rc)) {
830                 d_printf(_("Group %s deleted\n"), argv[0]);
831                 ads_destroy(&ads);
832                 return 0;
833         }
834         d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
835                  ads_errstr(rc));
836         ads_destroy(&ads);
837         return -1;
838 }
839
840 int net_ads_group(struct net_context *c, int argc, const char **argv)
841 {
842         struct functable func[] = {
843                 {
844                         "add",
845                         ads_group_add,
846                         NET_TRANSPORT_ADS,
847                         N_("Add an AD group"),
848                         N_("net ads group add\n"
849                            "    Add an AD group")
850                 },
851                 {
852                         "delete",
853                         ads_group_delete,
854                         NET_TRANSPORT_ADS,
855                         N_("Delete an AD group"),
856                         N_("net ads group delete\n"
857                            "    Delete an AD group")
858                 },
859                 {NULL, NULL, 0, NULL, NULL}
860         };
861         ADS_STRUCT *ads;
862         ADS_STATUS rc;
863         const char *shortattrs[] = {"sAMAccountName", NULL};
864         const char *longattrs[] = {"sAMAccountName", "description", NULL};
865         char *disp_fields[2] = {NULL, NULL};
866
867         if (argc == 0) {
868                 if (c->display_usage) {
869                         d_printf(  "%s\n"
870                                    "net ads group\n"
871                                    "    %s\n",
872                                  _("Usage:"),
873                                  _("List AD groups"));
874                         net_display_usage_from_functable(func);
875                         return 0;
876                 }
877
878                 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
879                         return -1;
880                 }
881
882                 if (c->opt_long_list_entries)
883                         d_printf(_("\nGroup name            Comment"
884                                    "\n-----------------------------\n"));
885                 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
886                                           LDAP_SCOPE_SUBTREE,
887                                           "(objectCategory=group)",
888                                           c->opt_long_list_entries ? longattrs :
889                                           shortattrs, usergrp_display,
890                                           disp_fields);
891
892                 ads_destroy(&ads);
893                 return ADS_ERR_OK(rc) ? 0 : -1;
894         }
895         return net_run_function(c, argc, argv, "net ads group", func);
896 }
897
898 static int net_ads_status(struct net_context *c, int argc, const char **argv)
899 {
900         ADS_STRUCT *ads;
901         ADS_STATUS rc;
902         LDAPMessage *res;
903
904         if (c->display_usage) {
905                 d_printf(  "%s\n"
906                            "net ads status\n"
907                            "    %s\n",
908                          _("Usage:"),
909                          _("Display machine account details"));
910                 return 0;
911         }
912
913         if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
914                 return -1;
915         }
916
917         rc = ads_find_machine_acct(ads, &res, global_myname());
918         if (!ADS_ERR_OK(rc)) {
919                 d_fprintf(stderr, _("ads_find_machine_acct: %s\n"), ads_errstr(rc));
920                 ads_destroy(&ads);
921                 return -1;
922         }
923
924         if (ads_count_replies(ads, res) == 0) {
925                 d_fprintf(stderr, _("No machine account for '%s' found\n"), global_myname());
926                 ads_destroy(&ads);
927                 return -1;
928         }
929
930         ads_dump(ads, res);
931         ads_destroy(&ads);
932         return 0;
933 }
934
935 /*******************************************************************
936  Leave an AD domain.  Windows XP disables the machine account.
937  We'll try the same.  The old code would do an LDAP delete.
938  That only worked using the machine creds because added the machine
939  with full control to the computer object's ACL.
940 *******************************************************************/
941
942 static int net_ads_leave(struct net_context *c, int argc, const char **argv)
943 {
944         TALLOC_CTX *ctx;
945         struct libnet_UnjoinCtx *r = NULL;
946         WERROR werr;
947
948         if (c->display_usage) {
949                 d_printf(  "%s\n"
950                            "net ads leave\n"
951                            "    %s\n",
952                          _("Usage:"),
953                          _("Leave an AD domain"));
954                 return 0;
955         }
956
957         if (!*lp_realm()) {
958                 d_fprintf(stderr, _("No realm set, are we joined ?\n"));
959                 return -1;
960         }
961
962         if (!(ctx = talloc_init("net_ads_leave"))) {
963                 d_fprintf(stderr, _("Could not initialise talloc context.\n"));
964                 return -1;
965         }
966
967         if (!c->opt_kerberos) {
968                 use_in_memory_ccache();
969         }
970
971         if (!c->msg_ctx) {
972                 d_fprintf(stderr, _("Could not initialise message context. "
973                         "Try running as root\n"));
974                 return -1;
975         }
976
977         werr = libnet_init_UnjoinCtx(ctx, &r);
978         if (!W_ERROR_IS_OK(werr)) {
979                 d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
980                 return -1;
981         }
982
983         r->in.debug             = true;
984         r->in.use_kerberos      = c->opt_kerberos;
985         r->in.dc_name           = c->opt_host;
986         r->in.domain_name       = lp_realm();
987         r->in.admin_account     = c->opt_user_name;
988         r->in.admin_password    = net_prompt_pass(c, c->opt_user_name);
989         r->in.modify_config     = lp_config_backend_is_registry();
990
991         /* Try to delete it, but if that fails, disable it.  The
992            WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
993         r->in.unjoin_flags      = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
994                                   WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
995         r->in.delete_machine_account = true;
996         r->in.msg_ctx           = c->msg_ctx;
997
998         werr = libnet_Unjoin(ctx, r);
999         if (!W_ERROR_IS_OK(werr)) {
1000                 d_printf(_("Failed to leave domain: %s\n"),
1001                          r->out.error_string ? r->out.error_string :
1002                          get_friendly_werror_msg(werr));
1003                 goto done;
1004         }
1005
1006         if (r->out.deleted_machine_account) {
1007                 d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1008                         r->in.machine_name, r->out.dns_domain_name);
1009                 goto done;
1010         }
1011
1012         /* We couldn't delete it - see if the disable succeeded. */
1013         if (r->out.disabled_machine_account) {
1014                 d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1015                         r->in.machine_name, r->out.dns_domain_name);
1016                 werr = WERR_OK;
1017                 goto done;
1018         }
1019
1020         /* Based on what we requseted, we shouldn't get here, but if
1021            we did, it means the secrets were removed, and therefore
1022            we have left the domain */
1023         d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"),
1024                   r->in.machine_name, r->out.dns_domain_name);
1025
1026  done:
1027         TALLOC_FREE(r);
1028         TALLOC_FREE(ctx);
1029
1030         if (W_ERROR_IS_OK(werr)) {
1031                 return 0;
1032         }
1033
1034         return -1;
1035 }
1036
1037 static NTSTATUS net_ads_join_ok(struct net_context *c)
1038 {
1039         ADS_STRUCT *ads = NULL;
1040         ADS_STATUS status;
1041         fstring dc_name;
1042         struct sockaddr_storage dcip;
1043
1044         if (!secrets_init()) {
1045                 DEBUG(1,("Failed to initialise secrets database\n"));
1046                 return NT_STATUS_ACCESS_DENIED;
1047         }
1048
1049         net_use_krb_machine_account(c);
1050
1051         get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
1052
1053         status = ads_startup(c, true, &ads);
1054         if (!ADS_ERR_OK(status)) {
1055                 return ads_ntstatus(status);
1056         }
1057
1058         ads_destroy(&ads);
1059         return NT_STATUS_OK;
1060 }
1061
1062 /*
1063   check that an existing join is OK
1064  */
1065 int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
1066 {
1067         NTSTATUS status;
1068         use_in_memory_ccache();
1069
1070         if (c->display_usage) {
1071                 d_printf(  "%s\n"
1072                            "net ads testjoin\n"
1073                            "    %s\n",
1074                          _("Usage:"),
1075                          _("Test if the existing join is ok"));
1076                 return 0;
1077         }
1078
1079         /* Display success or failure */
1080         status = net_ads_join_ok(c);
1081         if (!NT_STATUS_IS_OK(status)) {
1082                 fprintf(stderr, _("Join to domain is not valid: %s\n"),
1083                         get_friendly_nt_error_msg(status));
1084                 return -1;
1085         }
1086
1087         printf(_("Join is OK\n"));
1088         return 0;
1089 }
1090
1091 /*******************************************************************
1092   Simple configu checks before beginning the join
1093  ********************************************************************/
1094
1095 static WERROR check_ads_config( void )
1096 {
1097         if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
1098                 d_printf(_("Host is not configured as a member server.\n"));
1099                 return WERR_INVALID_DOMAIN_ROLE;
1100         }
1101
1102         if (strlen(global_myname()) > 15) {
1103                 d_printf(_("Our netbios name can be at most 15 chars long, "
1104                            "\"%s\" is %u chars long\n"), global_myname(),
1105                          (unsigned int)strlen(global_myname()));
1106                 return WERR_INVALID_COMPUTERNAME;
1107         }
1108
1109         if ( lp_security() == SEC_ADS && !*lp_realm()) {
1110                 d_fprintf(stderr, _("realm must be set in in %s for ADS "
1111                           "join to succeed.\n"), get_dyn_CONFIGFILE());
1112                 return WERR_INVALID_PARAM;
1113         }
1114
1115         return WERR_OK;
1116 }
1117
1118 /*******************************************************************
1119  Send a DNS update request
1120 *******************************************************************/
1121
1122 #if defined(WITH_DNS_UPDATES)
1123 #include "dns.h"
1124 DNS_ERROR DoDNSUpdate(char *pszServerName,
1125                       const char *pszDomainName, const char *pszHostName,
1126                       const struct sockaddr_storage *sslist,
1127                       size_t num_addrs );
1128
1129 static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads,
1130                                         const char *machine_name,
1131                                         const struct sockaddr_storage *addrs,
1132                                         int num_addrs)
1133 {
1134         struct dns_rr_ns *nameservers = NULL;
1135         int ns_count = 0;
1136         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1137         DNS_ERROR dns_err;
1138         fstring dns_server;
1139         const char *dnsdomain = NULL;
1140         char *root_domain = NULL;
1141
1142         if ( (dnsdomain = strchr_m( machine_name, '.')) == NULL ) {
1143                 d_printf(_("No DNS domain configured for %s. "
1144                            "Unable to perform DNS Update.\n"), machine_name);
1145                 status = NT_STATUS_INVALID_PARAMETER;
1146                 goto done;
1147         }
1148         dnsdomain++;
1149
1150         status = ads_dns_lookup_ns( ctx, dnsdomain, &nameservers, &ns_count );
1151         if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
1152                 /* Child domains often do not have NS records.  Look
1153                    for the NS record for the forest root domain
1154                    (rootDomainNamingContext in therootDSE) */
1155
1156                 const char *rootname_attrs[] =  { "rootDomainNamingContext", NULL };
1157                 LDAPMessage *msg = NULL;
1158                 char *root_dn;
1159                 ADS_STATUS ads_status;
1160
1161                 if ( !ads->ldap.ld ) {
1162                         ads_status = ads_connect( ads );
1163                         if ( !ADS_ERR_OK(ads_status) ) {
1164                                 DEBUG(0,("net_update_dns_internal: Failed to connect to our DC!\n"));
1165                                 goto done;
1166                         }
1167                 }
1168
1169                 ads_status = ads_do_search(ads, "", LDAP_SCOPE_BASE,
1170                                        "(objectclass=*)", rootname_attrs, &msg);
1171                 if (!ADS_ERR_OK(ads_status)) {
1172                         goto done;
1173                 }
1174
1175                 root_dn = ads_pull_string(ads, ctx, msg,  "rootDomainNamingContext");
1176                 if ( !root_dn ) {
1177                         ads_msgfree( ads, msg );
1178                         goto done;
1179                 }
1180
1181                 root_domain = ads_build_domain( root_dn );
1182
1183                 /* cleanup */
1184                 ads_msgfree( ads, msg );
1185
1186                 /* try again for NS servers */
1187
1188                 status = ads_dns_lookup_ns( ctx, root_domain, &nameservers, &ns_count );
1189
1190                 if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
1191                         DEBUG(3,("net_ads_join: Failed to find name server for the %s "
1192                          "realm\n", ads->config.realm));
1193                         goto done;
1194                 }
1195
1196                 dnsdomain = root_domain;
1197
1198         }
1199
1200         /* Now perform the dns update - we'll try non-secure and if we fail,
1201            we'll follow it up with a secure update */
1202
1203         fstrcpy( dns_server, nameservers[0].hostname );
1204
1205         dns_err = DoDNSUpdate(dns_server, dnsdomain, machine_name, addrs, num_addrs);
1206         if (!ERR_DNS_IS_OK(dns_err)) {
1207                 d_printf(_("DNS Update for %s failed: %s\n"),
1208                         machine_name, dns_errstr(dns_err));
1209                 status = NT_STATUS_UNSUCCESSFUL;
1210         }
1211
1212 done:
1213
1214         SAFE_FREE( root_domain );
1215
1216         return status;
1217 }
1218
1219 static NTSTATUS net_update_dns(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads, const char *hostname)
1220 {
1221         int num_addrs;
1222         struct sockaddr_storage *iplist = NULL;
1223         fstring machine_name;
1224         NTSTATUS status;
1225
1226         if (hostname) {
1227                 fstrcpy(machine_name, hostname);
1228         } else {
1229                 name_to_fqdn( machine_name, global_myname() );
1230         }
1231         strlower_m( machine_name );
1232
1233         /* Get our ip address (not the 127.0.0.x address but a real ip
1234          * address) */
1235
1236         num_addrs = get_my_ip_address( &iplist );
1237         if ( num_addrs <= 0 ) {
1238                 DEBUG(4,("net_update_dns: Failed to find my non-loopback IP "
1239                          "addresses!\n"));
1240                 return NT_STATUS_INVALID_PARAMETER;
1241         }
1242
1243         status = net_update_dns_internal(mem_ctx, ads, machine_name,
1244                                          iplist, num_addrs);
1245         SAFE_FREE( iplist );
1246         return status;
1247 }
1248 #endif
1249
1250
1251 /*******************************************************************
1252  ********************************************************************/
1253
1254 static int net_ads_join_usage(struct net_context *c, int argc, const char **argv)
1255 {
1256         d_printf(_("net ads join [options]\n"
1257                    "Valid options:\n"));
1258         d_printf(_("   createupn[=UPN]    Set the userPrincipalName attribute during the join.\n"
1259                    "                      The deault UPN is in the form host/netbiosname@REALM.\n"));
1260         d_printf(_("   createcomputer=OU  Precreate the computer account in a specific OU.\n"
1261                    "                      The OU string read from top to bottom without RDNs and delimited by a '/'.\n"
1262                    "                      E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1263                    "                      NB: A backslash '\\' is used as escape at multiple levels and may\n"
1264                    "                          need to be doubled or even quadrupled.  It is not used as a separator.\n"));
1265         d_printf(_("   osName=string      Set the operatingSystem attribute during the join.\n"));
1266         d_printf(_("   osVer=string       Set the operatingSystemVersion attribute during the join.\n"
1267                    "                      NB: osName and osVer must be specified together for either to take effect.\n"
1268                    "                          Also, the operatingSystemService attribute is also set when along with\n"
1269                    "                          the two other attributes.\n"));
1270
1271         return -1;
1272 }
1273
1274 /*******************************************************************
1275  ********************************************************************/
1276
1277 int net_ads_join(struct net_context *c, int argc, const char **argv)
1278 {
1279         TALLOC_CTX *ctx = NULL;
1280         struct libnet_JoinCtx *r = NULL;
1281         const char *domain = lp_realm();
1282         WERROR werr = WERR_SETUP_NOT_JOINED;
1283         bool createupn = false;
1284         const char *machineupn = NULL;
1285         const char *create_in_ou = NULL;
1286         int i;
1287         const char *os_name = NULL;
1288         const char *os_version = NULL;
1289         bool modify_config = lp_config_backend_is_registry();
1290
1291         if (c->display_usage)
1292                 return net_ads_join_usage(c, argc, argv);
1293
1294         if (!modify_config) {
1295
1296                 werr = check_ads_config();
1297                 if (!W_ERROR_IS_OK(werr)) {
1298                         d_fprintf(stderr, _("Invalid configuration.  Exiting....\n"));
1299                         goto fail;
1300                 }
1301         }
1302
1303         if (!(ctx = talloc_init("net_ads_join"))) {
1304                 d_fprintf(stderr, _("Could not initialise talloc context.\n"));
1305                 werr = WERR_NOMEM;
1306                 goto fail;
1307         }
1308
1309         if (!c->opt_kerberos) {
1310                 use_in_memory_ccache();
1311         }
1312
1313         werr = libnet_init_JoinCtx(ctx, &r);
1314         if (!W_ERROR_IS_OK(werr)) {
1315                 goto fail;
1316         }
1317
1318         /* process additional command line args */
1319
1320         for ( i=0; i<argc; i++ ) {
1321                 if ( !StrnCaseCmp(argv[i], "createupn", strlen("createupn")) ) {
1322                         createupn = true;
1323                         machineupn = get_string_param(argv[i]);
1324                 }
1325                 else if ( !StrnCaseCmp(argv[i], "createcomputer", strlen("createcomputer")) ) {
1326                         if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
1327                                 d_fprintf(stderr, _("Please supply a valid OU path.\n"));
1328                                 werr = WERR_INVALID_PARAM;
1329                                 goto fail;
1330                         }
1331                 }
1332                 else if ( !StrnCaseCmp(argv[i], "osName", strlen("osName")) ) {
1333                         if ( (os_name = get_string_param(argv[i])) == NULL ) {
1334                                 d_fprintf(stderr, _("Please supply a operating system name.\n"));
1335                                 werr = WERR_INVALID_PARAM;
1336                                 goto fail;
1337                         }
1338                 }
1339                 else if ( !StrnCaseCmp(argv[i], "osVer", strlen("osVer")) ) {
1340                         if ( (os_version = get_string_param(argv[i])) == NULL ) {
1341                                 d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
1342                                 werr = WERR_INVALID_PARAM;
1343                                 goto fail;
1344                         }
1345                 }
1346                 else {
1347                         domain = argv[i];
1348                 }
1349         }
1350
1351         if (!*domain) {
1352                 d_fprintf(stderr, _("Please supply a valid domain name\n"));
1353                 werr = WERR_INVALID_PARAM;
1354                 goto fail;
1355         }
1356
1357         if (!c->msg_ctx) {
1358                 d_fprintf(stderr, _("Could not initialise message context. "
1359                         "Try running as root\n"));
1360                 werr = WERR_ACCESS_DENIED;
1361                 goto fail;
1362         }
1363
1364         /* Do the domain join here */
1365
1366         r->in.domain_name       = domain;
1367         r->in.create_upn        = createupn;
1368         r->in.upn               = machineupn;
1369         r->in.account_ou        = create_in_ou;
1370         r->in.os_name           = os_name;
1371         r->in.os_version        = os_version;
1372         r->in.dc_name           = c->opt_host;
1373         r->in.admin_account     = c->opt_user_name;
1374         r->in.admin_password    = net_prompt_pass(c, c->opt_user_name);
1375         r->in.debug             = true;
1376         r->in.use_kerberos      = c->opt_kerberos;
1377         r->in.modify_config     = modify_config;
1378         r->in.join_flags        = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1379                                   WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
1380                                   WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
1381         r->in.msg_ctx           = c->msg_ctx;
1382
1383         werr = libnet_Join(ctx, r);
1384         if (!W_ERROR_IS_OK(werr)) {
1385                 goto fail;
1386         }
1387
1388         /* Check the short name of the domain */
1389
1390         if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
1391                 d_printf(_("The workgroup in %s does not match the short\n"
1392                            "domain name obtained from the server.\n"
1393                            "Using the name [%s] from the server.\n"
1394                            "You should set \"workgroup = %s\" in %s.\n"),
1395                          get_dyn_CONFIGFILE(), r->out.netbios_domain_name,
1396                          r->out.netbios_domain_name, get_dyn_CONFIGFILE());
1397         }
1398
1399         d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name);
1400
1401         if (r->out.dns_domain_name) {
1402                 d_printf(_("Joined '%s' to realm '%s'\n"), r->in.machine_name,
1403                         r->out.dns_domain_name);
1404         } else {
1405                 d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name,
1406                         r->out.netbios_domain_name);
1407         }
1408
1409 #if defined(WITH_DNS_UPDATES)
1410         /*
1411          * In a clustered environment, don't do dynamic dns updates:
1412          * Registering the set of ip addresses that are assigned to
1413          * the interfaces of the node that performs the join does usually
1414          * not have the desired effect, since the local interfaces do not
1415          * carry the complete set of the cluster's public IP addresses.
1416          * And it can also contain internal addresses that should not
1417          * be visible to the outside at all.
1418          * In order to do dns updates in a clustererd setup, use
1419          * net ads dns register.
1420          */
1421         if (lp_clustering()) {
1422                 d_fprintf(stderr, _("Not doing automatic DNS update in a"
1423                                     "clustered setup.\n"));
1424                 goto done;
1425         }
1426
1427         if (r->out.domain_is_ad) {
1428                 /* We enter this block with user creds */
1429                 ADS_STRUCT *ads_dns = NULL;
1430
1431                 if ( (ads_dns = ads_init( lp_realm(), NULL, NULL )) != NULL ) {
1432                         /* kinit with the machine password */
1433
1434                         use_in_memory_ccache();
1435                         if (asprintf( &ads_dns->auth.user_name, "%s$", global_myname()) == -1) {
1436                                 goto fail;
1437                         }
1438                         ads_dns->auth.password = secrets_fetch_machine_password(
1439                                 r->out.netbios_domain_name, NULL, NULL );
1440                         ads_dns->auth.realm = SMB_STRDUP( r->out.dns_domain_name );
1441                         strupper_m(ads_dns->auth.realm );
1442                         ads_kinit_password( ads_dns );
1443                 }
1444
1445                 if ( !ads_dns || !NT_STATUS_IS_OK(net_update_dns( ctx, ads_dns, NULL)) ) {
1446                         d_fprintf( stderr, _("DNS update failed!\n") );
1447                 }
1448
1449                 /* exit from this block using machine creds */
1450                 ads_destroy(&ads_dns);
1451         }
1452 #endif
1453
1454 done:
1455         TALLOC_FREE(r);
1456         TALLOC_FREE( ctx );
1457
1458         return 0;
1459
1460 fail:
1461         /* issue an overall failure message at the end. */
1462         d_printf(_("Failed to join domain: %s\n"),
1463                 r && r->out.error_string ? r->out.error_string :
1464                 get_friendly_werror_msg(werr));
1465         TALLOC_FREE( ctx );
1466
1467         return -1;
1468 }
1469
1470 /*******************************************************************
1471  ********************************************************************/
1472
1473 static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
1474 {
1475 #if defined(WITH_DNS_UPDATES)
1476         ADS_STRUCT *ads;
1477         ADS_STATUS status;
1478         TALLOC_CTX *ctx;
1479
1480 #ifdef DEVELOPER
1481         talloc_enable_leak_report();
1482 #endif
1483
1484         if (argc > 1 || c->display_usage) {
1485                 d_printf(  "%s\n"
1486                            "net ads dns register [hostname]\n"
1487                            "    %s\n",
1488                          _("Usage:"),
1489                          _("Register hostname with DNS\n"));
1490                 return -1;
1491         }
1492
1493         if (!(ctx = talloc_init("net_ads_dns"))) {
1494                 d_fprintf(stderr, _("Could not initialise talloc context\n"));
1495                 return -1;
1496         }
1497
1498         status = ads_startup(c, true, &ads);
1499         if ( !ADS_ERR_OK(status) ) {
1500                 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1501                 TALLOC_FREE(ctx);
1502                 return -1;
1503         }
1504
1505         if ( !NT_STATUS_IS_OK(net_update_dns(ctx, ads, argc == 1 ? argv[0] : NULL)) ) {
1506                 d_fprintf( stderr, _("DNS update failed!\n") );
1507                 ads_destroy( &ads );
1508                 TALLOC_FREE( ctx );
1509                 return -1;
1510         }
1511
1512         d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
1513
1514         ads_destroy(&ads);
1515         TALLOC_FREE( ctx );
1516
1517         return 0;
1518 #else
1519         d_fprintf(stderr,
1520                   _("DNS update support not enabled at compile time!\n"));
1521         return -1;
1522 #endif
1523 }
1524
1525 #if defined(WITH_DNS_UPDATES)
1526 DNS_ERROR do_gethostbyname(const char *server, const char *host);
1527 #endif
1528
1529 static int net_ads_dns_gethostbyname(struct net_context *c, int argc, const char **argv)
1530 {
1531 #if defined(WITH_DNS_UPDATES)
1532         DNS_ERROR err;
1533
1534 #ifdef DEVELOPER
1535         talloc_enable_leak_report();
1536 #endif
1537
1538         if (argc != 2 || c->display_usage) {
1539                 d_printf(  "%s\n"
1540                            "    %s\n"
1541                            "    %s\n",
1542                          _("Usage:"),
1543                          _("net ads dns gethostbyname <server> <name>\n"),
1544                          _("  Look up hostname from the AD\n"
1545                            "    server\tName server to use\n"
1546                            "    name\tName to look up\n"));
1547                 return -1;
1548         }
1549
1550         err = do_gethostbyname(argv[0], argv[1]);
1551
1552         d_printf(_("do_gethostbyname returned %s (%d)\n"),
1553                 dns_errstr(err), ERROR_DNS_V(err));
1554 #endif
1555         return 0;
1556 }
1557
1558 static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
1559 {
1560         struct functable func[] = {
1561                 {
1562                         "register",
1563                         net_ads_dns_register,
1564                         NET_TRANSPORT_ADS,
1565                         N_("Add host dns entry to AD"),
1566                         N_("net ads dns register\n"
1567                            "    Add host dns entry to AD")
1568                 },
1569                 {
1570                         "gethostbyname",
1571                         net_ads_dns_gethostbyname,
1572                         NET_TRANSPORT_ADS,
1573                         N_("Look up host"),
1574                         N_("net ads dns gethostbyname\n"
1575                            "    Look up host")
1576                 },
1577                 {NULL, NULL, 0, NULL, NULL}
1578         };
1579
1580         return net_run_function(c, argc, argv, "net ads dns", func);
1581 }
1582
1583 /*******************************************************************
1584  ********************************************************************/
1585
1586 int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
1587 {
1588         d_printf(_(
1589 "\nnet ads printer search <printer>"
1590 "\n\tsearch for a printer in the directory\n"
1591 "\nnet ads printer info <printer> <server>"
1592 "\n\tlookup info in directory for printer on server"
1593 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
1594 "\nnet ads printer publish <printername>"
1595 "\n\tpublish printer in directory"
1596 "\n\t(note: printer name is required)\n"
1597 "\nnet ads printer remove <printername>"
1598 "\n\tremove printer from directory"
1599 "\n\t(note: printer name is required)\n"));
1600         return -1;
1601 }
1602
1603 /*******************************************************************
1604  ********************************************************************/
1605
1606 static int net_ads_printer_search(struct net_context *c, int argc, const char **argv)
1607 {
1608         ADS_STRUCT *ads;
1609         ADS_STATUS rc;
1610         LDAPMessage *res = NULL;
1611
1612         if (c->display_usage) {
1613                 d_printf(  "%s\n"
1614                            "net ads printer search\n"
1615                            "    %s\n",
1616                          _("Usage:"),
1617                          _("List printers in the AD"));
1618                 return 0;
1619         }
1620
1621         if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
1622                 return -1;
1623         }
1624
1625         rc = ads_find_printers(ads, &res);
1626
1627         if (!ADS_ERR_OK(rc)) {
1628                 d_fprintf(stderr, _("ads_find_printer: %s\n"), ads_errstr(rc));
1629                 ads_msgfree(ads, res);
1630                 ads_destroy(&ads);
1631                 return -1;
1632         }
1633
1634         if (ads_count_replies(ads, res) == 0) {
1635                 d_fprintf(stderr, _("No results found\n"));
1636                 ads_msgfree(ads, res);
1637                 ads_destroy(&ads);
1638                 return -1;
1639         }
1640
1641         ads_dump(ads, res);
1642         ads_msgfree(ads, res);
1643         ads_destroy(&ads);
1644         return 0;
1645 }
1646
1647 static int net_ads_printer_info(struct net_context *c, int argc, const char **argv)
1648 {
1649         ADS_STRUCT *ads;
1650         ADS_STATUS rc;
1651         const char *servername, *printername;
1652         LDAPMessage *res = NULL;
1653
1654         if (c->display_usage) {
1655                 d_printf("%s\n%s",
1656                          _("Usage:"),
1657                          _("net ads printer info [printername [servername]]\n"
1658                            "  Display printer info from AD\n"
1659                            "    printername\tPrinter name or wildcard\n"
1660                            "    servername\tName of the print server\n"));
1661                 return 0;
1662         }
1663
1664         if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
1665                 return -1;
1666         }
1667
1668         if (argc > 0) {
1669                 printername = argv[0];
1670         } else {
1671                 printername = "*";
1672         }
1673
1674         if (argc > 1) {
1675                 servername =  argv[1];
1676         } else {
1677                 servername = global_myname();
1678         }
1679
1680         rc = ads_find_printer_on_server(ads, &res, printername, servername);
1681
1682         if (!ADS_ERR_OK(rc)) {
1683                 d_fprintf(stderr, _("Server '%s' not found: %s\n"),
1684                         servername, ads_errstr(rc));
1685                 ads_msgfree(ads, res);
1686                 ads_destroy(&ads);
1687                 return -1;
1688         }
1689
1690         if (ads_count_replies(ads, res) == 0) {
1691                 d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
1692                 ads_msgfree(ads, res);
1693                 ads_destroy(&ads);
1694                 return -1;
1695         }
1696
1697         ads_dump(ads, res);
1698         ads_msgfree(ads, res);
1699         ads_destroy(&ads);
1700
1701         return 0;
1702 }
1703
1704 static int net_ads_printer_publish(struct net_context *c, int argc, const char **argv)
1705 {
1706         ADS_STRUCT *ads;
1707         ADS_STATUS rc;
1708         const char *servername, *printername;
1709         struct cli_state *cli = NULL;
1710         struct rpc_pipe_client *pipe_hnd = NULL;
1711         struct sockaddr_storage server_ss;
1712         NTSTATUS nt_status;
1713         TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
1714         ADS_MODLIST mods = ads_init_mods(mem_ctx);
1715         char *prt_dn, *srv_dn, **srv_cn;
1716         char *srv_cn_escaped = NULL, *printername_escaped = NULL;
1717         LDAPMessage *res = NULL;
1718
1719         if (argc < 1 || c->display_usage) {
1720                 d_printf("%s\n%s",
1721                          _("Usage:"),
1722                          _("net ads printer publish <printername> [servername]\n"
1723                            "  Publish printer in AD\n"
1724                            "    printername\tName of the printer\n"
1725                            "    servername\tName of the print server\n"));
1726                 talloc_destroy(mem_ctx);
1727                 return -1;
1728         }
1729
1730         if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
1731                 talloc_destroy(mem_ctx);
1732                 return -1;
1733         }
1734
1735         printername = argv[0];
1736
1737         if (argc == 2) {
1738                 servername = argv[1];
1739         } else {
1740                 servername = global_myname();
1741         }
1742
1743         /* Get printer data from SPOOLSS */
1744
1745         resolve_name(servername, &server_ss, 0x20, false);
1746
1747         nt_status = cli_full_connection(&cli, global_myname(), servername,
1748                                         &server_ss, 0,
1749                                         "IPC$", "IPC",
1750                                         c->opt_user_name, c->opt_workgroup,
1751                                         c->opt_password ? c->opt_password : "",
1752                                         CLI_FULL_CONNECTION_USE_KERBEROS,
1753                                         Undefined, NULL);
1754
1755         if (NT_STATUS_IS_ERR(nt_status)) {
1756                 d_fprintf(stderr, _("Unable to open a connnection to %s to "
1757                                     "obtain data for %s\n"),
1758                           servername, printername);
1759                 ads_destroy(&ads);
1760                 talloc_destroy(mem_ctx);
1761                 return -1;
1762         }
1763
1764         /* Publish on AD server */
1765
1766         ads_find_machine_acct(ads, &res, servername);
1767
1768         if (ads_count_replies(ads, res) == 0) {
1769                 d_fprintf(stderr, _("Could not find machine account for server "
1770                                     "%s\n"),
1771                          servername);
1772                 ads_destroy(&ads);
1773                 talloc_destroy(mem_ctx);
1774                 return -1;
1775         }
1776
1777         srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
1778         srv_cn = ldap_explode_dn(srv_dn, 1);
1779
1780         srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
1781         printername_escaped = escape_rdn_val_string_alloc(printername);
1782         if (!srv_cn_escaped || !printername_escaped) {
1783                 SAFE_FREE(srv_cn_escaped);
1784                 SAFE_FREE(printername_escaped);
1785                 d_fprintf(stderr, _("Internal error, out of memory!"));
1786                 ads_destroy(&ads);
1787                 talloc_destroy(mem_ctx);
1788                 return -1;
1789         }
1790
1791         if (asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, printername_escaped, srv_dn) == -1) {
1792                 SAFE_FREE(srv_cn_escaped);
1793                 SAFE_FREE(printername_escaped);
1794                 d_fprintf(stderr, _("Internal error, out of memory!"));
1795                 ads_destroy(&ads);
1796                 talloc_destroy(mem_ctx);
1797                 return -1;
1798         }
1799
1800         SAFE_FREE(srv_cn_escaped);
1801         SAFE_FREE(printername_escaped);
1802
1803         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss.syntax_id, &pipe_hnd);
1804         if (!NT_STATUS_IS_OK(nt_status)) {
1805                 d_fprintf(stderr, _("Unable to open a connnection to the spoolss pipe on %s\n"),
1806                          servername);
1807                 SAFE_FREE(prt_dn);
1808                 ads_destroy(&ads);
1809                 talloc_destroy(mem_ctx);
1810                 return -1;
1811         }
1812
1813         if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
1814                                                               printername))) {
1815                 SAFE_FREE(prt_dn);
1816                 ads_destroy(&ads);
1817                 talloc_destroy(mem_ctx);
1818                 return -1;
1819         }
1820
1821         rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
1822         if (!ADS_ERR_OK(rc)) {
1823                 d_fprintf(stderr, "ads_publish_printer: %s\n", ads_errstr(rc));
1824                 SAFE_FREE(prt_dn);
1825                 ads_destroy(&ads);
1826                 talloc_destroy(mem_ctx);
1827                 return -1;
1828         }
1829
1830         d_printf("published printer\n");
1831         SAFE_FREE(prt_dn);
1832         ads_destroy(&ads);
1833         talloc_destroy(mem_ctx);
1834
1835         return 0;
1836 }
1837
1838 static int net_ads_printer_remove(struct net_context *c, int argc, const char **argv)
1839 {
1840         ADS_STRUCT *ads;
1841         ADS_STATUS rc;
1842         const char *servername;
1843         char *prt_dn;
1844         LDAPMessage *res = NULL;
1845
1846         if (argc < 1 || c->display_usage) {
1847                 d_printf("%s\n%s",
1848                          _("Usage:"),
1849                          _("net ads printer remove <printername> [servername]\n"
1850                            "  Remove a printer from the AD\n"
1851                            "    printername\tName of the printer\n"
1852                            "    servername\tName of the print server\n"));
1853                 return -1;
1854         }
1855
1856         if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
1857                 return -1;
1858         }
1859
1860         if (argc > 1) {
1861                 servername = argv[1];
1862         } else {
1863                 servername = global_myname();
1864         }
1865
1866         rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
1867
1868         if (!ADS_ERR_OK(rc)) {
1869                 d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"), ads_errstr(rc));
1870                 ads_msgfree(ads, res);
1871                 ads_destroy(&ads);
1872                 return -1;
1873         }
1874
1875         if (ads_count_replies(ads, res) == 0) {
1876                 d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
1877                 ads_msgfree(ads, res);
1878                 ads_destroy(&ads);
1879                 return -1;
1880         }
1881
1882         prt_dn = ads_get_dn(ads, talloc_tos(), res);
1883         ads_msgfree(ads, res);
1884         rc = ads_del_dn(ads, prt_dn);
1885         TALLOC_FREE(prt_dn);
1886
1887         if (!ADS_ERR_OK(rc)) {
1888                 d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(rc));
1889                 ads_destroy(&ads);
1890                 return -1;
1891         }
1892
1893         ads_destroy(&ads);
1894         return 0;
1895 }
1896
1897 static int net_ads_printer(struct net_context *c, int argc, const char **argv)
1898 {
1899         struct functable func[] = {
1900                 {
1901                         "search",
1902                         net_ads_printer_search,
1903                         NET_TRANSPORT_ADS,
1904                         N_("Search for a printer"),
1905                         N_("net ads printer search\n"
1906                            "    Search for a printer")
1907                 },
1908                 {
1909                         "info",
1910                         net_ads_printer_info,
1911                         NET_TRANSPORT_ADS,
1912                         N_("Display printer information"),
1913                         N_("net ads printer info\n"
1914                            "    Display printer information")
1915                 },
1916                 {
1917                         "publish",
1918                         net_ads_printer_publish,
1919                         NET_TRANSPORT_ADS,
1920                         N_("Publish a printer"),
1921                         N_("net ads printer publish\n"
1922                            "    Publish a printer")
1923                 },
1924                 {
1925                         "remove",
1926                         net_ads_printer_remove,
1927                         NET_TRANSPORT_ADS,
1928                         N_("Delete a printer"),
1929                         N_("net ads printer remove\n"
1930                            "    Delete a printer")
1931                 },
1932                 {NULL, NULL, 0, NULL, NULL}
1933         };
1934
1935         return net_run_function(c, argc, argv, "net ads printer", func);
1936 }
1937
1938
1939 static int net_ads_password(struct net_context *c, int argc, const char **argv)
1940 {
1941         ADS_STRUCT *ads;
1942         const char *auth_principal = c->opt_user_name;
1943         const char *auth_password = c->opt_password;
1944         char *realm = NULL;
1945         char *new_password = NULL;
1946         char *chr, *prompt;
1947         const char *user;
1948         ADS_STATUS ret;
1949
1950         if (c->display_usage) {
1951                 d_printf("%s\n%s",
1952                          _("Usage:"),
1953                          _("net ads password <username>\n"
1954                            "  Change password for user\n"
1955                            "    username\tName of user to change password for\n"));
1956                 return 0;
1957         }
1958
1959         if (c->opt_user_name == NULL || c->opt_password == NULL) {
1960                 d_fprintf(stderr, _("You must supply an administrator "
1961                                     "username/password\n"));
1962                 return -1;
1963         }
1964
1965         if (argc < 1) {
1966                 d_fprintf(stderr, _("ERROR: You must say which username to "
1967                                     "change password for\n"));
1968                 return -1;
1969         }
1970
1971         user = argv[0];
1972         if (!strchr_m(user, '@')) {
1973                 if (asprintf(&chr, "%s@%s", argv[0], lp_realm()) == -1) {
1974                         return -1;
1975                 }
1976                 user = chr;
1977         }
1978
1979         use_in_memory_ccache();
1980         chr = strchr_m(auth_principal, '@');
1981         if (chr) {
1982                 realm = ++chr;
1983         } else {
1984                 realm = lp_realm();
1985         }
1986
1987         /* use the realm so we can eventually change passwords for users
1988         in realms other than default */
1989         if (!(ads = ads_init(realm, c->opt_workgroup, c->opt_host))) {
1990                 return -1;
1991         }
1992
1993         /* we don't actually need a full connect, but it's the easy way to
1994                 fill in the KDC's addresss */
1995         ads_connect(ads);
1996
1997         if (!ads->config.realm) {
1998                 d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
1999                 ads_destroy(&ads);
2000                 return -1;
2001         }
2002
2003         if (argv[1]) {
2004                 new_password = (char *)argv[1];
2005         } else {
2006                 if (asprintf(&prompt, _("Enter new password for %s:"), user) == -1) {
2007                         return -1;
2008                 }
2009                 new_password = getpass(prompt);
2010                 free(prompt);
2011         }
2012
2013         ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
2014                                 auth_password, user, new_password, ads->auth.time_offset);
2015         if (!ADS_ERR_OK(ret)) {
2016                 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
2017                 ads_destroy(&ads);
2018                 return -1;
2019         }
2020
2021         d_printf(_("Password change for %s completed.\n"), user);
2022         ads_destroy(&ads);
2023
2024         return 0;
2025 }
2026
2027 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2028 {
2029         ADS_STRUCT *ads;
2030         char *host_principal;
2031         fstring my_name;
2032         ADS_STATUS ret;
2033
2034         if (c->display_usage) {
2035                 d_printf(  "%s\n"
2036                            "net ads changetrustpw\n"
2037                            "    %s\n",
2038                          _("Usage:"),
2039                          _("Change the machine account's trust password"));
2040                 return 0;
2041         }
2042
2043         if (!secrets_init()) {
2044                 DEBUG(1,("Failed to initialise secrets database\n"));
2045                 return -1;
2046         }
2047
2048         net_use_krb_machine_account(c);
2049
2050         use_in_memory_ccache();
2051
2052         if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2053                 return -1;
2054         }
2055
2056         fstrcpy(my_name, global_myname());
2057         strlower_m(my_name);
2058         if (asprintf(&host_principal, "%s$@%s", my_name, ads->config.realm) == -1) {
2059                 ads_destroy(&ads);
2060                 return -1;
2061         }
2062         d_printf(_("Changing password for principal: %s\n"), host_principal);
2063
2064         ret = ads_change_trust_account_password(ads, host_principal);
2065
2066         if (!ADS_ERR_OK(ret)) {
2067                 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
2068                 ads_destroy(&ads);
2069                 SAFE_FREE(host_principal);
2070                 return -1;
2071         }
2072
2073         d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2074
2075         if (USE_SYSTEM_KEYTAB) {
2076                 d_printf(_("Attempting to update system keytab with new password.\n"));
2077                 if (ads_keytab_create_default(ads)) {
2078                         d_printf(_("Failed to update system keytab.\n"));
2079                 }
2080         }
2081
2082         ads_destroy(&ads);
2083         SAFE_FREE(host_principal);
2084
2085         return 0;
2086 }
2087
2088 /*
2089   help for net ads search
2090 */
2091 static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2092 {
2093         d_printf(_(
2094                 "\nnet ads search <expression> <attributes...>\n"
2095                 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2096                 "The expression is a standard LDAP search expression, and the\n"
2097                 "attributes are a list of LDAP fields to show in the results.\n\n"
2098                 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2099                 ));
2100         net_common_flags_usage(c, argc, argv);
2101         return -1;
2102 }
2103
2104
2105 /*
2106   general ADS search function. Useful in diagnosing problems in ADS
2107 */
2108 static int net_ads_search(struct net_context *c, int argc, const char **argv)
2109 {
2110         ADS_STRUCT *ads;
2111         ADS_STATUS rc;
2112         const char *ldap_exp;
2113         const char **attrs;
2114         LDAPMessage *res = NULL;
2115
2116         if (argc < 1 || c->display_usage) {
2117                 return net_ads_search_usage(c, argc, argv);
2118         }
2119
2120         if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2121                 return -1;
2122         }
2123
2124         ldap_exp = argv[0];
2125         attrs = (argv + 1);
2126
2127         rc = ads_do_search_all(ads, ads->config.bind_path,
2128                                LDAP_SCOPE_SUBTREE,
2129                                ldap_exp, attrs, &res);
2130         if (!ADS_ERR_OK(rc)) {
2131                 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2132                 ads_destroy(&ads);
2133                 return -1;
2134         }
2135
2136         d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2137
2138         /* dump the results */
2139         ads_dump(ads, res);
2140
2141         ads_msgfree(ads, res);
2142         ads_destroy(&ads);
2143
2144         return 0;
2145 }
2146
2147
2148 /*
2149   help for net ads search
2150 */
2151 static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2152 {
2153         d_printf(_(
2154                 "\nnet ads dn <dn> <attributes...>\n"
2155                 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2156                 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2157                 "to show in the results\n\n"
2158                 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2159                 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2160                 ));
2161         net_common_flags_usage(c, argc, argv);
2162         return -1;
2163 }
2164
2165
2166 /*
2167   general ADS search function. Useful in diagnosing problems in ADS
2168 */
2169 static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2170 {
2171         ADS_STRUCT *ads;
2172         ADS_STATUS rc;
2173         const char *dn;
2174         const char **attrs;
2175         LDAPMessage *res = NULL;
2176
2177         if (argc < 1 || c->display_usage) {
2178                 return net_ads_dn_usage(c, argc, argv);
2179         }
2180
2181         if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2182                 return -1;
2183         }
2184
2185         dn = argv[0];
2186         attrs = (argv + 1);
2187
2188         rc = ads_do_search_all(ads, dn,
2189                                LDAP_SCOPE_BASE,
2190                                "(objectclass=*)", attrs, &res);
2191         if (!ADS_ERR_OK(rc)) {
2192                 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2193                 ads_destroy(&ads);
2194                 return -1;
2195         }
2196
2197         d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2198
2199         /* dump the results */
2200         ads_dump(ads, res);
2201
2202         ads_msgfree(ads, res);
2203         ads_destroy(&ads);
2204
2205         return 0;
2206 }
2207
2208 /*
2209   help for net ads sid search
2210 */
2211 static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2212 {
2213         d_printf(_(
2214                 "\nnet ads sid <sid> <attributes...>\n"
2215                 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2216                 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2217                 "to show in the results\n\n"
2218                 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2219                 ));
2220         net_common_flags_usage(c, argc, argv);
2221         return -1;
2222 }
2223
2224
2225 /*
2226   general ADS search function. Useful in diagnosing problems in ADS
2227 */
2228 static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2229 {
2230         ADS_STRUCT *ads;
2231         ADS_STATUS rc;
2232         const char *sid_string;
2233         const char **attrs;
2234         LDAPMessage *res = NULL;
2235         struct dom_sid sid;
2236
2237         if (argc < 1 || c->display_usage) {
2238                 return net_ads_sid_usage(c, argc, argv);
2239         }
2240
2241         if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2242                 return -1;
2243         }
2244
2245         sid_string = argv[0];
2246         attrs = (argv + 1);
2247
2248         if (!string_to_sid(&sid, sid_string)) {
2249                 d_fprintf(stderr, _("could not convert sid\n"));
2250                 ads_destroy(&ads);
2251                 return -1;
2252         }
2253
2254         rc = ads_search_retry_sid(ads, &res, &sid, attrs);
2255         if (!ADS_ERR_OK(rc)) {
2256                 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2257                 ads_destroy(&ads);
2258                 return -1;
2259         }
2260
2261         d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2262
2263         /* dump the results */
2264         ads_dump(ads, res);
2265
2266         ads_msgfree(ads, res);
2267         ads_destroy(&ads);
2268
2269         return 0;
2270 }
2271
2272 static int net_ads_keytab_flush(struct net_context *c, int argc, const char **argv)
2273 {
2274         int ret;
2275         ADS_STRUCT *ads;
2276
2277         if (c->display_usage) {
2278                 d_printf(  "%s\n"
2279                            "net ads keytab flush\n"
2280                            "    %s\n",
2281                          _("Usage:"),
2282                          _("Delete the whole keytab"));
2283                 return 0;
2284         }
2285
2286         if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2287                 return -1;
2288         }
2289         ret = ads_keytab_flush(ads);
2290         ads_destroy(&ads);
2291         return ret;
2292 }
2293
2294 static int net_ads_keytab_add(struct net_context *c, int argc, const char **argv)
2295 {
2296         int i;
2297         int ret = 0;
2298         ADS_STRUCT *ads;
2299
2300         if (c->display_usage) {
2301                 d_printf("%s\n%s",
2302                          _("Usage:"),
2303                          _("net ads keytab add <principal> [principal ...]\n"
2304                            "  Add principals to local keytab\n"
2305                            "    principal\tKerberos principal to add to "
2306                            "keytab\n"));
2307                 return 0;
2308         }
2309
2310         d_printf(_("Processing principals to add...\n"));
2311         if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2312                 return -1;
2313         }
2314         for (i = 0; i < argc; i++) {
2315                 ret |= ads_keytab_add_entry(ads, argv[i]);
2316         }
2317         ads_destroy(&ads);
2318         return ret;
2319 }
2320
2321 static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
2322 {
2323         ADS_STRUCT *ads;
2324         int ret;
2325
2326         if (c->display_usage) {
2327                 d_printf(  "%s\n"
2328                            "net ads keytab create\n"
2329                            "    %s\n",
2330                          _("Usage:"),
2331                          _("Create new default keytab"));
2332                 return 0;
2333         }
2334
2335         if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2336                 return -1;
2337         }
2338         ret = ads_keytab_create_default(ads);
2339         ads_destroy(&ads);
2340         return ret;
2341 }
2342
2343 static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
2344 {
2345         const char *keytab = NULL;
2346
2347         if (c->display_usage) {
2348                 d_printf("%s\n%s",
2349                          _("Usage:"),
2350                          _("net ads keytab list [keytab]\n"
2351                            "  List a local keytab\n"
2352                            "    keytab\tKeytab to list\n"));
2353                 return 0;
2354         }
2355
2356         if (argc >= 1) {
2357                 keytab = argv[0];
2358         }
2359
2360         return ads_keytab_list(keytab);
2361 }
2362
2363
2364 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
2365 {
2366         struct functable func[] = {
2367                 {
2368                         "add",
2369                         net_ads_keytab_add,
2370                         NET_TRANSPORT_ADS,
2371                         N_("Add a service principal"),
2372                         N_("net ads keytab add\n"
2373                            "    Add a service principal")
2374                 },
2375                 {
2376                         "create",
2377                         net_ads_keytab_create,
2378                         NET_TRANSPORT_ADS,
2379                         N_("Create a fresh keytab"),
2380                         N_("net ads keytab create\n"
2381                            "    Create a fresh keytab")
2382                 },
2383                 {
2384                         "flush",
2385                         net_ads_keytab_flush,
2386                         NET_TRANSPORT_ADS,
2387                         N_("Remove all keytab entries"),
2388                         N_("net ads keytab flush\n"
2389                            "    Remove all keytab entries")
2390                 },
2391                 {
2392                         "list",
2393                         net_ads_keytab_list,
2394                         NET_TRANSPORT_ADS,
2395                         N_("List a keytab"),
2396                         N_("net ads keytab list\n"
2397                            "    List a keytab")
2398                 },
2399                 {NULL, NULL, 0, NULL, NULL}
2400         };
2401
2402         if (!USE_KERBEROS_KEYTAB) {
2403                 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
2404                     "keytab method to use keytab functions.\n"));
2405         }
2406
2407         return net_run_function(c, argc, argv, "net ads keytab", func);
2408 }
2409
2410 static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
2411 {
2412         int ret = -1;
2413
2414         if (c->display_usage) {
2415                 d_printf(  "%s\n"
2416                            "net ads kerberos renew\n"
2417                            "    %s\n",
2418                          _("Usage:"),
2419                          _("Renew TGT from existing credential cache"));
2420                 return 0;
2421         }
2422
2423         ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
2424         if (ret) {
2425                 d_printf(_("failed to renew kerberos ticket: %s\n"),
2426                         error_message(ret));
2427         }
2428         return ret;
2429 }
2430
2431 static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
2432 {
2433         struct PAC_LOGON_INFO *info = NULL;
2434         TALLOC_CTX *mem_ctx = NULL;
2435         NTSTATUS status;
2436         int ret = -1;
2437         const char *impersonate_princ_s = NULL;
2438
2439         if (c->display_usage) {
2440                 d_printf(  "%s\n"
2441                            "net ads kerberos pac\n"
2442                            "    %s\n",
2443                          _("Usage:"),
2444                          _("Dump the Kerberos PAC"));
2445                 return 0;
2446         }
2447
2448         mem_ctx = talloc_init("net_ads_kerberos_pac");
2449         if (!mem_ctx) {
2450                 goto out;
2451         }
2452
2453         if (argc > 0) {
2454                 impersonate_princ_s = argv[0];
2455         }
2456
2457         c->opt_password = net_prompt_pass(c, c->opt_user_name);
2458
2459         status = kerberos_return_pac(mem_ctx,
2460                                      c->opt_user_name,
2461                                      c->opt_password,
2462                                      0,
2463                                      NULL,
2464                                      NULL,
2465                                      NULL,
2466                                      true,
2467                                      true,
2468                                      2592000, /* one month */
2469                                      impersonate_princ_s,
2470                                      &info);
2471         if (!NT_STATUS_IS_OK(status)) {
2472                 d_printf(_("failed to query kerberos PAC: %s\n"),
2473                         nt_errstr(status));
2474                 goto out;
2475         }
2476
2477         if (info) {
2478                 const char *s;
2479                 s = NDR_PRINT_STRUCT_STRING(mem_ctx, PAC_LOGON_INFO, info);
2480                 d_printf(_("The Pac: %s\n"), s);
2481         }
2482
2483         ret = 0;
2484  out:
2485         TALLOC_FREE(mem_ctx);
2486         return ret;
2487 }
2488
2489 static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
2490 {
2491         TALLOC_CTX *mem_ctx = NULL;
2492         int ret = -1;
2493         NTSTATUS status;
2494
2495         if (c->display_usage) {
2496                 d_printf(  "%s\n"
2497                            "net ads kerberos kinit\n"
2498                            "    %s\n",
2499                          _("Usage:"),
2500                          _("Get Ticket Granting Ticket (TGT) for the user"));
2501                 return 0;
2502         }
2503
2504         mem_ctx = talloc_init("net_ads_kerberos_kinit");
2505         if (!mem_ctx) {
2506                 goto out;
2507         }
2508
2509         c->opt_password = net_prompt_pass(c, c->opt_user_name);
2510
2511         ret = kerberos_kinit_password_ext(c->opt_user_name,
2512                                           c->opt_password,
2513                                           0,
2514                                           NULL,
2515                                           NULL,
2516                                           NULL,
2517                                           true,
2518                                           true,
2519                                           2592000, /* one month */
2520                                           &status);
2521         if (ret) {
2522                 d_printf(_("failed to kinit password: %s\n"),
2523                         nt_errstr(status));
2524         }
2525  out:
2526         return ret;
2527 }
2528
2529 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
2530 {
2531         struct functable func[] = {
2532                 {
2533                         "kinit",
2534                         net_ads_kerberos_kinit,
2535                         NET_TRANSPORT_ADS,
2536                         N_("Retrieve Ticket Granting Ticket (TGT)"),
2537                         N_("net ads kerberos kinit\n"
2538                            "    Receive Ticket Granting Ticket (TGT)")
2539                 },
2540                 {
2541                         "renew",
2542                         net_ads_kerberos_renew,
2543                         NET_TRANSPORT_ADS,
2544                         N_("Renew Ticket Granting Ticket from credential cache"),
2545                         N_("net ads kerberos renew\n"
2546                            "    Renew Ticket Granting Ticket (TGT) from "
2547                            "credential cache")
2548                 },
2549                 {
2550                         "pac",
2551                         net_ads_kerberos_pac,
2552                         NET_TRANSPORT_ADS,
2553                         N_("Dump Kerberos PAC"),
2554                         N_("net ads kerberos pac\n"
2555                            "    Dump Kerberos PAC")
2556                 },
2557                 {NULL, NULL, 0, NULL, NULL}
2558         };
2559
2560         return net_run_function(c, argc, argv, "net ads kerberos", func);
2561 }
2562
2563 int net_ads(struct net_context *c, int argc, const char **argv)
2564 {
2565         struct functable func[] = {
2566                 {
2567                         "info",
2568                         net_ads_info,
2569                         NET_TRANSPORT_ADS,
2570                         N_("Display details on remote ADS server"),
2571                         N_("net ads info\n"
2572                            "    Display details on remote ADS server")
2573                 },
2574                 {
2575                         "join",
2576                         net_ads_join,
2577                         NET_TRANSPORT_ADS,
2578                         N_("Join the local machine to ADS realm"),
2579                         N_("net ads join\n"
2580                            "    Join the local machine to ADS realm")
2581                 },
2582                 {
2583                         "testjoin",
2584                         net_ads_testjoin,
2585                         NET_TRANSPORT_ADS,
2586                         N_("Validate machine account"),
2587                         N_("net ads testjoin\n"
2588                            "    Validate machine account")
2589                 },
2590                 {
2591                         "leave",
2592                         net_ads_leave,
2593                         NET_TRANSPORT_ADS,
2594                         N_("Remove the local machine from ADS"),
2595                         N_("net ads leave\n"
2596                            "    Remove the local machine from ADS")
2597                 },
2598                 {
2599                         "status",
2600                         net_ads_status,
2601                         NET_TRANSPORT_ADS,
2602                         N_("Display machine account details"),
2603                         N_("net ads status\n"
2604                            "    Display machine account details")
2605                 },
2606                 {
2607                         "user",
2608                         net_ads_user,
2609                         NET_TRANSPORT_ADS,
2610                         N_("List/modify users"),
2611                         N_("net ads user\n"
2612                            "    List/modify users")
2613                 },
2614                 {
2615                         "group",
2616                         net_ads_group,
2617                         NET_TRANSPORT_ADS,
2618                         N_("List/modify groups"),
2619                         N_("net ads group\n"
2620                            "    List/modify groups")
2621                 },
2622                 {
2623                         "dns",
2624                         net_ads_dns,
2625                         NET_TRANSPORT_ADS,
2626                         N_("Issue dynamic DNS update"),
2627                         N_("net ads dns\n"
2628                            "    Issue dynamic DNS update")
2629                 },
2630                 {
2631                         "password",
2632                         net_ads_password,
2633                         NET_TRANSPORT_ADS,
2634                         N_("Change user passwords"),
2635                         N_("net ads password\n"
2636                            "    Change user passwords")
2637                 },
2638                 {
2639                         "changetrustpw",
2640                         net_ads_changetrustpw,
2641                         NET_TRANSPORT_ADS,
2642                         N_("Change trust account password"),
2643                         N_("net ads changetrustpw\n"
2644                            "    Change trust account password")
2645                 },
2646                 {
2647                         "printer",
2648                         net_ads_printer,
2649                         NET_TRANSPORT_ADS,
2650                         N_("List/modify printer entries"),
2651                         N_("net ads printer\n"
2652                            "    List/modify printer entries")
2653                 },
2654                 {
2655                         "search",
2656                         net_ads_search,
2657                         NET_TRANSPORT_ADS,
2658                         N_("Issue LDAP search using filter"),
2659                         N_("net ads search\n"
2660                            "    Issue LDAP search using filter")
2661                 },
2662                 {
2663                         "dn",
2664                         net_ads_dn,
2665                         NET_TRANSPORT_ADS,
2666                         N_("Issue LDAP search by DN"),
2667                         N_("net ads dn\n"
2668                            "    Issue LDAP search by DN")
2669                 },
2670                 {
2671                         "sid",
2672                         net_ads_sid,
2673                         NET_TRANSPORT_ADS,
2674                         N_("Issue LDAP search by SID"),
2675                         N_("net ads sid\n"
2676                            "    Issue LDAP search by SID")
2677                 },
2678                 {
2679                         "workgroup",
2680                         net_ads_workgroup,
2681                         NET_TRANSPORT_ADS,
2682                         N_("Display workgroup name"),
2683                         N_("net ads workgroup\n"
2684                            "    Display the workgroup name")
2685                 },
2686                 {
2687                         "lookup",
2688                         net_ads_lookup,
2689                         NET_TRANSPORT_ADS,
2690                         N_("Perfom CLDAP query on DC"),
2691                         N_("net ads lookup\n"
2692                            "    Find the ADS DC using CLDAP lookups")
2693                 },
2694                 {
2695                         "keytab",
2696                         net_ads_keytab,
2697                         NET_TRANSPORT_ADS,
2698                         N_("Manage local keytab file"),
2699                         N_("net ads keytab\n"
2700                            "    Manage local keytab file")
2701                 },
2702                 {
2703                         "gpo",
2704                         net_ads_gpo,
2705                         NET_TRANSPORT_ADS,
2706                         N_("Manage group policy objects"),
2707                         N_("net ads gpo\n"
2708                            "    Manage group policy objects")
2709                 },
2710                 {
2711                         "kerberos",
2712                         net_ads_kerberos,
2713                         NET_TRANSPORT_ADS,
2714                         N_("Manage kerberos keytab"),
2715                         N_("net ads kerberos\n"
2716                            "    Manage kerberos keytab")
2717                 },
2718                 {NULL, NULL, 0, NULL, NULL}
2719         };
2720
2721         return net_run_function(c, argc, argv, "net ads", func);
2722 }
2723
2724 #else
2725
2726 static int net_ads_noads(void)
2727 {
2728         d_fprintf(stderr, _("ADS support not compiled in\n"));
2729         return -1;
2730 }
2731
2732 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
2733 {
2734         return net_ads_noads();
2735 }
2736
2737 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
2738 {
2739         return net_ads_noads();
2740 }
2741
2742 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2743 {
2744         return net_ads_noads();
2745 }
2746
2747 int net_ads_join(struct net_context *c, int argc, const char **argv)
2748 {
2749         return net_ads_noads();
2750 }
2751
2752 int net_ads_user(struct net_context *c, int argc, const char **argv)
2753 {
2754         return net_ads_noads();
2755 }
2756
2757 int net_ads_group(struct net_context *c, int argc, const char **argv)
2758 {
2759         return net_ads_noads();
2760 }
2761
2762 int net_ads_gpo(struct net_context *c, int argc, const char **argv)
2763 {
2764         return net_ads_noads();
2765 }
2766
2767 /* this one shouldn't display a message */
2768 int net_ads_check(struct net_context *c)
2769 {
2770         return -1;
2771 }
2772
2773 int net_ads_check_our_domain(struct net_context *c)
2774 {
2775         return -1;
2776 }
2777
2778 int net_ads(struct net_context *c, int argc, const char **argv)
2779 {
2780         return net_ads_noads();
2781 }
2782
2783 #endif  /* WITH_ADS */