LCOV - code coverage report
Current view: top level - source3/libads - util.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 81 119 68.1 %
Date: 2021-09-23 10:06:22 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    krb5 set password implementation
       4             :    Copyright (C) Remus Koos 2001 (remuskoos@yahoo.com)
       5             :    
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             :    
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             :    
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "ads.h"
      22             : #include "secrets.h"
      23             : #include "librpc/gen_ndr/ndr_secrets.h"
      24             : 
      25             : #ifdef HAVE_KRB5
      26           4 : ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_principal)
      27             : {
      28           4 :         const char *password = NULL;
      29           4 :         const char *new_password = NULL;
      30             :         ADS_STATUS ret;
      31           4 :         const char *domain = lp_workgroup();
      32           4 :         struct secrets_domain_info1 *info = NULL;
      33           4 :         struct secrets_domain_info1_change *prev = NULL;
      34           4 :         const DATA_BLOB *cleartext_blob = NULL;
      35           4 :         DATA_BLOB pw_blob = data_blob_null;
      36           4 :         DATA_BLOB new_pw_blob = data_blob_null;
      37             :         NTSTATUS status;
      38           4 :         struct timeval tv = timeval_current();
      39           4 :         NTTIME now = timeval_to_nttime(&tv);
      40           4 :         int role = lp_server_role();
      41             :         bool ok;
      42             : 
      43           4 :         if (role != ROLE_DOMAIN_MEMBER) {
      44           0 :                 DBG_ERR("Machine account password change only supported on a DOMAIN_MEMBER.\n");
      45           0 :                 return ADS_ERROR_NT(NT_STATUS_INVALID_SERVER_STATE);
      46             :         }
      47             : 
      48           4 :         new_password = trust_pw_new_value(talloc_tos(), SEC_CHAN_WKSTA, SEC_ADS);
      49           4 :         if (new_password == NULL) {
      50           0 :                 ret = ADS_ERROR_SYSTEM(errno);
      51           0 :                 DEBUG(1,("Failed to generate machine password\n"));
      52           0 :                 return ret;
      53             :         }
      54             : 
      55           6 :         status = secrets_prepare_password_change(domain,
      56           4 :                                                  ads->auth.kdc_server,
      57             :                                                  new_password,
      58             :                                                  talloc_tos(),
      59             :                                                  &info, &prev);
      60           4 :         if (!NT_STATUS_IS_OK(status)) {
      61           0 :                 return ADS_ERROR_NT(status);
      62             :         }
      63           4 :         if (prev != NULL) {
      64           0 :                 status = NT_STATUS_REQUEST_NOT_ACCEPTED;
      65           0 :                 secrets_failed_password_change("localhost",
      66             :                                                status,
      67           0 :                                                NT_STATUS_NOT_COMMITTED,
      68             :                                                info);
      69           0 :                 return ADS_ERROR_NT(status);
      70             :         }
      71             : 
      72           4 :         cleartext_blob = &info->password->cleartext_blob;
      73           6 :         ok = convert_string_talloc(talloc_tos(), CH_UTF16MUNGED, CH_UNIX,
      74           4 :                                    cleartext_blob->data,
      75           2 :                                    cleartext_blob->length,
      76             :                                    (void **)&pw_blob.data,
      77             :                                    &pw_blob.length);
      78           4 :         if (!ok) {
      79           0 :                 status = NT_STATUS_UNMAPPABLE_CHARACTER;
      80           0 :                 if (errno == ENOMEM) {
      81           0 :                         status = NT_STATUS_NO_MEMORY;
      82             :                 }
      83           0 :                 DBG_ERR("convert_string_talloc(CH_UTF16MUNGED, CH_UNIX) "
      84             :                         "failed for password of %s - %s\n",
      85             :                         domain, nt_errstr(status));
      86           0 :                 return ADS_ERROR_NT(status);
      87             :         }
      88           4 :         password = (const char *)pw_blob.data;
      89             : 
      90           4 :         cleartext_blob = &info->next_change->password->cleartext_blob;
      91           6 :         ok = convert_string_talloc(talloc_tos(), CH_UTF16MUNGED, CH_UNIX,
      92           4 :                                    cleartext_blob->data,
      93           2 :                                    cleartext_blob->length,
      94             :                                    (void **)&new_pw_blob.data,
      95             :                                    &new_pw_blob.length);
      96           4 :         if (!ok) {
      97           0 :                 status = NT_STATUS_UNMAPPABLE_CHARACTER;
      98           0 :                 if (errno == ENOMEM) {
      99           0 :                         status = NT_STATUS_NO_MEMORY;
     100             :                 }
     101           0 :                 DBG_ERR("convert_string_talloc(CH_UTF16MUNGED, CH_UNIX) "
     102             :                         "failed for new_password of %s - %s\n",
     103             :                         domain, nt_errstr(status));
     104           0 :                 secrets_failed_password_change("localhost",
     105             :                                                status,
     106           0 :                                                NT_STATUS_NOT_COMMITTED,
     107             :                                                info);
     108           0 :                 return ADS_ERROR_NT(status);
     109             :         }
     110           4 :         new_password = (const char *)new_pw_blob.data;
     111             : 
     112           4 :         ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password, host_principal, new_password, ads->auth.time_offset);
     113             : 
     114           4 :         if (!ADS_ERR_OK(ret)) {
     115           0 :                 status = ads_ntstatus(ret);
     116           0 :                 DBG_ERR("kerberos_set_password(%s, %s) "
     117             :                         "failed for new_password of %s - %s\n",
     118             :                         ads->auth.kdc_server, host_principal,
     119             :                         domain, nt_errstr(status));
     120           0 :                 secrets_failed_password_change(ads->auth.kdc_server,
     121           0 :                                                NT_STATUS_NOT_COMMITTED,
     122             :                                                status,
     123             :                                                info);
     124           0 :                 return ret;
     125             :         }
     126             : 
     127           4 :         status = secrets_finish_password_change(ads->auth.kdc_server, now, info);
     128           4 :         if (!NT_STATUS_IS_OK(status)) {
     129           0 :                 DEBUG(1,("Failed to save machine password\n"));
     130           0 :                 return ADS_ERROR_NT(status);
     131             :         }
     132             : 
     133           4 :         return ADS_SUCCESS;
     134             : }
     135             : #endif
     136             : 
     137             : /**
     138             : * @brief Parses windows style SPN service/host:port/servicename
     139             : *      serviceclass - A string that identifies the general class of service
     140             : *            e.g. 'http'
     141             : *      host - A netbios name or fully-qualified DNS name
     142             : *      port - An optional TCP or UDP port number
     143             : *      servicename - An optional distinguished name, GUID, DNS name or
     144             : *                    DNS name of an SRV or MX record. (not needed for host
     145             : *                    based services)
     146             : *
     147             : * @param[in]  ctx       - Talloc context.
     148             : * @param[in]  srvprinc  - The service principal
     149             : *
     150             : * @return               - struct spn_struct containing the fields parsed or NULL
     151             : *                         if srvprinc could not be parsed.
     152             : */
     153          14 : struct spn_struct *parse_spn(TALLOC_CTX *ctx, const char *srvprinc)
     154             : {
     155          14 :         struct spn_struct * result = NULL;
     156          14 :         char *tmp = NULL;
     157          14 :         char *port_str = NULL;
     158          14 :         char *host_str = NULL;
     159             : 
     160          14 :         result = talloc_zero(ctx, struct spn_struct);
     161          14 :         if (result == NULL) {
     162           0 :                 DBG_ERR("Out of memory\n");
     163           0 :                 return NULL;
     164             :         }
     165             : 
     166          14 :         result->serviceclass = talloc_strdup(result, srvprinc);
     167          14 :         if (result->serviceclass == NULL) {
     168           0 :                 DBG_ERR("Out of memory\n");
     169           0 :                 goto fail;
     170             :         }
     171          14 :         result->port = -1;
     172             : 
     173          14 :         tmp = strchr_m(result->serviceclass, '/');
     174          14 :         if (tmp == NULL) {
     175             :                 /* illegal */
     176           2 :                 DBG_ERR("Failed to parse spn %s, no host definition\n",
     177             :                         srvprinc);
     178           2 :                 goto fail;
     179             :         }
     180             : 
     181             :         /* terminate service principal */
     182          12 :         *tmp = '\0';
     183          12 :         tmp++;
     184          12 :         host_str = tmp;
     185             : 
     186          12 :         tmp = strchr_m(host_str, ':');
     187          12 :         if (tmp != NULL) {
     188           4 :                 *tmp  = '\0';
     189           4 :                 tmp++;
     190           4 :                 port_str = tmp;
     191             :         } else {
     192           8 :                 tmp = host_str;
     193             :         }
     194             : 
     195          12 :         tmp = strchr_m(tmp, '/');
     196          12 :         if (tmp != NULL) {
     197           2 :                 *tmp  = '\0';
     198           2 :                 tmp++;
     199           2 :                 result->servicename = tmp;
     200             :         }
     201             : 
     202          12 :         if (strlen(host_str) == 0) {
     203             :                 /* illegal */
     204           0 :                 DBG_ERR("Failed to parse spn %s, illegal host definition\n",
     205             :                         srvprinc);
     206           0 :                 goto fail;
     207             :         }
     208          12 :         result->host = host_str;
     209             : 
     210          12 :         if (result->servicename != NULL && (strlen(result->servicename) == 0)) {
     211           2 :                 DBG_ERR("Failed to parse spn %s, empty servicename "
     212             :                         "definition\n", srvprinc);
     213           2 :                 goto fail;
     214             :         }
     215          10 :         if (port_str != NULL) {
     216           4 :                 if (strlen(port_str) == 0) {
     217           2 :                         DBG_ERR("Failed to parse spn %s, empty port "
     218             :                                 "definition\n", srvprinc);
     219           2 :                         goto fail;
     220             :                 }
     221           2 :                 result->port = (int32_t)strtol(port_str, NULL, 10);
     222           2 :                 if (result->port <= 0
     223           2 :                     || result->port > 65535
     224           2 :                     || errno == ERANGE) {
     225           0 :                         DBG_ERR("Failed to parse spn %s, port number "
     226             :                                 "conversion failed\n", srvprinc);
     227           0 :                         errno = 0;
     228           0 :                         goto fail;
     229             :                 }
     230             :         }
     231           8 :         return result;
     232           6 : fail:
     233           6 :         TALLOC_FREE(result);
     234           6 :         return NULL;
     235             : }

Generated by: LCOV version 1.13