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