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