LCOV - code coverage report
Current view: top level - source3/utils - net_ads.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 745 1951 38.2 %
Date: 2024-05-31 13:13:24 Functions: 40 77 51.9 %

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

Generated by: LCOV version 1.14