LCOV - code coverage report
Current view: top level - source4/auth/kerberos - srv_keytab.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 135 231 58.4 %
Date: 2024-05-31 13:13:24 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Kerberos utility functions
       5             : 
       6             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      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             : /**
      24             :  * @file srv_keytab.c
      25             :  *
      26             :  * @brief Kerberos keytab utility functions
      27             :  *
      28             :  */
      29             : 
      30             : #include "includes.h"
      31             : #include "system/kerberos.h"
      32             : #include "auth/credentials/credentials.h"
      33             : #include "auth/credentials/credentials_krb5.h"
      34             : #include "auth/kerberos/kerberos.h"
      35             : #include "auth/kerberos/kerberos_util.h"
      36             : #include "auth/kerberos/kerberos_srv_keytab.h"
      37             : #include "librpc/gen_ndr/ndr_gmsa.h"
      38             : #include "dsdb/samdb/samdb.h"
      39             : 
      40         348 : static void keytab_principals_free(krb5_context context,
      41             :                                    uint32_t num_principals,
      42             :                                    krb5_principal *set)
      43             : {
      44          26 :         uint32_t i;
      45             : 
      46        1178 :         for (i = 0; i < num_principals; i++) {
      47         830 :                 krb5_free_principal(context, set[i]);
      48             :         }
      49         322 : }
      50             : 
      51         347 : static krb5_error_code keytab_add_keys(TALLOC_CTX *parent_ctx,
      52             :                                        uint32_t num_principals,
      53             :                                        krb5_principal *principals,
      54             :                                        krb5_principal salt_princ,
      55             :                                        int kvno,
      56             :                                        const char *password_s,
      57             :                                        krb5_context context,
      58             :                                        krb5_enctype *enctypes,
      59             :                                        krb5_keytab keytab,
      60             :                                        const char **error_string)
      61             : {
      62          26 :         unsigned int i, p;
      63          26 :         krb5_error_code ret;
      64          26 :         krb5_data password;
      65          26 :         char *unparsed;
      66             : 
      67         347 :         password.data = discard_const_p(char, password_s);
      68         347 :         password.length = strlen(password_s);
      69             : 
      70        1386 :         for (i = 0; enctypes[i]; i++) {
      71          78 :                 krb5_keytab_entry entry;
      72             : 
      73        1039 :                 ZERO_STRUCT(entry);
      74             : 
      75        1039 :                 ret = smb_krb5_create_key_from_string(context,
      76             :                                                       salt_princ,
      77             :                                                       NULL,
      78             :                                                       &password,
      79         961 :                                                       enctypes[i],
      80             :                                                       KRB5_KT_KEY(&entry));
      81        1039 :                 if (ret != 0) {
      82           0 :                         *error_string = talloc_strdup(parent_ctx,
      83             :                                                       "Failed to create key from string");
      84           0 :                         return ret;
      85             :                 }
      86             : 
      87        1039 :                 entry.vno = kvno;
      88             : 
      89        3515 :                 for (p = 0; p < num_principals; p++) {
      90        2476 :                         bool found = false;
      91             : 
      92        2476 :                         unparsed = NULL;
      93        2476 :                         entry.principal = principals[p];
      94             : 
      95        2476 :                         ret = smb_krb5_is_exact_entry_in_keytab(parent_ctx,
      96             :                                                                 context,
      97             :                                                                 keytab,
      98             :                                                                 &entry,
      99             :                                                                 &found,
     100             :                                                                 error_string);
     101        2476 :                         if (ret != 0) {
     102           0 :                                 krb5_free_keyblock_contents(context,
     103             :                                                             KRB5_KT_KEY(&entry));
     104           0 :                                 return ret;
     105             :                         }
     106             : 
     107             :                         /*
     108             :                          * Do not add the exact same key twice, this
     109             :                          * will allow "samba-tool domain exportkeytab"
     110             :                          * to refresh a keytab rather than infinitely
     111             :                          * extend it
     112             :                          */
     113        2476 :                         if (found) {
     114           0 :                                 continue;
     115             :                         }
     116             : 
     117        2476 :                         ret = krb5_kt_add_entry(context, keytab, &entry);
     118        2476 :                         if (ret != 0) {
     119           0 :                                 char *k5_error_string =
     120           0 :                                         smb_get_krb5_error_message(context,
     121             :                                                                    ret, NULL);
     122           0 :                                 krb5_unparse_name(context,
     123           0 :                                                 principals[p], &unparsed);
     124           0 :                                 *error_string = talloc_asprintf(parent_ctx,
     125             :                                         "Failed to add enctype %d entry for "
     126             :                                         "%s(kvno %d) to keytab: %s\n",
     127           0 :                                         (int)enctypes[i], unparsed,
     128             :                                         kvno, k5_error_string);
     129             : 
     130           0 :                                 free(unparsed);
     131           0 :                                 talloc_free(k5_error_string);
     132           0 :                                 krb5_free_keyblock_contents(context,
     133             :                                                             KRB5_KT_KEY(&entry));
     134           0 :                                 return ret;
     135             :                         }
     136             : 
     137        2476 :                         DEBUG(5, ("Added key (kvno %d) to keytab (enctype %d)\n",
     138             :                                   kvno, (int)enctypes[i]));
     139             :                 }
     140        1039 :                 krb5_free_keyblock_contents(context, KRB5_KT_KEY(&entry));
     141             :         }
     142         321 :         return 0;
     143             : }
     144             : 
     145             : /*
     146             :  * This is the inner part of smb_krb5_update_keytab on an open keytab
     147             :  * and without the deletion
     148             :  */
     149         348 : static krb5_error_code smb_krb5_fill_keytab(TALLOC_CTX *parent_ctx,
     150             :                                             const char *saltPrincipal,
     151             :                                             int kvno,
     152             :                                             const char *new_secret,
     153             :                                             const char *old_secret,
     154             :                                             uint32_t supp_enctypes,
     155             :                                             uint32_t num_principals,
     156             :                                             krb5_principal *principals,
     157             :                                             krb5_context context,
     158             :                                             krb5_keytab keytab,
     159             :                                             bool add_old,
     160             :                                             const char **perror_string)
     161             : {
     162          26 :         krb5_error_code ret;
     163         348 :         krb5_principal salt_princ = NULL;
     164          26 :         krb5_enctype *enctypes;
     165          26 :         TALLOC_CTX *mem_ctx;
     166         348 :         const char *error_string = NULL;
     167             : 
     168         348 :         if (!new_secret) {
     169             :                 /* There is no password here, so nothing to do */
     170           1 :                 return 0;
     171             :         }
     172             : 
     173         347 :         mem_ctx = talloc_new(parent_ctx);
     174         347 :         if (!mem_ctx) {
     175           0 :                 *perror_string = talloc_strdup(parent_ctx,
     176             :                         "unable to allocate tmp_ctx for smb_krb5_fill_keytab");
     177           0 :                 return ENOMEM;
     178             :         }
     179             : 
     180             :         /* The salt used to generate these entries may be different however,
     181             :          * fetch that */
     182         347 :         ret = krb5_parse_name(context, saltPrincipal, &salt_princ);
     183         347 :         if (ret) {
     184           0 :                 *perror_string = smb_get_krb5_error_message(context,
     185             :                                                            ret,
     186             :                                                            parent_ctx);
     187           0 :                 talloc_free(mem_ctx);
     188           0 :                 return ret;
     189             :         }
     190             : 
     191         347 :         ret = ms_suptypes_to_ietf_enctypes(mem_ctx, supp_enctypes, &enctypes);
     192         347 :         if (ret) {
     193           0 :                 *perror_string = talloc_asprintf(parent_ctx,
     194             :                                         "smb_krb5_fill_keytab: generating list of "
     195             :                                         "encryption types failed (%s)\n",
     196             :                                         smb_get_krb5_error_message(context,
     197             :                                                                 ret, mem_ctx));
     198           0 :                 goto done;
     199             :         }
     200             : 
     201         347 :         ret = keytab_add_keys(mem_ctx,
     202             :                               num_principals,
     203             :                               principals,
     204             :                               salt_princ, kvno, new_secret,
     205             :                               context, enctypes, keytab, &error_string);
     206         347 :         if (ret) {
     207           0 :                 *perror_string = talloc_steal(parent_ctx, error_string);
     208           0 :                 goto done;
     209             :         }
     210             : 
     211         347 :         if (old_secret && add_old && kvno != 0) {
     212           0 :                 ret = keytab_add_keys(mem_ctx,
     213             :                                       num_principals,
     214             :                                       principals,
     215             :                                       salt_princ, kvno - 1, old_secret,
     216             :                                       context, enctypes, keytab, &error_string);
     217           0 :                 if (ret) {
     218           0 :                         *perror_string = talloc_steal(parent_ctx, error_string);
     219             :                 }
     220             :         }
     221             : 
     222         347 : done:
     223         347 :         krb5_free_principal(context, salt_princ);
     224         347 :         talloc_free(mem_ctx);
     225         347 :         return ret;
     226             : }
     227             : 
     228           2 : NTSTATUS smb_krb5_fill_keytab_gmsa_keys(TALLOC_CTX *mem_ctx,
     229             :                                         struct smb_krb5_context *smb_krb5_context,
     230             :                                         krb5_keytab keytab,
     231             :                                         krb5_principal principal,
     232             :                                         struct ldb_context *samdb,
     233             :                                         struct ldb_dn *dn,
     234             :                                         bool include_historic_keys,
     235             :                                         const char **error_string)
     236             : {
     237           2 :         const char *gmsa_attrs[] = {
     238             :                 "msDS-ManagedPassword",
     239             :                 "msDS-KeyVersionNumber",
     240             :                 "sAMAccountName",
     241             :                 "msDS-SupportedEncryptionTypes",
     242             :                 NULL
     243             :         };
     244             : 
     245           0 :         NTSTATUS status;
     246           0 :         struct ldb_message *msg;
     247           0 :         const struct ldb_val *managed_password_blob;
     248           0 :         const char *managed_pw_utf8;
     249           0 :         const char *previous_managed_pw_utf8;
     250           0 :         const char *username;
     251           0 :         const char *salt_principal;
     252           2 :         uint32_t kvno = 0;
     253           2 :         uint32_t supported_enctypes = 0;
     254           2 :         krb5_context context = smb_krb5_context->krb5_context;
     255           2 :         struct cli_credentials *cred = NULL;
     256           2 :         const char *realm = NULL;
     257             : 
     258             :         /*
     259             :          * Search for msDS-ManagedPassword (and other attributes to
     260             :          * avoid a race) as this was not in the original search.
     261             :          */
     262           0 :         int ret;
     263             : 
     264           2 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     265           2 :         if (tmp_ctx == NULL) {
     266           0 :                 return NT_STATUS_NO_MEMORY;
     267             :         }
     268             : 
     269           2 :         ret = dsdb_search_one(samdb,
     270             :                               tmp_ctx,
     271             :                               &msg,
     272             :                               dn,
     273             :                               LDB_SCOPE_BASE,
     274             :                               gmsa_attrs, 0,
     275             :                               "(objectClass=msDS-GroupManagedServiceAccount)");
     276             : 
     277           2 :         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     278             :                 /*
     279             :                  * Race condition, object has gone, or just wasn't a
     280             :                  * gMSA
     281             :                  */
     282           0 :                 *error_string = talloc_asprintf(mem_ctx,
     283             :                                                 "Did not find gMSA at %s",
     284             :                                                 ldb_dn_get_linearized(dn));
     285           0 :                 TALLOC_FREE(tmp_ctx);
     286           0 :                 return NT_STATUS_NO_SUCH_USER;
     287             :         }
     288             : 
     289           2 :         if (ret != LDB_SUCCESS) {
     290           0 :                 *error_string = talloc_asprintf(mem_ctx,
     291             :                                                 "Error looking for gMSA at %s: %s",
     292             :                                                 ldb_dn_get_linearized(dn), ldb_errstring(samdb));
     293           0 :                 TALLOC_FREE(tmp_ctx);
     294           0 :                 return NT_STATUS_UNSUCCESSFUL;
     295             :         }
     296             : 
     297             :         /* Extract out passwords */
     298           2 :         managed_password_blob = ldb_msg_find_ldb_val(msg, "msDS-ManagedPassword");
     299             : 
     300           2 :         if (managed_password_blob == NULL) {
     301             :                 /*
     302             :                  * No password set on this yet or not readable by this user
     303             :                  */
     304           0 :                 *error_string = talloc_asprintf(mem_ctx,
     305             :                                                 "Did not find msDS-ManagedPassword at %s",
     306           0 :                                                 ldb_dn_get_extended_linearized(mem_ctx, msg->dn, 1));
     307           0 :                 TALLOC_FREE(tmp_ctx);
     308           0 :                 return NT_STATUS_NO_USER_KEYS;
     309             :         }
     310             : 
     311           2 :         cred = cli_credentials_init(tmp_ctx);
     312           2 :         if (cred == NULL) {
     313           0 :                 *error_string = talloc_asprintf(mem_ctx,
     314             :                                                 "Could not allocate cli_credentials for %s",
     315           0 :                                                 ldb_dn_get_linearized(msg->dn));
     316           0 :                 TALLOC_FREE(tmp_ctx);
     317           0 :                 return NT_STATUS_NO_MEMORY;
     318             :         }
     319             : 
     320           2 :         realm = smb_krb5_principal_get_realm(tmp_ctx,
     321             :                                              context,
     322             :                                              principal);
     323           2 :         if (realm == NULL) {
     324           0 :                 *error_string = talloc_asprintf(mem_ctx,
     325             :                                                 "Could not allocate copy of realm for %s",
     326           0 :                                                 ldb_dn_get_linearized(msg->dn));
     327           0 :                 TALLOC_FREE(tmp_ctx);
     328           0 :                 return NT_STATUS_NO_MEMORY;
     329             :         }
     330             : 
     331           2 :         cli_credentials_set_realm(cred, realm, CRED_SPECIFIED);
     332             : 
     333           2 :         username = ldb_msg_find_attr_as_string(msg, "sAMAccountName", NULL);
     334           2 :         if (username == NULL) {
     335           0 :                 *error_string = talloc_asprintf(mem_ctx,
     336             :                                                 "No sAMAccountName on %s",
     337           0 :                                                 ldb_dn_get_linearized(msg->dn));
     338           0 :                 TALLOC_FREE(tmp_ctx);
     339           0 :                 return NT_STATUS_INVALID_ACCOUNT_NAME;
     340             :         }
     341             : 
     342           2 :         cli_credentials_set_username(cred, username, CRED_SPECIFIED);
     343             : 
     344             :         /*
     345             :          * Note that this value may not be correct, it is updated
     346             :          * after the query that gives us the passwords
     347             :          */
     348           2 :         kvno = ldb_msg_find_attr_as_uint(msg, "msDS-KeyVersionNumber", 0);
     349             : 
     350           2 :         cli_credentials_set_kvno(cred, kvno);
     351             : 
     352           2 :         supported_enctypes = ldb_msg_find_attr_as_uint(msg,
     353             :                                                        "msDS-SupportedEncryptionTypes",
     354             :                                                        ENC_STRONG_SALTED_TYPES);
     355             :         /*
     356             :          * We trim this down to just the salted AES types, as the
     357             :          * passwords are now wrong for rc4-hmac due to the mapping of
     358             :          * invalid sequences in UTF16_MUNGED -> UTF8 string conversion
     359             :          * within cli_credentials_get_password(). Users using this new
     360             :          * feature won't be using such weak crypto anyway.  If
     361             :          * required we could also set the NT Hash as a key directly,
     362             :          * this is just a limitation of smb_krb5_fill_keytab() taking
     363             :          * a simple string as input.
     364             :          */
     365           2 :         supported_enctypes &= ENC_STRONG_SALTED_TYPES;
     366             : 
     367             :         /* Update the keytab */
     368             : 
     369           2 :         status = cli_credentials_set_gmsa_passwords(cred,
     370             :                                                     managed_password_blob,
     371             :                                                     true /* for keytab */,
     372             :                                                     error_string);
     373             : 
     374           2 :         if (!NT_STATUS_IS_OK(status)) {
     375           0 :                 *error_string = talloc_asprintf(mem_ctx,
     376             :                                                 "Could not parse gMSA passwords on %s: %s",
     377           0 :                                                 ldb_dn_get_linearized(msg->dn),
     378             :                                                 *error_string);
     379           0 :                 TALLOC_FREE(tmp_ctx);
     380           0 :                 return status;
     381             :         }
     382             : 
     383           2 :         managed_pw_utf8 = cli_credentials_get_password(cred);
     384             : 
     385           2 :         previous_managed_pw_utf8 = cli_credentials_get_old_password(cred);
     386             : 
     387           2 :         salt_principal = cli_credentials_get_salt_principal(cred, tmp_ctx);
     388           2 :         if (salt_principal == NULL) {
     389           0 :                 *error_string = talloc_asprintf(mem_ctx,
     390             :                                                 "Failed to generate salt principal for %s",
     391           0 :                                                 ldb_dn_get_linearized(msg->dn));
     392           0 :                 TALLOC_FREE(tmp_ctx);
     393           0 :                 return NT_STATUS_NO_MEMORY;
     394             :         }
     395             : 
     396           2 :         ret = smb_krb5_fill_keytab(tmp_ctx,
     397             :                                    salt_principal,
     398             :                                    kvno,
     399             :                                    managed_pw_utf8,
     400             :                                    previous_managed_pw_utf8,
     401             :                                    supported_enctypes,
     402             :                                    1,
     403             :                                    &principal,
     404             :                                    context,
     405             :                                    keytab,
     406             :                                    include_historic_keys,
     407             :                                    error_string);
     408           2 :         if (ret) {
     409           0 :                 *error_string = talloc_asprintf(mem_ctx,
     410             :                                                 "Failed to add keys from %s to keytab: %s",
     411           0 :                                                 ldb_dn_get_linearized(msg->dn),
     412             :                                                 *error_string);
     413           0 :                 TALLOC_FREE(tmp_ctx);
     414           0 :                 return NT_STATUS_UNSUCCESSFUL;
     415             :         }
     416             : 
     417           2 :         TALLOC_FREE(tmp_ctx);
     418           2 :         return NT_STATUS_OK;
     419             : }
     420             : 
     421             : /**
     422             :  * @brief Update a Kerberos keytab and removes any obsolete keytab entries.
     423             :  *
     424             :  * If the keytab does not exist, this function will create one.
     425             :  *
     426             :  * @param[in] parent_ctx        Talloc memory context
     427             :  * @param[in] context           Kerberos context
     428             :  * @param[in] keytab_name       Keytab to open
     429             :  * @param[in] samAccountName    User account to update
     430             :  * @param[in] realm             Kerberos realm
     431             :  * @param[in] SPNs              Service principal names to update
     432             :  * @param[in] num_SPNs          Length of SPNs
     433             :  * @param[in] saltPrincipal     Salt used for AES encryption.
     434             :  *                              Required, unless delete_all_kvno is set.
     435             :  * @param[in] old_secret        Old password
     436             :  * @param[in] new_secret        New password
     437             :  * @param[in] kvno              Current key version number
     438             :  * @param[in] supp_enctypes     msDS-SupportedEncryptionTypes bit-field
     439             :  * @param[in] delete_all_kvno   Removes all obsolete entries, without
     440             :  *                              recreating the keytab.
     441             :  * @param[out] _keytab          If supplied, returns the keytab
     442             :  * @param[out] perror_string    Error string on failure
     443             :  *
     444             :  * @return                      0 on success, errno on failure
     445             :  */
     446         348 : krb5_error_code smb_krb5_update_keytab(TALLOC_CTX *parent_ctx,
     447             :                                 krb5_context context,
     448             :                                 const char *keytab_name,
     449             :                                 const char *samAccountName,
     450             :                                 const char *realm,
     451             :                                 const char **SPNs,
     452             :                                 int num_SPNs,
     453             :                                 const char *saltPrincipal,
     454             :                                 const char *new_secret,
     455             :                                 const char *old_secret,
     456             :                                 int kvno,
     457             :                                 uint32_t supp_enctypes,
     458             :                                 bool delete_all_kvno,
     459             :                                 krb5_keytab *_keytab,
     460             :                                 const char **perror_string)
     461             : {
     462         348 :         krb5_keytab keytab = NULL;
     463          26 :         krb5_error_code ret;
     464         348 :         bool found_previous = false;
     465         348 :         TALLOC_CTX *tmp_ctx = NULL;
     466         348 :         krb5_principal *principals = NULL;
     467         348 :         uint32_t num_principals = 0;
     468          26 :         char *upper_realm;
     469         348 :         const char *error_string = NULL;
     470             : 
     471         348 :         if (keytab_name == NULL) {
     472           0 :                 return ENOENT;
     473             :         }
     474             : 
     475         348 :         ret = krb5_kt_resolve(context, keytab_name, &keytab);
     476         348 :         if (ret) {
     477           0 :                 *perror_string = smb_get_krb5_error_message(context,
     478             :                                                            ret, parent_ctx);
     479           0 :                 return ret;
     480             :         }
     481             : 
     482         348 :         DEBUG(5, ("Opened keytab %s\n", keytab_name));
     483             : 
     484         348 :         tmp_ctx = talloc_new(parent_ctx);
     485         348 :         if (!tmp_ctx) {
     486           0 :                 *perror_string = talloc_strdup(parent_ctx,
     487             :                                               "Failed to allocate memory context");
     488           0 :                 ret = ENOMEM;
     489           0 :                 goto done;
     490             :         }
     491             : 
     492         348 :         upper_realm = strupper_talloc(tmp_ctx, realm);
     493         348 :         if (upper_realm == NULL) {
     494           0 :                 *perror_string = talloc_strdup(parent_ctx,
     495             :                                               "Cannot allocate memory to upper case realm");
     496           0 :                 ret = ENOMEM;
     497           0 :                 goto done;
     498             :         }
     499             : 
     500         348 :         ret = smb_krb5_create_principals_array(tmp_ctx,
     501             :                                                context,
     502             :                                                samAccountName,
     503             :                                                upper_realm,
     504             :                                                num_SPNs,
     505             :                                                SPNs,
     506             :                                                &num_principals,
     507             :                                                &principals,
     508             :                                                &error_string);
     509         348 :         if (ret != 0) {
     510           0 :                 *perror_string = talloc_asprintf(parent_ctx,
     511             :                         "Failed to load principals from ldb message: %s\n",
     512             :                         error_string);
     513           0 :                 goto done;
     514             :         }
     515             : 
     516         348 :         ret = smb_krb5_remove_obsolete_keytab_entries(tmp_ctx,
     517             :                                                       context,
     518             :                                                       keytab,
     519             :                                                       num_principals,
     520             :                                                       principals,
     521             :                                                       kvno,
     522             :                                                       &found_previous,
     523             :                                                       &error_string);
     524         348 :         if (ret != 0) {
     525           0 :                 *perror_string = talloc_asprintf(parent_ctx,
     526             :                         "Failed to remove old principals from keytab: %s\n",
     527             :                         error_string);
     528           0 :                 goto done;
     529             :         }
     530             : 
     531         348 :         if (!delete_all_kvno) {
     532             :                 /* Create a new keytab.  If during the cleanout we found
     533             :                  * entries for kvno -1, then don't try and duplicate them.
     534             :                  * Otherwise, add kvno, and kvno -1 */
     535         346 :                 if (saltPrincipal == NULL) {
     536           0 :                         *perror_string = talloc_strdup(parent_ctx,
     537             :                                                        "No saltPrincipal provided");
     538           0 :                         ret = EINVAL;
     539           0 :                         goto done;
     540             :                 }
     541             : 
     542         372 :                 ret = smb_krb5_fill_keytab(tmp_ctx,
     543             :                                     saltPrincipal,
     544             :                                     kvno, new_secret, old_secret,
     545             :                                     supp_enctypes,
     546             :                                     num_principals,
     547             :                                     principals,
     548             :                                     context, keytab,
     549         346 :                                     found_previous ? false : true,
     550             :                                     &error_string);
     551         346 :                 if (ret) {
     552           0 :                         *perror_string = talloc_steal(parent_ctx, error_string);
     553             :                 }
     554             :         }
     555             : 
     556         348 :         if (ret == 0 && _keytab != NULL) {
     557             :                 /* caller wants the keytab handle back */
     558          97 :                 *_keytab = keytab;
     559             :         }
     560             : 
     561         251 : done:
     562         348 :         keytab_principals_free(context, num_principals, principals);
     563         348 :         if (ret != 0 || _keytab == NULL) {
     564         251 :                 krb5_kt_close(context, keytab);
     565             :         }
     566         348 :         talloc_free(tmp_ctx);
     567         348 :         return ret;
     568             : }
     569             : 
     570             : /**
     571             :  * @brief Wrapper around smb_krb5_update_keytab() for creating an in-memory keytab
     572             :  *
     573             :  * @param[in] parent_ctx        Talloc memory context
     574             :  * @param[in] context           Kerberos context
     575             :  * @param[in] new_secret        New password
     576             :  * @param[in] samAccountName    User account to update
     577             :  * @param[in] realm             Kerberos realm
     578             :  * @param[in] salt_principal    Salt used for AES encryption.
     579             :  *                              Required, unless delete_all_kvno is set.
     580             :  * @param[in] kvno              Current key version number
     581             :  * @param[out] keytab           If supplied, returns the keytab
     582             :  * @param[out] keytab_name      Returns the created keytab name
     583             :  *
     584             :  * @return                      0 on success, errno on failure
     585             :  */
     586          97 : krb5_error_code smb_krb5_create_memory_keytab(TALLOC_CTX *parent_ctx,
     587             :                                 krb5_context context,
     588             :                                 const char *new_secret,
     589             :                                 const char *samAccountName,
     590             :                                 const char *realm,
     591             :                                 const char *salt_principal,
     592             :                                 int kvno,
     593             :                                 krb5_keytab *keytab,
     594             :                                 const char **keytab_name)
     595             : {
     596           0 :         krb5_error_code ret;
     597          97 :         TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
     598           0 :         const char *rand_string;
     599          97 :         const char *error_string = NULL;
     600          97 :         if (!mem_ctx) {
     601           0 :                 return ENOMEM;
     602             :         }
     603             : 
     604          97 :         rand_string = generate_random_str(mem_ctx, 16);
     605          97 :         if (!rand_string) {
     606           0 :                 talloc_free(mem_ctx);
     607           0 :                 return ENOMEM;
     608             :         }
     609             : 
     610          97 :         *keytab_name = talloc_asprintf(mem_ctx, "MEMORY:%s", rand_string);
     611          97 :         if (*keytab_name == NULL) {
     612           0 :                 talloc_free(mem_ctx);
     613           0 :                 return ENOMEM;
     614             :         }
     615             : 
     616          97 :         ret = smb_krb5_update_keytab(mem_ctx, context,
     617             :                                      *keytab_name, samAccountName, realm,
     618             :                                      NULL, 0, salt_principal, new_secret, NULL,
     619             :                                      kvno, ENC_ALL_TYPES,
     620             :                                      false, keytab, &error_string);
     621          97 :         if (ret == 0) {
     622          97 :                 talloc_steal(parent_ctx, *keytab_name);
     623             :         } else {
     624           0 :                 DEBUG(0, ("Failed to create in-memory keytab: %s\n",
     625             :                           error_string));
     626           0 :                 *keytab_name = NULL;
     627             :         }
     628          97 :         talloc_free(mem_ctx);
     629          97 :         return ret;
     630             : }

Generated by: LCOV version 1.14