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