ba500b50b6cec3bbe2ba1ca2143ad20f1e08295d
[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         return -1;
1333 }
1334
1335
1336 static void _net_ads_join_dns_updates(struct net_context *c, TALLOC_CTX *ctx, struct libnet_JoinCtx *r)
1337 {
1338 #if defined(WITH_DNS_UPDATES)
1339         ADS_STRUCT *ads_dns = NULL;
1340         int ret;
1341         NTSTATUS status;
1342
1343         /*
1344          * In a clustered environment, don't do dynamic dns updates:
1345          * Registering the set of ip addresses that are assigned to
1346          * the interfaces of the node that performs the join does usually
1347          * not have the desired effect, since the local interfaces do not
1348          * carry the complete set of the cluster's public IP addresses.
1349          * And it can also contain internal addresses that should not
1350          * be visible to the outside at all.
1351          * In order to do dns updates in a clustererd setup, use
1352          * net ads dns register.
1353          */
1354         if (lp_clustering()) {
1355                 d_fprintf(stderr, _("Not doing automatic DNS update in a "
1356                                     "clustered setup.\n"));
1357                 return;
1358         }
1359
1360         if (!r->out.domain_is_ad) {
1361                 return;
1362         }
1363
1364         /*
1365          * We enter this block with user creds.
1366          * kinit with the machine password to do dns update.
1367          */
1368
1369         ads_dns = ads_init(lp_realm(), NULL, r->in.dc_name);
1370
1371         if (ads_dns == NULL) {
1372                 d_fprintf(stderr, _("DNS update failed: out of memory!\n"));
1373                 goto done;
1374         }
1375
1376         use_in_memory_ccache();
1377
1378         ret = asprintf(&ads_dns->auth.user_name, "%s$", lp_netbios_name());
1379         if (ret == -1) {
1380                 d_fprintf(stderr, _("DNS update failed: out of memory\n"));
1381                 goto done;
1382         }
1383
1384         ads_dns->auth.password = secrets_fetch_machine_password(
1385                 r->out.netbios_domain_name, NULL, NULL);
1386         if (ads_dns->auth.password == NULL) {
1387                 d_fprintf(stderr, _("DNS update failed: out of memory\n"));
1388                 goto done;
1389         }
1390
1391         ads_dns->auth.realm = SMB_STRDUP(r->out.dns_domain_name);
1392         if (ads_dns->auth.realm == NULL) {
1393                 d_fprintf(stderr, _("DNS update failed: out of memory\n"));
1394                 goto done;
1395         }
1396
1397         if (!strupper_m(ads_dns->auth.realm)) {
1398                 d_fprintf(stderr, _("strupper_m %s failed\n"), ads_dns->auth.realm);
1399                 goto done;
1400         }
1401
1402         ret = ads_kinit_password(ads_dns);
1403         if (ret != 0) {
1404                 d_fprintf(stderr,
1405                           _("DNS update failed: kinit failed: %s\n"),
1406                           error_message(ret));
1407                 goto done;
1408         }
1409
1410         status = net_update_dns(c, ctx, ads_dns, NULL);
1411         if (!NT_STATUS_IS_OK(status)) {
1412                 d_fprintf( stderr, _("DNS update failed: %s\n"),
1413                           nt_errstr(status));
1414         }
1415
1416 done:
1417         ads_destroy(&ads_dns);
1418 #endif
1419
1420         return;
1421 }
1422
1423
1424 int net_ads_join(struct net_context *c, int argc, const char **argv)
1425 {
1426         TALLOC_CTX *ctx = NULL;
1427         struct libnet_JoinCtx *r = NULL;
1428         const char *domain = lp_realm();
1429         WERROR werr = WERR_SETUP_NOT_JOINED;
1430         bool createupn = false;
1431         const char *machineupn = NULL;
1432         const char *machine_password = NULL;
1433         const char *create_in_ou = NULL;
1434         int i;
1435         const char *os_name = NULL;
1436         const char *os_version = NULL;
1437         bool modify_config = lp_config_backend_is_registry();
1438
1439         if (c->display_usage)
1440                 return net_ads_join_usage(c, argc, argv);
1441
1442         if (!modify_config) {
1443
1444                 werr = check_ads_config();
1445                 if (!W_ERROR_IS_OK(werr)) {
1446                         d_fprintf(stderr, _("Invalid configuration.  Exiting....\n"));
1447                         goto fail;
1448                 }
1449         }
1450
1451         if (!(ctx = talloc_init("net_ads_join"))) {
1452                 d_fprintf(stderr, _("Could not initialise talloc context.\n"));
1453                 werr = WERR_NOMEM;
1454                 goto fail;
1455         }
1456
1457         if (!c->opt_kerberos) {
1458                 use_in_memory_ccache();
1459         }
1460
1461         werr = libnet_init_JoinCtx(ctx, &r);
1462         if (!W_ERROR_IS_OK(werr)) {
1463                 goto fail;
1464         }
1465
1466         /* process additional command line args */
1467
1468         for ( i=0; i<argc; i++ ) {
1469                 if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
1470                         createupn = true;
1471                         machineupn = get_string_param(argv[i]);
1472                 }
1473                 else if ( !strncasecmp_m(argv[i], "createcomputer", strlen("createcomputer")) ) {
1474                         if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
1475                                 d_fprintf(stderr, _("Please supply a valid OU path.\n"));
1476                                 werr = WERR_INVALID_PARAM;
1477                                 goto fail;
1478                         }
1479                 }
1480                 else if ( !strncasecmp_m(argv[i], "osName", strlen("osName")) ) {
1481                         if ( (os_name = get_string_param(argv[i])) == NULL ) {
1482                                 d_fprintf(stderr, _("Please supply a operating system name.\n"));
1483                                 werr = WERR_INVALID_PARAM;
1484                                 goto fail;
1485                         }
1486                 }
1487                 else if ( !strncasecmp_m(argv[i], "osVer", strlen("osVer")) ) {
1488                         if ( (os_version = get_string_param(argv[i])) == NULL ) {
1489                                 d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
1490                                 werr = WERR_INVALID_PARAM;
1491                                 goto fail;
1492                         }
1493                 }
1494                 else if ( !strncasecmp_m(argv[i], "machinepass", strlen("machinepass")) ) {
1495                         if ( (machine_password = get_string_param(argv[i])) == NULL ) {
1496                                 d_fprintf(stderr, _("Please supply a valid password to set as trust account password.\n"));
1497                                 werr = WERR_INVALID_PARAM;
1498                                 goto fail;
1499                         }
1500                 }
1501                 else {
1502                         domain = argv[i];
1503                 }
1504         }
1505
1506         if (!*domain) {
1507                 d_fprintf(stderr, _("Please supply a valid domain name\n"));
1508                 werr = WERR_INVALID_PARAM;
1509                 goto fail;
1510         }
1511
1512         if (!c->msg_ctx) {
1513                 d_fprintf(stderr, _("Could not initialise message context. "
1514                         "Try running as root\n"));
1515                 werr = WERR_ACCESS_DENIED;
1516                 goto fail;
1517         }
1518
1519         /* Do the domain join here */
1520
1521         r->in.domain_name       = domain;
1522         r->in.create_upn        = createupn;
1523         r->in.upn               = machineupn;
1524         r->in.account_ou        = create_in_ou;
1525         r->in.os_name           = os_name;
1526         r->in.os_version        = os_version;
1527         r->in.dc_name           = c->opt_host;
1528         r->in.admin_account     = c->opt_user_name;
1529         r->in.admin_password    = net_prompt_pass(c, c->opt_user_name);
1530         r->in.machine_password  = machine_password;
1531         r->in.debug             = true;
1532         r->in.use_kerberos      = c->opt_kerberos;
1533         r->in.modify_config     = modify_config;
1534         r->in.join_flags        = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1535                                   WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
1536                                   WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
1537         r->in.msg_ctx           = c->msg_ctx;
1538
1539         werr = libnet_Join(ctx, r);
1540         if (W_ERROR_EQUAL(werr, WERR_DCNOTFOUND) &&
1541             strequal(domain, lp_realm())) {
1542                 r->in.domain_name = lp_workgroup();
1543                 werr = libnet_Join(ctx, r);
1544         }
1545         if (!W_ERROR_IS_OK(werr)) {
1546                 goto fail;
1547         }
1548
1549         /* Check the short name of the domain */
1550
1551         if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
1552                 d_printf(_("The workgroup in %s does not match the short\n"
1553                            "domain name obtained from the server.\n"
1554                            "Using the name [%s] from the server.\n"
1555                            "You should set \"workgroup = %s\" in %s.\n"),
1556                          get_dyn_CONFIGFILE(), r->out.netbios_domain_name,
1557                          r->out.netbios_domain_name, get_dyn_CONFIGFILE());
1558         }
1559
1560         d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name);
1561
1562         if (r->out.dns_domain_name) {
1563                 d_printf(_("Joined '%s' to dns domain '%s'\n"), r->in.machine_name,
1564                         r->out.dns_domain_name);
1565         } else {
1566                 d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name,
1567                         r->out.netbios_domain_name);
1568         }
1569
1570         /*
1571          * We try doing the dns update (if it was compiled in).
1572          * If the dns update fails, we still consider the join
1573          * operation as succeeded if we came this far.
1574          */
1575         _net_ads_join_dns_updates(c, ctx, r);
1576
1577         TALLOC_FREE(r);
1578         TALLOC_FREE( ctx );
1579
1580         return 0;
1581
1582 fail:
1583         /* issue an overall failure message at the end. */
1584         d_printf(_("Failed to join domain: %s\n"),
1585                 r && r->out.error_string ? r->out.error_string :
1586                 get_friendly_werror_msg(werr));
1587         TALLOC_FREE( ctx );
1588
1589         return -1;
1590 }
1591
1592 /*******************************************************************
1593  ********************************************************************/
1594
1595 static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
1596 {
1597 #if defined(WITH_DNS_UPDATES)
1598         ADS_STRUCT *ads;
1599         ADS_STATUS status;
1600         NTSTATUS ntstatus;
1601         TALLOC_CTX *ctx;
1602         const char *hostname = NULL;
1603         const char **addrs_list = NULL;
1604         struct sockaddr_storage *addrs = NULL;
1605         int num_addrs = 0;
1606         int count;
1607
1608 #ifdef DEVELOPER
1609         talloc_enable_leak_report();
1610 #endif
1611
1612         if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
1613                 d_fprintf(stderr, _("Refusing DNS updates with automatic "
1614                                     "detection of addresses in a clustered "
1615                                     "setup.\n"));
1616                 c->display_usage = true;
1617         }
1618
1619         if (c->display_usage) {
1620                 d_printf(  "%s\n"
1621                            "net ads dns register [hostname [IP [IP...]]]\n"
1622                            "    %s\n",
1623                          _("Usage:"),
1624                          _("Register hostname with DNS\n"));
1625                 return -1;
1626         }
1627
1628         if (!(ctx = talloc_init("net_ads_dns"))) {
1629                 d_fprintf(stderr, _("Could not initialise talloc context\n"));
1630                 return -1;
1631         }
1632
1633         if (argc >= 1) {
1634                 hostname = argv[0];
1635         }
1636
1637         if (argc > 1) {
1638                 num_addrs = argc - 1;
1639                 addrs_list = &argv[1];
1640         } else if (lp_clustering()) {
1641                 addrs_list = lp_cluster_addresses();
1642                 num_addrs = str_list_length(addrs_list);
1643         }
1644
1645         if (num_addrs > 0) {
1646                 addrs = talloc_zero_array(ctx, struct sockaddr_storage, num_addrs);
1647                 if (addrs == NULL) {
1648                         d_fprintf(stderr, _("Error allocating memory!\n"));
1649                         talloc_free(ctx);
1650                         return -1;
1651                 }
1652         }
1653
1654         for (count = 0; count < num_addrs; count++) {
1655                 if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
1656                         d_fprintf(stderr, "%s '%s'.\n",
1657                                           _("Cannot interpret address"),
1658                                           addrs_list[count]);
1659                         talloc_free(ctx);
1660                         return -1;
1661                 }
1662         }
1663
1664         status = ads_startup(c, true, &ads);
1665         if ( !ADS_ERR_OK(status) ) {
1666                 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1667                 TALLOC_FREE(ctx);
1668                 return -1;
1669         }
1670
1671         ntstatus = net_update_dns_ext(c, ctx, ads, hostname, addrs, num_addrs);
1672         if (!NT_STATUS_IS_OK(ntstatus)) {
1673                 d_fprintf( stderr, _("DNS update failed!\n") );
1674                 ads_destroy( &ads );
1675                 TALLOC_FREE( ctx );
1676                 return -1;
1677         }
1678
1679         d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
1680
1681         ads_destroy(&ads);
1682         TALLOC_FREE( ctx );
1683
1684         return 0;
1685 #else
1686         d_fprintf(stderr,
1687                   _("DNS update support not enabled at compile time!\n"));
1688         return -1;
1689 #endif
1690 }
1691
1692 static int net_ads_dns_gethostbyname(struct net_context *c, int argc, const char **argv)
1693 {
1694 #if defined(WITH_DNS_UPDATES)
1695         DNS_ERROR err;
1696
1697 #ifdef DEVELOPER
1698         talloc_enable_leak_report();
1699 #endif
1700
1701         if (argc != 2 || c->display_usage) {
1702                 d_printf(  "%s\n"
1703                            "    %s\n"
1704                            "    %s\n",
1705                          _("Usage:"),
1706                          _("net ads dns gethostbyname <server> <name>\n"),
1707                          _("  Look up hostname from the AD\n"
1708                            "    server\tName server to use\n"
1709                            "    name\tName to look up\n"));
1710                 return -1;
1711         }
1712
1713         err = do_gethostbyname(argv[0], argv[1]);
1714
1715         d_printf(_("do_gethostbyname returned %s (%d)\n"),
1716                 dns_errstr(err), ERROR_DNS_V(err));
1717 #endif
1718         return 0;
1719 }
1720
1721 static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
1722 {
1723         struct functable func[] = {
1724                 {
1725                         "register",
1726                         net_ads_dns_register,
1727                         NET_TRANSPORT_ADS,
1728                         N_("Add host dns entry to AD"),
1729                         N_("net ads dns register\n"
1730                            "    Add host dns entry to AD")
1731                 },
1732                 {
1733                         "gethostbyname",
1734                         net_ads_dns_gethostbyname,
1735                         NET_TRANSPORT_ADS,
1736                         N_("Look up host"),
1737                         N_("net ads dns gethostbyname\n"
1738                            "    Look up host")
1739                 },
1740                 {NULL, NULL, 0, NULL, NULL}
1741         };
1742
1743         return net_run_function(c, argc, argv, "net ads dns", func);
1744 }
1745
1746 /*******************************************************************
1747  ********************************************************************/
1748
1749 int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
1750 {
1751         d_printf(_(
1752 "\nnet ads printer search <printer>"
1753 "\n\tsearch for a printer in the directory\n"
1754 "\nnet ads printer info <printer> <server>"
1755 "\n\tlookup info in directory for printer on server"
1756 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
1757 "\nnet ads printer publish <printername>"
1758 "\n\tpublish printer in directory"
1759 "\n\t(note: printer name is required)\n"
1760 "\nnet ads printer remove <printername>"
1761 "\n\tremove printer from directory"
1762 "\n\t(note: printer name is required)\n"));
1763         return -1;
1764 }
1765
1766 /*******************************************************************
1767  ********************************************************************/
1768
1769 static int net_ads_printer_search(struct net_context *c, int argc, const char **argv)
1770 {
1771         ADS_STRUCT *ads;
1772         ADS_STATUS rc;
1773         LDAPMessage *res = NULL;
1774
1775         if (c->display_usage) {
1776                 d_printf(  "%s\n"
1777                            "net ads printer search\n"
1778                            "    %s\n",
1779                          _("Usage:"),
1780                          _("List printers in the AD"));
1781                 return 0;
1782         }
1783
1784         if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
1785                 return -1;
1786         }
1787
1788         rc = ads_find_printers(ads, &res);
1789
1790         if (!ADS_ERR_OK(rc)) {
1791                 d_fprintf(stderr, _("ads_find_printer: %s\n"), ads_errstr(rc));
1792                 ads_msgfree(ads, res);
1793                 ads_destroy(&ads);
1794                 return -1;
1795         }
1796
1797         if (ads_count_replies(ads, res) == 0) {
1798                 d_fprintf(stderr, _("No results found\n"));
1799                 ads_msgfree(ads, res);
1800                 ads_destroy(&ads);
1801                 return -1;
1802         }
1803
1804         ads_dump(ads, res);
1805         ads_msgfree(ads, res);
1806         ads_destroy(&ads);
1807         return 0;
1808 }
1809
1810 static int net_ads_printer_info(struct net_context *c, int argc, const char **argv)
1811 {
1812         ADS_STRUCT *ads;
1813         ADS_STATUS rc;
1814         const char *servername, *printername;
1815         LDAPMessage *res = NULL;
1816
1817         if (c->display_usage) {
1818                 d_printf("%s\n%s",
1819                          _("Usage:"),
1820                          _("net ads printer info [printername [servername]]\n"
1821                            "  Display printer info from AD\n"
1822                            "    printername\tPrinter name or wildcard\n"
1823                            "    servername\tName of the print server\n"));
1824                 return 0;
1825         }
1826
1827         if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
1828                 return -1;
1829         }
1830
1831         if (argc > 0) {
1832                 printername = argv[0];
1833         } else {
1834                 printername = "*";
1835         }
1836
1837         if (argc > 1) {
1838                 servername =  argv[1];
1839         } else {
1840                 servername = lp_netbios_name();
1841         }
1842
1843         rc = ads_find_printer_on_server(ads, &res, printername, servername);
1844
1845         if (!ADS_ERR_OK(rc)) {
1846                 d_fprintf(stderr, _("Server '%s' not found: %s\n"),
1847                         servername, ads_errstr(rc));
1848                 ads_msgfree(ads, res);
1849                 ads_destroy(&ads);
1850                 return -1;
1851         }
1852
1853         if (ads_count_replies(ads, res) == 0) {
1854                 d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
1855                 ads_msgfree(ads, res);
1856                 ads_destroy(&ads);
1857                 return -1;
1858         }
1859
1860         ads_dump(ads, res);
1861         ads_msgfree(ads, res);
1862         ads_destroy(&ads);
1863
1864         return 0;
1865 }
1866
1867 static int net_ads_printer_publish(struct net_context *c, int argc, const char **argv)
1868 {
1869         ADS_STRUCT *ads;
1870         ADS_STATUS rc;
1871         const char *servername, *printername;
1872         struct cli_state *cli = NULL;
1873         struct rpc_pipe_client *pipe_hnd = NULL;
1874         struct sockaddr_storage server_ss;
1875         NTSTATUS nt_status;
1876         TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
1877         ADS_MODLIST mods = ads_init_mods(mem_ctx);
1878         char *prt_dn, *srv_dn, **srv_cn;
1879         char *srv_cn_escaped = NULL, *printername_escaped = NULL;
1880         LDAPMessage *res = NULL;
1881
1882         if (argc < 1 || c->display_usage) {
1883                 d_printf("%s\n%s",
1884                          _("Usage:"),
1885                          _("net ads printer publish <printername> [servername]\n"
1886                            "  Publish printer in AD\n"
1887                            "    printername\tName of the printer\n"
1888                            "    servername\tName of the print server\n"));
1889                 talloc_destroy(mem_ctx);
1890                 return -1;
1891         }
1892
1893         if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
1894                 talloc_destroy(mem_ctx);
1895                 return -1;
1896         }
1897
1898         printername = argv[0];
1899
1900         if (argc == 2) {
1901                 servername = argv[1];
1902         } else {
1903                 servername = lp_netbios_name();
1904         }
1905
1906         /* Get printer data from SPOOLSS */
1907
1908         resolve_name(servername, &server_ss, 0x20, false);
1909
1910         nt_status = cli_full_connection(&cli, lp_netbios_name(), servername,
1911                                         &server_ss, 0,
1912                                         "IPC$", "IPC",
1913                                         c->opt_user_name, c->opt_workgroup,
1914                                         c->opt_password ? c->opt_password : "",
1915                                         CLI_FULL_CONNECTION_USE_KERBEROS,
1916                                         SMB_SIGNING_DEFAULT);
1917
1918         if (NT_STATUS_IS_ERR(nt_status)) {
1919                 d_fprintf(stderr, _("Unable to open a connection to %s to "
1920                                     "obtain data for %s\n"),
1921                           servername, printername);
1922                 ads_destroy(&ads);
1923                 talloc_destroy(mem_ctx);
1924                 return -1;
1925         }
1926
1927         /* Publish on AD server */
1928
1929         ads_find_machine_acct(ads, &res, servername);
1930
1931         if (ads_count_replies(ads, res) == 0) {
1932                 d_fprintf(stderr, _("Could not find machine account for server "
1933                                     "%s\n"),
1934                          servername);
1935                 ads_destroy(&ads);
1936                 talloc_destroy(mem_ctx);
1937                 return -1;
1938         }
1939
1940         srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
1941         srv_cn = ldap_explode_dn(srv_dn, 1);
1942
1943         srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
1944         printername_escaped = escape_rdn_val_string_alloc(printername);
1945         if (!srv_cn_escaped || !printername_escaped) {
1946                 SAFE_FREE(srv_cn_escaped);
1947                 SAFE_FREE(printername_escaped);
1948                 d_fprintf(stderr, _("Internal error, out of memory!"));
1949                 ads_destroy(&ads);
1950                 talloc_destroy(mem_ctx);
1951                 return -1;
1952         }
1953
1954         if (asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, printername_escaped, srv_dn) == -1) {
1955                 SAFE_FREE(srv_cn_escaped);
1956                 SAFE_FREE(printername_escaped);
1957                 d_fprintf(stderr, _("Internal error, out of memory!"));
1958                 ads_destroy(&ads);
1959                 talloc_destroy(mem_ctx);
1960                 return -1;
1961         }
1962
1963         SAFE_FREE(srv_cn_escaped);
1964         SAFE_FREE(printername_escaped);
1965
1966         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd);
1967         if (!NT_STATUS_IS_OK(nt_status)) {
1968                 d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
1969                          servername);
1970                 SAFE_FREE(prt_dn);
1971                 ads_destroy(&ads);
1972                 talloc_destroy(mem_ctx);
1973                 return -1;
1974         }
1975
1976         if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
1977                                                               printername))) {
1978                 SAFE_FREE(prt_dn);
1979                 ads_destroy(&ads);
1980                 talloc_destroy(mem_ctx);
1981                 return -1;
1982         }
1983
1984         rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
1985         if (!ADS_ERR_OK(rc)) {
1986                 d_fprintf(stderr, "ads_publish_printer: %s\n", ads_errstr(rc));
1987                 SAFE_FREE(prt_dn);
1988                 ads_destroy(&ads);
1989                 talloc_destroy(mem_ctx);
1990                 return -1;
1991         }
1992
1993         d_printf("published printer\n");
1994         SAFE_FREE(prt_dn);
1995         ads_destroy(&ads);
1996         talloc_destroy(mem_ctx);
1997
1998         return 0;
1999 }
2000
2001 static int net_ads_printer_remove(struct net_context *c, int argc, const char **argv)
2002 {
2003         ADS_STRUCT *ads;
2004         ADS_STATUS rc;
2005         const char *servername;
2006         char *prt_dn;
2007         LDAPMessage *res = NULL;
2008
2009         if (argc < 1 || c->display_usage) {
2010                 d_printf("%s\n%s",
2011                          _("Usage:"),
2012                          _("net ads printer remove <printername> [servername]\n"
2013                            "  Remove a printer from the AD\n"
2014                            "    printername\tName of the printer\n"
2015                            "    servername\tName of the print server\n"));
2016                 return -1;
2017         }
2018
2019         if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2020                 return -1;
2021         }
2022
2023         if (argc > 1) {
2024                 servername = argv[1];
2025         } else {
2026                 servername = lp_netbios_name();
2027         }
2028
2029         rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
2030
2031         if (!ADS_ERR_OK(rc)) {
2032                 d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"), ads_errstr(rc));
2033                 ads_msgfree(ads, res);
2034                 ads_destroy(&ads);
2035                 return -1;
2036         }
2037
2038         if (ads_count_replies(ads, res) == 0) {
2039                 d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
2040                 ads_msgfree(ads, res);
2041                 ads_destroy(&ads);
2042                 return -1;
2043         }
2044
2045         prt_dn = ads_get_dn(ads, talloc_tos(), res);
2046         ads_msgfree(ads, res);
2047         rc = ads_del_dn(ads, prt_dn);
2048         TALLOC_FREE(prt_dn);
2049
2050         if (!ADS_ERR_OK(rc)) {
2051                 d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(rc));
2052                 ads_destroy(&ads);
2053                 return -1;
2054         }
2055
2056         ads_destroy(&ads);
2057         return 0;
2058 }
2059
2060 static int net_ads_printer(struct net_context *c, int argc, const char **argv)
2061 {
2062         struct functable func[] = {
2063                 {
2064                         "search",
2065                         net_ads_printer_search,
2066                         NET_TRANSPORT_ADS,
2067                         N_("Search for a printer"),
2068                         N_("net ads printer search\n"
2069                            "    Search for a printer")
2070                 },
2071                 {
2072                         "info",
2073                         net_ads_printer_info,
2074                         NET_TRANSPORT_ADS,
2075                         N_("Display printer information"),
2076                         N_("net ads printer info\n"
2077                            "    Display printer information")
2078                 },
2079                 {
2080                         "publish",
2081                         net_ads_printer_publish,
2082                         NET_TRANSPORT_ADS,
2083                         N_("Publish a printer"),
2084                         N_("net ads printer publish\n"
2085                            "    Publish a printer")
2086                 },
2087                 {
2088                         "remove",
2089                         net_ads_printer_remove,
2090                         NET_TRANSPORT_ADS,
2091                         N_("Delete a printer"),
2092                         N_("net ads printer remove\n"
2093                            "    Delete a printer")
2094                 },
2095                 {NULL, NULL, 0, NULL, NULL}
2096         };
2097
2098         return net_run_function(c, argc, argv, "net ads printer", func);
2099 }
2100
2101
2102 static int net_ads_password(struct net_context *c, int argc, const char **argv)
2103 {
2104         ADS_STRUCT *ads;
2105         const char *auth_principal = c->opt_user_name;
2106         const char *auth_password = c->opt_password;
2107         const char *realm = NULL;
2108         const char *new_password = NULL;
2109         char *chr, *prompt;
2110         const char *user;
2111         char pwd[256] = {0};
2112         ADS_STATUS ret;
2113
2114         if (c->display_usage) {
2115                 d_printf("%s\n%s",
2116                          _("Usage:"),
2117                          _("net ads password <username>\n"
2118                            "  Change password for user\n"
2119                            "    username\tName of user to change password for\n"));
2120                 return 0;
2121         }
2122
2123         if (c->opt_user_name == NULL || c->opt_password == NULL) {
2124                 d_fprintf(stderr, _("You must supply an administrator "
2125                                     "username/password\n"));
2126                 return -1;
2127         }
2128
2129         if (argc < 1) {
2130                 d_fprintf(stderr, _("ERROR: You must say which username to "
2131                                     "change password for\n"));
2132                 return -1;
2133         }
2134
2135         user = argv[0];
2136         if (!strchr_m(user, '@')) {
2137                 if (asprintf(&chr, "%s@%s", argv[0], lp_realm()) == -1) {
2138                         return -1;
2139                 }
2140                 user = chr;
2141         }
2142
2143         use_in_memory_ccache();
2144         chr = strchr_m(auth_principal, '@');
2145         if (chr) {
2146                 realm = ++chr;
2147         } else {
2148                 realm = lp_realm();
2149         }
2150
2151         /* use the realm so we can eventually change passwords for users
2152         in realms other than default */
2153         if (!(ads = ads_init(realm, c->opt_workgroup, c->opt_host))) {
2154                 return -1;
2155         }
2156
2157         /* we don't actually need a full connect, but it's the easy way to
2158                 fill in the KDC's addresss */
2159         ads_connect(ads);
2160
2161         if (!ads->config.realm) {
2162                 d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
2163                 ads_destroy(&ads);
2164                 return -1;
2165         }
2166
2167         if (argv[1]) {
2168                 new_password = (const char *)argv[1];
2169         } else {
2170                 int rc;
2171
2172                 if (asprintf(&prompt, _("Enter new password for %s:"), user) == -1) {
2173                         return -1;
2174                 }
2175                 rc = samba_getpass(prompt, pwd, sizeof(pwd), false, true);
2176                 if (rc < 0) {
2177                         return -1;
2178                 }
2179                 new_password = pwd;
2180                 free(prompt);
2181         }
2182
2183         ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
2184                                 auth_password, user, new_password, ads->auth.time_offset);
2185         memset(pwd, '\0', sizeof(pwd));
2186         if (!ADS_ERR_OK(ret)) {
2187                 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
2188                 ads_destroy(&ads);
2189                 return -1;
2190         }
2191
2192         d_printf(_("Password change for %s completed.\n"), user);
2193         ads_destroy(&ads);
2194
2195         return 0;
2196 }
2197
2198 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2199 {
2200         ADS_STRUCT *ads;
2201         char *host_principal;
2202         fstring my_name;
2203         ADS_STATUS ret;
2204
2205         if (c->display_usage) {
2206                 d_printf(  "%s\n"
2207                            "net ads changetrustpw\n"
2208                            "    %s\n",
2209                          _("Usage:"),
2210                          _("Change the machine account's trust password"));
2211                 return 0;
2212         }
2213
2214         if (!secrets_init()) {
2215                 DEBUG(1,("Failed to initialise secrets database\n"));
2216                 return -1;
2217         }
2218
2219         net_use_krb_machine_account(c);
2220
2221         use_in_memory_ccache();
2222
2223         if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2224                 return -1;
2225         }
2226
2227         fstrcpy(my_name, lp_netbios_name());
2228         if (!strlower_m(my_name)) {
2229                 ads_destroy(&ads);
2230                 return -1;
2231         }
2232
2233         if (asprintf(&host_principal, "%s$@%s", my_name, ads->config.realm) == -1) {
2234                 ads_destroy(&ads);
2235                 return -1;
2236         }
2237         d_printf(_("Changing password for principal: %s\n"), host_principal);
2238
2239         ret = ads_change_trust_account_password(ads, host_principal);
2240
2241         if (!ADS_ERR_OK(ret)) {
2242                 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
2243                 ads_destroy(&ads);
2244                 SAFE_FREE(host_principal);
2245                 return -1;
2246         }
2247
2248         d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2249
2250         if (USE_SYSTEM_KEYTAB) {
2251                 d_printf(_("Attempting to update system keytab with new password.\n"));
2252                 if (ads_keytab_create_default(ads)) {
2253                         d_printf(_("Failed to update system keytab.\n"));
2254                 }
2255         }
2256
2257         ads_destroy(&ads);
2258         SAFE_FREE(host_principal);
2259
2260         return 0;
2261 }
2262
2263 /*
2264   help for net ads search
2265 */
2266 static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2267 {
2268         d_printf(_(
2269                 "\nnet ads search <expression> <attributes...>\n"
2270                 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2271                 "The expression is a standard LDAP search expression, and the\n"
2272                 "attributes are a list of LDAP fields to show in the results.\n\n"
2273                 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2274                 ));
2275         net_common_flags_usage(c, argc, argv);
2276         return -1;
2277 }
2278
2279
2280 /*
2281   general ADS search function. Useful in diagnosing problems in ADS
2282 */
2283 static int net_ads_search(struct net_context *c, int argc, const char **argv)
2284 {
2285         ADS_STRUCT *ads;
2286         ADS_STATUS rc;
2287         const char *ldap_exp;
2288         const char **attrs;
2289         LDAPMessage *res = NULL;
2290
2291         if (argc < 1 || c->display_usage) {
2292                 return net_ads_search_usage(c, argc, argv);
2293         }
2294
2295         if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2296                 return -1;
2297         }
2298
2299         ldap_exp = argv[0];
2300         attrs = (argv + 1);
2301
2302         rc = ads_do_search_retry(ads, ads->config.bind_path,
2303                                LDAP_SCOPE_SUBTREE,
2304                                ldap_exp, attrs, &res);
2305         if (!ADS_ERR_OK(rc)) {
2306                 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2307                 ads_destroy(&ads);
2308                 return -1;
2309         }
2310
2311         d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2312
2313         /* dump the results */
2314         ads_dump(ads, res);
2315
2316         ads_msgfree(ads, res);
2317         ads_destroy(&ads);
2318
2319         return 0;
2320 }
2321
2322
2323 /*
2324   help for net ads search
2325 */
2326 static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2327 {
2328         d_printf(_(
2329                 "\nnet ads dn <dn> <attributes...>\n"
2330                 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2331                 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2332                 "to show in the results\n\n"
2333                 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2334                 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2335                 ));
2336         net_common_flags_usage(c, argc, argv);
2337         return -1;
2338 }
2339
2340
2341 /*
2342   general ADS search function. Useful in diagnosing problems in ADS
2343 */
2344 static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2345 {
2346         ADS_STRUCT *ads;
2347         ADS_STATUS rc;
2348         const char *dn;
2349         const char **attrs;
2350         LDAPMessage *res = NULL;
2351
2352         if (argc < 1 || c->display_usage) {
2353                 return net_ads_dn_usage(c, argc, argv);
2354         }
2355
2356         if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2357                 return -1;
2358         }
2359
2360         dn = argv[0];
2361         attrs = (argv + 1);
2362
2363         rc = ads_do_search_all(ads, dn,
2364                                LDAP_SCOPE_BASE,
2365                                "(objectclass=*)", attrs, &res);
2366         if (!ADS_ERR_OK(rc)) {
2367                 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2368                 ads_destroy(&ads);
2369                 return -1;
2370         }
2371
2372         d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2373
2374         /* dump the results */
2375         ads_dump(ads, res);
2376
2377         ads_msgfree(ads, res);
2378         ads_destroy(&ads);
2379
2380         return 0;
2381 }
2382
2383 /*
2384   help for net ads sid search
2385 */
2386 static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2387 {
2388         d_printf(_(
2389                 "\nnet ads sid <sid> <attributes...>\n"
2390                 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2391                 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2392                 "to show in the results\n\n"
2393                 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2394                 ));
2395         net_common_flags_usage(c, argc, argv);
2396         return -1;
2397 }
2398
2399
2400 /*
2401   general ADS search function. Useful in diagnosing problems in ADS
2402 */
2403 static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2404 {
2405         ADS_STRUCT *ads;
2406         ADS_STATUS rc;
2407         const char *sid_string;
2408         const char **attrs;
2409         LDAPMessage *res = NULL;
2410         struct dom_sid sid;
2411
2412         if (argc < 1 || c->display_usage) {
2413                 return net_ads_sid_usage(c, argc, argv);
2414         }
2415
2416         if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2417                 return -1;
2418         }
2419
2420         sid_string = argv[0];
2421         attrs = (argv + 1);
2422
2423         if (!string_to_sid(&sid, sid_string)) {
2424                 d_fprintf(stderr, _("could not convert sid\n"));
2425                 ads_destroy(&ads);
2426                 return -1;
2427         }
2428
2429         rc = ads_search_retry_sid(ads, &res, &sid, attrs);
2430         if (!ADS_ERR_OK(rc)) {
2431                 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2432                 ads_destroy(&ads);
2433                 return -1;
2434         }
2435
2436         d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2437
2438         /* dump the results */
2439         ads_dump(ads, res);
2440
2441         ads_msgfree(ads, res);
2442         ads_destroy(&ads);
2443
2444         return 0;
2445 }
2446
2447 static int net_ads_keytab_flush(struct net_context *c, int argc, const char **argv)
2448 {
2449         int ret;
2450         ADS_STRUCT *ads;
2451
2452         if (c->display_usage) {
2453                 d_printf(  "%s\n"
2454                            "net ads keytab flush\n"
2455                            "    %s\n",
2456                          _("Usage:"),
2457                          _("Delete the whole keytab"));
2458                 return 0;
2459         }
2460
2461         if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2462                 return -1;
2463         }
2464         ret = ads_keytab_flush(ads);
2465         ads_destroy(&ads);
2466         return ret;
2467 }
2468
2469 static int net_ads_keytab_add(struct net_context *c, int argc, const char **argv)
2470 {
2471         int i;
2472         int ret = 0;
2473         ADS_STRUCT *ads;
2474
2475         if (c->display_usage) {
2476                 d_printf("%s\n%s",
2477                          _("Usage:"),
2478                          _("net ads keytab add <principal> [principal ...]\n"
2479                            "  Add principals to local keytab\n"
2480                            "    principal\tKerberos principal to add to "
2481                            "keytab\n"));
2482                 return 0;
2483         }
2484
2485         d_printf(_("Processing principals to add...\n"));
2486         if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2487                 return -1;
2488         }
2489         for (i = 0; i < argc; i++) {
2490                 ret |= ads_keytab_add_entry(ads, argv[i]);
2491         }
2492         ads_destroy(&ads);
2493         return ret;
2494 }
2495
2496 static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
2497 {
2498         ADS_STRUCT *ads;
2499         int ret;
2500
2501         if (c->display_usage) {
2502                 d_printf(  "%s\n"
2503                            "net ads keytab create\n"
2504                            "    %s\n",
2505                          _("Usage:"),
2506                          _("Create new default keytab"));
2507                 return 0;
2508         }
2509
2510         if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2511                 return -1;
2512         }
2513         ret = ads_keytab_create_default(ads);
2514         ads_destroy(&ads);
2515         return ret;
2516 }
2517
2518 static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
2519 {
2520         const char *keytab = NULL;
2521
2522         if (c->display_usage) {
2523                 d_printf("%s\n%s",
2524                          _("Usage:"),
2525                          _("net ads keytab list [keytab]\n"
2526                            "  List a local keytab\n"
2527                            "    keytab\tKeytab to list\n"));
2528                 return 0;
2529         }
2530
2531         if (argc >= 1) {
2532                 keytab = argv[0];
2533         }
2534
2535         return ads_keytab_list(keytab);
2536 }
2537
2538
2539 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
2540 {
2541         struct functable func[] = {
2542                 {
2543                         "add",
2544                         net_ads_keytab_add,
2545                         NET_TRANSPORT_ADS,
2546                         N_("Add a service principal"),
2547                         N_("net ads keytab add\n"
2548                            "    Add a service principal")
2549                 },
2550                 {
2551                         "create",
2552                         net_ads_keytab_create,
2553                         NET_TRANSPORT_ADS,
2554                         N_("Create a fresh keytab"),
2555                         N_("net ads keytab create\n"
2556                            "    Create a fresh keytab")
2557                 },
2558                 {
2559                         "flush",
2560                         net_ads_keytab_flush,
2561                         NET_TRANSPORT_ADS,
2562                         N_("Remove all keytab entries"),
2563                         N_("net ads keytab flush\n"
2564                            "    Remove all keytab entries")
2565                 },
2566                 {
2567                         "list",
2568                         net_ads_keytab_list,
2569                         NET_TRANSPORT_ADS,
2570                         N_("List a keytab"),
2571                         N_("net ads keytab list\n"
2572                            "    List a keytab")
2573                 },
2574                 {NULL, NULL, 0, NULL, NULL}
2575         };
2576
2577         if (!USE_KERBEROS_KEYTAB) {
2578                 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
2579                     "keytab method to use keytab functions.\n"));
2580         }
2581
2582         return net_run_function(c, argc, argv, "net ads keytab", func);
2583 }
2584
2585 static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
2586 {
2587         int ret = -1;
2588
2589         if (c->display_usage) {
2590                 d_printf(  "%s\n"
2591                            "net ads kerberos renew\n"
2592                            "    %s\n",
2593                          _("Usage:"),
2594                          _("Renew TGT from existing credential cache"));
2595                 return 0;
2596         }
2597
2598         ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
2599         if (ret) {
2600                 d_printf(_("failed to renew kerberos ticket: %s\n"),
2601                         error_message(ret));
2602         }
2603         return ret;
2604 }
2605
2606 static int net_ads_kerberos_pac_common(struct net_context *c, int argc, const char **argv,
2607                                        struct PAC_DATA_CTR **pac_data_ctr)
2608 {
2609         NTSTATUS status;
2610         int ret = -1;
2611         const char *impersonate_princ_s = NULL;
2612         const char *local_service = NULL;
2613         int i;
2614
2615         for (i=0; i<argc; i++) {
2616                 if (strnequal(argv[i], "impersonate", strlen("impersonate"))) {
2617                         impersonate_princ_s = get_string_param(argv[i]);
2618                         if (impersonate_princ_s == NULL) {
2619                                 return -1;
2620                         }
2621                 }
2622                 if (strnequal(argv[i], "local_service", strlen("local_service"))) {
2623                         local_service = get_string_param(argv[i]);
2624                         if (local_service == NULL) {
2625                                 return -1;
2626                         }
2627                 }
2628         }
2629
2630         if (local_service == NULL) {
2631                 local_service = talloc_asprintf(c, "%s$@%s",
2632                                                 lp_netbios_name(), lp_realm());
2633                 if (local_service == NULL) {
2634                         goto out;
2635                 }
2636         }
2637
2638         c->opt_password = net_prompt_pass(c, c->opt_user_name);
2639
2640         status = kerberos_return_pac(c,
2641                                      c->opt_user_name,
2642                                      c->opt_password,
2643                                      0,
2644                                      NULL,
2645                                      NULL,
2646                                      NULL,
2647                                      true,
2648                                      true,
2649                                      2592000, /* one month */
2650                                      impersonate_princ_s,
2651                                      local_service,
2652                                      pac_data_ctr);
2653         if (!NT_STATUS_IS_OK(status)) {
2654                 d_printf(_("failed to query kerberos PAC: %s\n"),
2655                         nt_errstr(status));
2656                 goto out;
2657         }
2658
2659         ret = 0;
2660  out:
2661         return ret;
2662 }
2663
2664 static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv)
2665 {
2666         struct PAC_DATA_CTR *pac_data_ctr = NULL;
2667         int i;
2668         int ret = -1;
2669         enum PAC_TYPE type = 0;
2670
2671         if (c->display_usage) {
2672                 d_printf(  "%s\n"
2673                            "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
2674                            "    %s\n",
2675                          _("Usage:"),
2676                          _("Dump the Kerberos PAC"));
2677                 return -1;
2678         }
2679
2680         for (i=0; i<argc; i++) {
2681                 if (strnequal(argv[i], "pac_buffer_type", strlen("pac_buffer_type"))) {
2682                         type = get_int_param(argv[i]);
2683                 }
2684         }
2685
2686         ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
2687         if (ret) {
2688                 return ret;
2689         }
2690
2691         if (type == 0) {
2692
2693                 char *s = NULL;
2694
2695                 s = NDR_PRINT_STRUCT_STRING(c, PAC_DATA,
2696                         pac_data_ctr->pac_data);
2697                 if (s != NULL) {
2698                         d_printf(_("The Pac: %s\n"), s);
2699                         talloc_free(s);
2700                 }
2701
2702                 return 0;
2703         }
2704
2705         for (i=0; i < pac_data_ctr->pac_data->num_buffers; i++) {
2706
2707                 char *s = NULL;
2708
2709                 if (pac_data_ctr->pac_data->buffers[i].type != type) {
2710                         continue;
2711                 }
2712
2713                 s = NDR_PRINT_UNION_STRING(c, PAC_INFO, type,
2714                                 pac_data_ctr->pac_data->buffers[i].info);
2715                 if (s != NULL) {
2716                         d_printf(_("The Pac: %s\n"), s);
2717                         talloc_free(s);
2718                 }
2719                 break;
2720         }
2721
2722         return 0;
2723 }
2724
2725 static int net_ads_kerberos_pac_save(struct net_context *c, int argc, const char **argv)
2726 {
2727         struct PAC_DATA_CTR *pac_data_ctr = NULL;
2728         char *filename = NULL;
2729         int ret = -1;
2730         int i;
2731
2732         if (c->display_usage) {
2733                 d_printf(  "%s\n"
2734                            "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
2735                            "    %s\n",
2736                          _("Usage:"),
2737                          _("Save the Kerberos PAC"));
2738                 return -1;
2739         }
2740
2741         for (i=0; i<argc; i++) {
2742                 if (strnequal(argv[i], "filename", strlen("filename"))) {
2743                         filename = get_string_param(argv[i]);
2744                         if (filename == NULL) {
2745                                 return -1;
2746                         }
2747                 }
2748         }
2749
2750         ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
2751         if (ret) {
2752                 return ret;
2753         }
2754
2755         if (filename == NULL) {
2756                 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
2757                 return -1;
2758         }
2759
2760         /* save the raw format */
2761         if (!file_save(filename, pac_data_ctr->pac_blob.data, pac_data_ctr->pac_blob.length)) {
2762                 d_printf(_("failed to save PAC in %s\n"), filename);
2763                 return -1;
2764         }
2765
2766         return 0;
2767 }
2768
2769 static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
2770 {
2771         struct functable func[] = {
2772                 {
2773                         "dump",
2774                         net_ads_kerberos_pac_dump,
2775                         NET_TRANSPORT_ADS,
2776                         N_("Dump Kerberos PAC"),
2777                         N_("net ads kerberos pac dump\n"
2778                            "    Dump a Kerberos PAC to stdout")
2779                 },
2780                 {
2781                         "save",
2782                         net_ads_kerberos_pac_save,
2783                         NET_TRANSPORT_ADS,
2784                         N_("Save Kerberos PAC"),
2785                         N_("net ads kerberos pac save\n"
2786                            "    Save a Kerberos PAC in a file")
2787                 },
2788
2789                 {NULL, NULL, 0, NULL, NULL}
2790         };
2791
2792         return net_run_function(c, argc, argv, "net ads kerberos pac", func);
2793 }
2794
2795 static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
2796 {
2797         TALLOC_CTX *mem_ctx = NULL;
2798         int ret = -1;
2799         NTSTATUS status;
2800
2801         if (c->display_usage) {
2802                 d_printf(  "%s\n"
2803                            "net ads kerberos kinit\n"
2804                            "    %s\n",
2805                          _("Usage:"),
2806                          _("Get Ticket Granting Ticket (TGT) for the user"));
2807                 return 0;
2808         }
2809
2810         mem_ctx = talloc_init("net_ads_kerberos_kinit");
2811         if (!mem_ctx) {
2812                 goto out;
2813         }
2814
2815         c->opt_password = net_prompt_pass(c, c->opt_user_name);
2816
2817         ret = kerberos_kinit_password_ext(c->opt_user_name,
2818                                           c->opt_password,
2819                                           0,
2820                                           NULL,
2821                                           NULL,
2822                                           NULL,
2823                                           true,
2824                                           true,
2825                                           2592000, /* one month */
2826                                           &status);
2827         if (ret) {
2828                 d_printf(_("failed to kinit password: %s\n"),
2829                         nt_errstr(status));
2830         }
2831  out:
2832         return ret;
2833 }
2834
2835 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
2836 {
2837         struct functable func[] = {
2838                 {
2839                         "kinit",
2840                         net_ads_kerberos_kinit,
2841                         NET_TRANSPORT_ADS,
2842                         N_("Retrieve Ticket Granting Ticket (TGT)"),
2843                         N_("net ads kerberos kinit\n"
2844                            "    Receive Ticket Granting Ticket (TGT)")
2845                 },
2846                 {
2847                         "renew",
2848                         net_ads_kerberos_renew,
2849                         NET_TRANSPORT_ADS,
2850                         N_("Renew Ticket Granting Ticket from credential cache"),
2851                         N_("net ads kerberos renew\n"
2852                            "    Renew Ticket Granting Ticket (TGT) from "
2853                            "credential cache")
2854                 },
2855                 {
2856                         "pac",
2857                         net_ads_kerberos_pac,
2858                         NET_TRANSPORT_ADS,
2859                         N_("Dump Kerberos PAC"),
2860                         N_("net ads kerberos pac\n"
2861                            "    Dump Kerberos PAC")
2862                 },
2863                 {NULL, NULL, 0, NULL, NULL}
2864         };
2865
2866         return net_run_function(c, argc, argv, "net ads kerberos", func);
2867 }
2868
2869 static int net_ads_enctype_lookup_account(struct net_context *c,
2870                                           ADS_STRUCT *ads,
2871                                           const char *account,
2872                                           LDAPMessage **res,
2873                                           const char **enctype_str)
2874 {
2875         const char *filter;
2876         const char *attrs[] = {
2877                 "msDS-SupportedEncryptionTypes",
2878                 NULL
2879         };
2880         int count;
2881         int ret = -1;
2882         ADS_STATUS status;
2883
2884         filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))",
2885                                  account);
2886         if (filter == NULL) {
2887                 goto done;
2888         }
2889
2890         status = ads_search(ads, res, filter, attrs);
2891         if (!ADS_ERR_OK(status)) {
2892                 d_printf(_("no account found with filter: %s\n"), filter);
2893                 goto done;
2894         }
2895
2896         count = ads_count_replies(ads, *res);
2897         switch (count) {
2898         case 1:
2899                 break;
2900         case 0:
2901                 d_printf(_("no account found with filter: %s\n"), filter);
2902                 goto done;
2903         default:
2904                 d_printf(_("multiple accounts found with filter: %s\n"), filter);
2905                 goto done;
2906         }
2907
2908         if (enctype_str) {
2909                 *enctype_str = ads_pull_string(ads, c, *res,
2910                                                "msDS-SupportedEncryptionTypes");
2911                 if (*enctype_str == NULL) {
2912                         d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
2913                         goto done;
2914                 }
2915         }
2916
2917         ret = 0;
2918  done:
2919         return ret;
2920 }
2921
2922 static void net_ads_enctype_dump_enctypes(const char *username,
2923                                           const char *enctype_str)
2924 {
2925         int enctypes = atoi(enctype_str);
2926
2927         d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
2928                 username, enctypes, enctypes);
2929
2930         printf("[%s] 0x%08x DES-CBC-CRC\n",
2931                 enctypes & ENC_CRC32 ? "X" : " ",
2932                 ENC_CRC32);
2933         printf("[%s] 0x%08x DES-CBC-MD5\n",
2934                 enctypes & ENC_RSA_MD5 ? "X" : " ",
2935                 ENC_RSA_MD5);
2936         printf("[%s] 0x%08x RC4-HMAC\n",
2937                 enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ",
2938                 ENC_RC4_HMAC_MD5);
2939         printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
2940                 enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ",
2941                 ENC_HMAC_SHA1_96_AES128);
2942         printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
2943                 enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
2944                 ENC_HMAC_SHA1_96_AES256);
2945 }
2946
2947 static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
2948 {
2949         int ret = -1;
2950         ADS_STATUS status;
2951         ADS_STRUCT *ads = NULL;
2952         LDAPMessage *res = NULL;
2953         const char *str = NULL;
2954
2955         if (c->display_usage || (argc < 1)) {
2956                 d_printf(  "%s\n"
2957                            "net ads enctypes list\n"
2958                            "    %s\n",
2959                          _("Usage:"),
2960                          _("List supported enctypes"));
2961                 return 0;
2962         }
2963
2964         status = ads_startup(c, false, &ads);
2965         if (!ADS_ERR_OK(status)) {
2966                 printf("startup failed\n");
2967                 return ret;
2968         }
2969
2970         ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
2971         if (ret) {
2972                 goto done;
2973         }
2974
2975         net_ads_enctype_dump_enctypes(argv[0], str);
2976
2977         ret = 0;
2978  done:
2979         ads_msgfree(ads, res);
2980         ads_destroy(&ads);
2981
2982         return ret;
2983 }
2984
2985 static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
2986 {
2987         int ret = -1;
2988         ADS_STATUS status;
2989         ADS_STRUCT *ads;
2990         LDAPMessage *res = NULL;
2991         const char *etype_list_str;
2992         const char *dn;
2993         ADS_MODLIST mods;
2994         uint32_t etype_list;
2995         const char *str;
2996
2997         if (c->display_usage || argc < 1) {
2998                 d_printf(  "%s\n"
2999                            "net ads enctypes set <sAMAccountName> [enctypes]\n"
3000                            "    %s\n",
3001                          _("Usage:"),
3002                          _("Set supported enctypes"));
3003                 return 0;
3004         }
3005
3006         status = ads_startup(c, false, &ads);
3007         if (!ADS_ERR_OK(status)) {
3008                 printf("startup failed\n");
3009                 return ret;
3010         }
3011
3012         ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3013         if (ret) {
3014                 goto done;
3015         }
3016
3017         dn = ads_get_dn(ads, c, res);
3018         if (dn == NULL) {
3019                 goto done;
3020         }
3021
3022         etype_list = ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5;
3023 #ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
3024         etype_list |= ENC_HMAC_SHA1_96_AES128;
3025 #endif
3026 #ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
3027         etype_list |= ENC_HMAC_SHA1_96_AES256;
3028 #endif
3029
3030         if (argv[1] != NULL) {
3031                 sscanf(argv[1], "%i", &etype_list);
3032         }
3033
3034         etype_list_str = talloc_asprintf(c, "%d", etype_list);
3035         if (!etype_list_str) {
3036                 goto done;
3037         }
3038
3039         mods = ads_init_mods(c);
3040         if (!mods) {
3041                 goto done;
3042         }
3043
3044         status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes",
3045                              etype_list_str);
3046         if (!ADS_ERR_OK(status)) {
3047                 goto done;
3048         }
3049
3050         status = ads_gen_mod(ads, dn, mods);
3051         if (!ADS_ERR_OK(status)) {
3052                 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3053                         ads_errstr(status));
3054                 goto done;
3055         }
3056
3057         ads_msgfree(ads, res);
3058
3059         ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3060         if (ret) {
3061                 goto done;
3062         }
3063
3064         net_ads_enctype_dump_enctypes(argv[0], str);
3065
3066         ret = 0;
3067  done:
3068         ads_msgfree(ads, res);
3069         ads_destroy(&ads);
3070
3071         return ret;
3072 }
3073
3074 static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
3075 {
3076         int ret = -1;
3077         ADS_STATUS status;
3078         ADS_STRUCT *ads;
3079         LDAPMessage *res = NULL;
3080         const char *dn;
3081         ADS_MODLIST mods;
3082
3083         if (c->display_usage || argc < 1) {
3084                 d_printf(  "%s\n"
3085                            "net ads enctypes delete <sAMAccountName>\n"
3086                            "    %s\n",
3087                          _("Usage:"),
3088                          _("Delete supported enctypes"));
3089                 return 0;
3090         }
3091
3092         status = ads_startup(c, false, &ads);
3093         if (!ADS_ERR_OK(status)) {
3094                 printf("startup failed\n");
3095                 return ret;
3096         }
3097
3098         ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3099         if (ret) {
3100                 goto done;
3101         }
3102
3103         dn = ads_get_dn(ads, c, res);
3104         if (dn == NULL) {
3105                 goto done;
3106         }
3107
3108         mods = ads_init_mods(c);
3109         if (!mods) {
3110                 goto done;
3111         }
3112
3113         status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes", NULL);
3114         if (!ADS_ERR_OK(status)) {
3115                 goto done;
3116         }
3117
3118         status = ads_gen_mod(ads, dn, mods);
3119         if (!ADS_ERR_OK(status)) {
3120                 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3121                         ads_errstr(status));
3122                 goto done;
3123         }
3124
3125         ret = 0;
3126
3127  done:
3128         ads_msgfree(ads, res);
3129         ads_destroy(&ads);
3130         return ret;
3131 }
3132
3133 static int net_ads_enctypes(struct net_context *c, int argc, const char **argv)
3134 {
3135         struct functable func[] = {
3136                 {
3137                         "list",
3138                         net_ads_enctypes_list,
3139                         NET_TRANSPORT_ADS,
3140                         N_("List the supported encryption types"),
3141                         N_("net ads enctypes list\n"
3142                            "    List the supported encryption types")
3143                 },
3144                 {
3145                         "set",
3146                         net_ads_enctypes_set,
3147                         NET_TRANSPORT_ADS,
3148                         N_("Set the supported encryption types"),
3149                         N_("net ads enctypes set\n"
3150                            "    Set the supported encryption types")
3151                 },
3152                 {
3153                         "delete",
3154                         net_ads_enctypes_delete,
3155                         NET_TRANSPORT_ADS,
3156                         N_("Delete the supported encryption types"),
3157                         N_("net ads enctypes delete\n"
3158                            "    Delete the supported encryption types")
3159                 },
3160
3161                 {NULL, NULL, 0, NULL, NULL}
3162         };
3163
3164         return net_run_function(c, argc, argv, "net ads enctypes", func);
3165 }
3166
3167
3168 int net_ads(struct net_context *c, int argc, const char **argv)
3169 {
3170         struct functable func[] = {
3171                 {
3172                         "info",
3173                         net_ads_info,
3174                         NET_TRANSPORT_ADS,
3175                         N_("Display details on remote ADS server"),
3176                         N_("net ads info\n"
3177                            "    Display details on remote ADS server")
3178                 },
3179                 {
3180                         "join",
3181                         net_ads_join,
3182                         NET_TRANSPORT_ADS,
3183                         N_("Join the local machine to ADS realm"),
3184                         N_("net ads join\n"
3185                            "    Join the local machine to ADS realm")
3186                 },
3187                 {
3188                         "testjoin",
3189                         net_ads_testjoin,
3190                         NET_TRANSPORT_ADS,
3191                         N_("Validate machine account"),
3192                         N_("net ads testjoin\n"
3193                            "    Validate machine account")
3194                 },
3195                 {
3196                         "leave",
3197                         net_ads_leave,
3198                         NET_TRANSPORT_ADS,
3199                         N_("Remove the local machine from ADS"),
3200                         N_("net ads leave\n"
3201                            "    Remove the local machine from ADS")
3202                 },
3203                 {
3204                         "status",
3205                         net_ads_status,
3206                         NET_TRANSPORT_ADS,
3207                         N_("Display machine account details"),
3208                         N_("net ads status\n"
3209                            "    Display machine account details")
3210                 },
3211                 {
3212                         "user",
3213                         net_ads_user,
3214                         NET_TRANSPORT_ADS,
3215                         N_("List/modify users"),
3216                         N_("net ads user\n"
3217                            "    List/modify users")
3218                 },
3219                 {
3220                         "group",
3221                         net_ads_group,
3222                         NET_TRANSPORT_ADS,
3223                         N_("List/modify groups"),
3224                         N_("net ads group\n"
3225                            "    List/modify groups")
3226                 },
3227                 {
3228                         "dns",
3229                         net_ads_dns,
3230                         NET_TRANSPORT_ADS,
3231                         N_("Issue dynamic DNS update"),
3232                         N_("net ads dns\n"
3233                            "    Issue dynamic DNS update")
3234                 },
3235                 {
3236                         "password",
3237                         net_ads_password,
3238                         NET_TRANSPORT_ADS,
3239                         N_("Change user passwords"),
3240                         N_("net ads password\n"
3241                            "    Change user passwords")
3242                 },
3243                 {
3244                         "changetrustpw",
3245                         net_ads_changetrustpw,
3246                         NET_TRANSPORT_ADS,
3247                         N_("Change trust account password"),
3248                         N_("net ads changetrustpw\n"
3249                            "    Change trust account password")
3250                 },
3251                 {
3252                         "printer",
3253                         net_ads_printer,
3254                         NET_TRANSPORT_ADS,
3255                         N_("List/modify printer entries"),
3256                         N_("net ads printer\n"
3257                            "    List/modify printer entries")
3258                 },
3259                 {
3260                         "search",
3261                         net_ads_search,
3262                         NET_TRANSPORT_ADS,
3263                         N_("Issue LDAP search using filter"),
3264                         N_("net ads search\n"
3265                            "    Issue LDAP search using filter")
3266                 },
3267                 {
3268                         "dn",
3269                         net_ads_dn,
3270                         NET_TRANSPORT_ADS,
3271                         N_("Issue LDAP search by DN"),
3272                         N_("net ads dn\n"
3273                            "    Issue LDAP search by DN")
3274                 },
3275                 {
3276                         "sid",
3277                         net_ads_sid,
3278                         NET_TRANSPORT_ADS,
3279                         N_("Issue LDAP search by SID"),
3280                         N_("net ads sid\n"
3281                            "    Issue LDAP search by SID")
3282                 },
3283                 {
3284                         "workgroup",
3285                         net_ads_workgroup,
3286                         NET_TRANSPORT_ADS,
3287                         N_("Display workgroup name"),
3288                         N_("net ads workgroup\n"
3289                            "    Display the workgroup name")
3290                 },
3291                 {
3292                         "lookup",
3293                         net_ads_lookup,
3294                         NET_TRANSPORT_ADS,
3295                         N_("Perfom CLDAP query on DC"),
3296                         N_("net ads lookup\n"
3297                            "    Find the ADS DC using CLDAP lookups")
3298                 },
3299                 {
3300                         "keytab",
3301                         net_ads_keytab,
3302                         NET_TRANSPORT_ADS,
3303                         N_("Manage local keytab file"),
3304                         N_("net ads keytab\n"
3305                            "    Manage local keytab file")
3306                 },
3307                 {
3308                         "gpo",
3309                         net_ads_gpo,
3310                         NET_TRANSPORT_ADS,
3311                         N_("Manage group policy objects"),
3312                         N_("net ads gpo\n"
3313                            "    Manage group policy objects")
3314                 },
3315                 {
3316                         "kerberos",
3317                         net_ads_kerberos,
3318                         NET_TRANSPORT_ADS,
3319                         N_("Manage kerberos keytab"),
3320                         N_("net ads kerberos\n"
3321                            "    Manage kerberos keytab")
3322                 },
3323                 {
3324                         "enctypes",
3325                         net_ads_enctypes,
3326                         NET_TRANSPORT_ADS,
3327                         N_("List/modify supported encryption types"),
3328                         N_("net ads enctypes\n"
3329                            "    List/modify enctypes")
3330                 },
3331                 {NULL, NULL, 0, NULL, NULL}
3332         };
3333
3334         return net_run_function(c, argc, argv, "net ads", func);
3335 }
3336
3337 #else
3338
3339 static int net_ads_noads(void)
3340 {
3341         d_fprintf(stderr, _("ADS support not compiled in\n"));
3342         return -1;
3343 }
3344
3345 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
3346 {
3347         return net_ads_noads();
3348 }
3349
3350 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3351 {
3352         return net_ads_noads();
3353 }
3354
3355 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
3356 {
3357         return net_ads_noads();
3358 }
3359
3360 int net_ads_join(struct net_context *c, int argc, const char **argv)
3361 {
3362         return net_ads_noads();
3363 }
3364
3365 int net_ads_user(struct net_context *c, int argc, const char **argv)
3366 {
3367         return net_ads_noads();
3368 }
3369
3370 int net_ads_group(struct net_context *c, int argc, const char **argv)
3371 {
3372         return net_ads_noads();
3373 }
3374
3375 int net_ads_gpo(struct net_context *c, int argc, const char **argv)
3376 {
3377         return net_ads_noads();
3378 }
3379
3380 /* this one shouldn't display a message */
3381 int net_ads_check(struct net_context *c)
3382 {
3383         return -1;
3384 }
3385
3386 int net_ads_check_our_domain(struct net_context *c)
3387 {
3388         return -1;
3389 }
3390
3391 int net_ads(struct net_context *c, int argc, const char **argv)
3392 {
3393         return net_ads_noads();
3394 }
3395
3396 #endif  /* HAVE_ADS */