LCOV - code coverage report
Current view: top level - source3/utils - net_ads.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 785 1995 39.3 %
Date: 2024-04-21 15:09:00 Functions: 40 77 51.9 %

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

Generated by: LCOV version 1.14