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