LCOV - code coverage report
Current view: top level - source3/utils - net_ads.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 557 1846 30.2 %
Date: 2024-06-13 04:01:37 Functions: 25 74 33.8 %

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

Generated by: LCOV version 1.13