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