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