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