LCOV - code coverage report
Current view: top level - source3/libads - util.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 81 122 66.4 %
Date: 2024-04-21 15:09:00 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           0 :         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           0 :         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           0 :         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           4 :         status = secrets_prepare_password_change(domain,
      56             :                                                  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           4 :         ok = convert_string_talloc(talloc_tos(), CH_UTF16MUNGED, CH_UNIX,
      74           4 :                                    cleartext_blob->data,
      75           4 :                                    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           4 :         ok = convert_string_talloc(talloc_tos(), CH_UTF16MUNGED, CH_UNIX,
      92           4 :                                    cleartext_blob->data,
      93           4 :                                    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 :         talloc_keep_secret(new_pw_blob.data);
     111           4 :         new_password = (const char *)new_pw_blob.data;
     112             : 
     113           4 :         ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password, host_principal, new_password, ads->auth.time_offset);
     114             : 
     115           4 :         if (!ADS_ERR_OK(ret)) {
     116           0 :                 status = ads_ntstatus(ret);
     117           0 :                 DBG_ERR("kerberos_set_password(%s, %s) "
     118             :                         "failed for new_password of %s - %s\n",
     119             :                         ads->auth.kdc_server, host_principal,
     120             :                         domain, nt_errstr(status));
     121           0 :                 secrets_failed_password_change(ads->auth.kdc_server,
     122           0 :                                                NT_STATUS_NOT_COMMITTED,
     123             :                                                status,
     124             :                                                info);
     125           0 :                 return ret;
     126             :         }
     127             : 
     128           4 :         status = secrets_finish_password_change(ads->auth.kdc_server, now, info);
     129           4 :         if (!NT_STATUS_IS_OK(status)) {
     130           0 :                 DEBUG(1,("Failed to save machine password\n"));
     131           0 :                 return ADS_ERROR_NT(status);
     132             :         }
     133             : 
     134           4 :         return ADS_SUCCESS;
     135             : }
     136             : #endif
     137             : 
     138             : /**
     139             : * @brief Parses windows style SPN service/host:port/servicename
     140             : *      serviceclass - A string that identifies the general class of service
     141             : *            e.g. 'http'
     142             : *      host - A netbios name or fully-qualified DNS name
     143             : *      port - An optional TCP or UDP port number
     144             : *      servicename - An optional distinguished name, GUID, DNS name or
     145             : *                    DNS name of an SRV or MX record. (not needed for host
     146             : *                    based services)
     147             : *
     148             : * @param[in]  ctx       - Talloc context.
     149             : * @param[in]  srvprinc  - The service principal
     150             : *
     151             : * @return               - struct spn_struct containing the fields parsed or NULL
     152             : *                         if srvprinc could not be parsed.
     153             : */
     154          18 : struct spn_struct *parse_spn(TALLOC_CTX *ctx, const char *srvprinc)
     155             : {
     156          18 :         struct spn_struct * result = NULL;
     157          18 :         char *tmp = NULL;
     158          18 :         char *port_str = NULL;
     159          18 :         char *host_str = NULL;
     160             : 
     161          18 :         result = talloc_zero(ctx, struct spn_struct);
     162          18 :         if (result == NULL) {
     163           0 :                 DBG_ERR("Out of memory\n");
     164           0 :                 return NULL;
     165             :         }
     166             : 
     167          18 :         result->serviceclass = talloc_strdup(result, srvprinc);
     168          18 :         if (result->serviceclass == NULL) {
     169           0 :                 DBG_ERR("Out of memory\n");
     170           0 :                 goto fail;
     171             :         }
     172          18 :         result->port = -1;
     173             : 
     174          18 :         tmp = strchr_m(result->serviceclass, '/');
     175          18 :         if (tmp == NULL) {
     176             :                 /* illegal */
     177           2 :                 DBG_ERR("Failed to parse spn %s, no host definition\n",
     178             :                         srvprinc);
     179           2 :                 goto fail;
     180             :         }
     181             : 
     182             :         /* terminate service principal */
     183          16 :         *tmp = '\0';
     184          16 :         tmp++;
     185          16 :         host_str = tmp;
     186             : 
     187          16 :         tmp = strchr_m(host_str, ':');
     188          16 :         if (tmp != NULL) {
     189           6 :                 *tmp  = '\0';
     190           6 :                 tmp++;
     191           6 :                 port_str = tmp;
     192             :         } else {
     193          10 :                 tmp = host_str;
     194             :         }
     195             : 
     196          16 :         tmp = strchr_m(tmp, '/');
     197          16 :         if (tmp != NULL) {
     198           2 :                 *tmp  = '\0';
     199           2 :                 tmp++;
     200           2 :                 result->servicename = tmp;
     201             :         }
     202             : 
     203          16 :         if (strlen(host_str) == 0) {
     204             :                 /* illegal */
     205           0 :                 DBG_ERR("Failed to parse spn %s, illegal host definition\n",
     206             :                         srvprinc);
     207           0 :                 goto fail;
     208             :         }
     209          16 :         result->host = host_str;
     210             : 
     211          16 :         if (result->servicename != NULL && (strlen(result->servicename) == 0)) {
     212           2 :                 DBG_ERR("Failed to parse spn %s, empty servicename "
     213             :                         "definition\n", srvprinc);
     214           2 :                 goto fail;
     215             :         }
     216          14 :         if (port_str != NULL) {
     217           6 :                 if (strlen(port_str) == 0) {
     218           2 :                         DBG_ERR("Failed to parse spn %s, empty port "
     219             :                                 "definition\n", srvprinc);
     220           2 :                         goto fail;
     221             :                 }
     222           4 :                 result->port = (int32_t)strtol(port_str, NULL, 10);
     223           4 :                 if (result->port <= 0
     224           4 :                     || result->port > 65535
     225           4 :                     || errno == ERANGE) {
     226           0 :                         DBG_ERR("Failed to parse spn %s, port number "
     227             :                                 "conversion failed\n", srvprinc);
     228           0 :                         errno = 0;
     229           0 :                         goto fail;
     230             :                 }
     231             :         }
     232          12 :         return result;
     233           6 : fail:
     234           6 :         TALLOC_FREE(result);
     235           6 :         return NULL;
     236             : }

Generated by: LCOV version 1.14