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

Generated by: LCOV version 1.14