LCOV - code coverage report
Current view: top level - source3/utils - net_ads.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 721 1800 40.1 %
Date: 2021-09-23 10:06:22 Functions: 43 85 50.6 %

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

Generated by: LCOV version 1.13