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