LCOV - code coverage report
Current view: top level - source4/auth/kerberos - srv_keytab.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 135 231 58.4 %
Date: 2024-04-21 15:09:00 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        1384 :         for (i = 0; enctypes[i]; i++) {
      71          78 :                 krb5_keytab_entry entry;
      72             : 
      73        1037 :                 ZERO_STRUCT(entry);
      74             : 
      75        1037 :                 ret = smb_krb5_create_key_from_string(context,
      76             :                                                       salt_princ,
      77             :                                                       NULL,
      78             :                                                       &password,
      79         959 :                                                       enctypes[i],
      80             :                                                       KRB5_KT_KEY(&entry));
      81        1037 :                 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        1037 :                 entry.vno = kvno;
      88             : 
      89        3511 :                 for (p = 0; p < num_principals; p++) {
      90        2474 :                         bool found = false;
      91             : 
      92        2474 :                         unparsed = NULL;
      93        2474 :                         entry.principal = principals[p];
      94             : 
      95        2474 :                         ret = smb_krb5_is_exact_entry_in_keytab(parent_ctx,
      96             :                                                                 context,
      97             :                                                                 keytab,
      98             :                                                                 &entry,
      99             :                                                                 &found,
     100             :                                                                 error_string);
     101        2474 :                         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        2474 :                         if (found) {
     114           0 :                                 continue;
     115             :                         }
     116             : 
     117        2474 :                         ret = krb5_kt_add_entry(context, keytab, &entry);
     118        2474 :                         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        2474 :                         DEBUG(5, ("Added key (kvno %d) to keytab (enctype %d)\n",
     138             :                                   kvno, (int)enctypes[i]));
     139             :                 }
     140        1037 :                 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             :                                         const char **error_string)
     235             : {
     236           2 :         const char *gmsa_attrs[] = {
     237             :                 "msDS-ManagedPassword",
     238             :                 "msDS-KeyVersionNumber",
     239             :                 "sAMAccountName",
     240             :                 "msDS-SupportedEncryptionTypes",
     241             :                 NULL
     242             :         };
     243             : 
     244           0 :         NTSTATUS status;
     245           0 :         struct ldb_message *msg;
     246           0 :         const struct ldb_val *managed_password_blob;
     247           0 :         const char *managed_pw_utf8;
     248           0 :         const char *previous_managed_pw_utf8;
     249           0 :         const char *username;
     250           0 :         const char *salt_principal;
     251           2 :         uint32_t kvno = 0;
     252           2 :         uint32_t supported_enctypes = 0;
     253           2 :         krb5_context context = smb_krb5_context->krb5_context;
     254           2 :         struct cli_credentials *cred = NULL;
     255           2 :         const char *realm = NULL;
     256             : 
     257             :         /*
     258             :          * Search for msDS-ManagedPassword (and other attributes to
     259             :          * avoid a race) as this was not in the original search.
     260             :          */
     261           0 :         int ret;
     262             : 
     263           2 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     264           2 :         if (tmp_ctx == NULL) {
     265           0 :                 return NT_STATUS_NO_MEMORY;
     266             :         }
     267             : 
     268           2 :         ret = dsdb_search_one(samdb,
     269             :                               tmp_ctx,
     270             :                               &msg,
     271             :                               dn,
     272             :                               LDB_SCOPE_BASE,
     273             :                               gmsa_attrs, 0,
     274             :                               "(objectClass=msDS-GroupManagedServiceAccount)");
     275             : 
     276           2 :         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     277             :                 /*
     278             :                  * Race condition, object has gone, or just wasn't a
     279             :                  * gMSA
     280             :                  */
     281           0 :                 *error_string = talloc_asprintf(mem_ctx,
     282             :                                                 "Did not find gMSA at %s",
     283             :                                                 ldb_dn_get_linearized(dn));
     284           0 :                 TALLOC_FREE(tmp_ctx);
     285           0 :                 return NT_STATUS_NO_SUCH_USER;
     286             :         }
     287             : 
     288           2 :         if (ret != LDB_SUCCESS) {
     289           0 :                 *error_string = talloc_asprintf(mem_ctx,
     290             :                                                 "Error looking for gMSA at %s: %s",
     291             :                                                 ldb_dn_get_linearized(dn), ldb_errstring(samdb));
     292           0 :                 TALLOC_FREE(tmp_ctx);
     293           0 :                 return NT_STATUS_UNSUCCESSFUL;
     294             :         }
     295             : 
     296             :         /* Extract out passwords */
     297           2 :         managed_password_blob = ldb_msg_find_ldb_val(msg, "msDS-ManagedPassword");
     298             : 
     299           2 :         if (managed_password_blob == NULL) {
     300             :                 /*
     301             :                  * No password set on this yet or not readable by this user
     302             :                  */
     303           0 :                 *error_string = talloc_asprintf(mem_ctx,
     304             :                                                 "Did not find msDS-ManagedPassword at %s",
     305           0 :                                                 ldb_dn_get_extended_linearized(mem_ctx, msg->dn, 1));
     306           0 :                 TALLOC_FREE(tmp_ctx);
     307           0 :                 return NT_STATUS_NO_USER_KEYS;
     308             :         }
     309             : 
     310           2 :         cred = cli_credentials_init(tmp_ctx);
     311           2 :         if (cred == NULL) {
     312           0 :                 *error_string = talloc_asprintf(mem_ctx,
     313             :                                                 "Could not allocate cli_credentials for %s",
     314           0 :                                                 ldb_dn_get_linearized(msg->dn));
     315           0 :                 TALLOC_FREE(tmp_ctx);
     316           0 :                 return NT_STATUS_NO_MEMORY;
     317             :         }
     318             : 
     319           2 :         realm = smb_krb5_principal_get_realm(tmp_ctx,
     320             :                                              context,
     321             :                                              principal);
     322           2 :         if (realm == NULL) {
     323           0 :                 *error_string = talloc_asprintf(mem_ctx,
     324             :                                                 "Could not allocate copy of realm for %s",
     325           0 :                                                 ldb_dn_get_linearized(msg->dn));
     326           0 :                 TALLOC_FREE(tmp_ctx);
     327           0 :                 return NT_STATUS_NO_MEMORY;
     328             :         }
     329             : 
     330           2 :         cli_credentials_set_realm(cred, realm, CRED_SPECIFIED);
     331             : 
     332           2 :         username = ldb_msg_find_attr_as_string(msg, "sAMAccountName", NULL);
     333           2 :         if (username == NULL) {
     334           0 :                 *error_string = talloc_asprintf(mem_ctx,
     335             :                                                 "No sAMAccountName on %s",
     336           0 :                                                 ldb_dn_get_linearized(msg->dn));
     337           0 :                 TALLOC_FREE(tmp_ctx);
     338           0 :                 return NT_STATUS_INVALID_ACCOUNT_NAME;
     339             :         }
     340             : 
     341           2 :         cli_credentials_set_username(cred, username, CRED_SPECIFIED);
     342             : 
     343             :         /*
     344             :          * Note that this value may not be correct, it is updated
     345             :          * after the query that gives us the passwords
     346             :          */
     347           2 :         kvno = ldb_msg_find_attr_as_uint(msg, "msDS-KeyVersionNumber", 0);
     348             : 
     349           2 :         cli_credentials_set_kvno(cred, kvno);
     350             : 
     351           2 :         supported_enctypes = ldb_msg_find_attr_as_uint(msg,
     352             :                                                        "msDS-SupportedEncryptionTypes",
     353             :                                                        ENC_HMAC_SHA1_96_AES256);
     354             :         /*
     355             :          * We trim this down to just the salted AES types, as the
     356             :          * passwords are now wrong for rc4-hmac due to the mapping of
     357             :          * invalid sequences in UTF16_MUNGED -> UTF8 string conversion
     358             :          * within cli_credentials_get_password(). Users using this new
     359             :          * feature won't be using such weak crypto anyway.  If
     360             :          * required we could also set the NT Hash as a key directly,
     361             :          * this is just a limitation of smb_krb5_fill_keytab() taking
     362             :          * a simple string as input.
     363             :          */
     364           2 :         supported_enctypes &= ENC_STRONG_SALTED_TYPES;
     365             : 
     366             :         /* Update the keytab */
     367             : 
     368           2 :         status = cli_credentials_set_gmsa_passwords(cred,
     369             :                                                     managed_password_blob,
     370             :                                                     true /* for keytab */,
     371             :                                                     error_string);
     372             : 
     373           2 :         if (!NT_STATUS_IS_OK(status)) {
     374           0 :                 *error_string = talloc_asprintf(mem_ctx,
     375             :                                                 "Could not parse gMSA passwords on %s: %s",
     376           0 :                                                 ldb_dn_get_linearized(msg->dn),
     377             :                                                 *error_string);
     378           0 :                 TALLOC_FREE(tmp_ctx);
     379           0 :                 return status;
     380             :         }
     381             : 
     382           2 :         managed_pw_utf8 = cli_credentials_get_password(cred);
     383             : 
     384           2 :         previous_managed_pw_utf8 = cli_credentials_get_old_password(cred);
     385             : 
     386           2 :         salt_principal = cli_credentials_get_salt_principal(cred, tmp_ctx);
     387           2 :         if (salt_principal == NULL) {
     388           0 :                 *error_string = talloc_asprintf(mem_ctx,
     389             :                                                 "Failed to generate salt principal for %s",
     390           0 :                                                 ldb_dn_get_linearized(msg->dn));
     391           0 :                 TALLOC_FREE(tmp_ctx);
     392           0 :                 return NT_STATUS_NO_MEMORY;
     393             :         }
     394             : 
     395           2 :         ret = smb_krb5_fill_keytab(tmp_ctx,
     396             :                                    salt_principal,
     397             :                                    kvno,
     398             :                                    managed_pw_utf8,
     399             :                                    previous_managed_pw_utf8,
     400             :                                    supported_enctypes,
     401             :                                    1,
     402             :                                    &principal,
     403             :                                    context,
     404             :                                    keytab,
     405             :                                    true,
     406             :                                    error_string);
     407           2 :         if (ret) {
     408           0 :                 *error_string = talloc_asprintf(mem_ctx,
     409             :                                                 "Failed to add keys from %s to keytab: %s",
     410           0 :                                                 ldb_dn_get_linearized(msg->dn),
     411             :                                                 *error_string);
     412           0 :                 TALLOC_FREE(tmp_ctx);
     413           0 :                 return NT_STATUS_UNSUCCESSFUL;
     414             :         }
     415             : 
     416           2 :         TALLOC_FREE(tmp_ctx);
     417           2 :         return NT_STATUS_OK;
     418             : }
     419             : 
     420             : /**
     421             :  * @brief Update a Kerberos keytab and removes any obsolete keytab entries.
     422             :  *
     423             :  * If the keytab does not exist, this function will create one.
     424             :  *
     425             :  * @param[in] parent_ctx        Talloc memory context
     426             :  * @param[in] context           Kerberos context
     427             :  * @param[in] keytab_name       Keytab to open
     428             :  * @param[in] samAccountName    User account to update
     429             :  * @param[in] realm             Kerberos realm
     430             :  * @param[in] SPNs              Service principal names to update
     431             :  * @param[in] num_SPNs          Length of SPNs
     432             :  * @param[in] saltPrincipal     Salt used for AES encryption.
     433             :  *                              Required, unless delete_all_kvno is set.
     434             :  * @param[in] old_secret        Old password
     435             :  * @param[in] new_secret        New password
     436             :  * @param[in] kvno              Current key version number
     437             :  * @param[in] supp_enctypes     msDS-SupportedEncryptionTypes bit-field
     438             :  * @param[in] delete_all_kvno   Removes all obsolete entries, without
     439             :  *                              recreating the keytab.
     440             :  * @param[out] _keytab          If supplied, returns the keytab
     441             :  * @param[out] perror_string    Error string on failure
     442             :  *
     443             :  * @return                      0 on success, errno on failure
     444             :  */
     445         348 : krb5_error_code smb_krb5_update_keytab(TALLOC_CTX *parent_ctx,
     446             :                                 krb5_context context,
     447             :                                 const char *keytab_name,
     448             :                                 const char *samAccountName,
     449             :                                 const char *realm,
     450             :                                 const char **SPNs,
     451             :                                 int num_SPNs,
     452             :                                 const char *saltPrincipal,
     453             :                                 const char *new_secret,
     454             :                                 const char *old_secret,
     455             :                                 int kvno,
     456             :                                 uint32_t supp_enctypes,
     457             :                                 bool delete_all_kvno,
     458             :                                 krb5_keytab *_keytab,
     459             :                                 const char **perror_string)
     460             : {
     461         348 :         krb5_keytab keytab = NULL;
     462          26 :         krb5_error_code ret;
     463         348 :         bool found_previous = false;
     464         348 :         TALLOC_CTX *tmp_ctx = NULL;
     465         348 :         krb5_principal *principals = NULL;
     466         348 :         uint32_t num_principals = 0;
     467          26 :         char *upper_realm;
     468         348 :         const char *error_string = NULL;
     469             : 
     470         348 :         if (keytab_name == NULL) {
     471           0 :                 return ENOENT;
     472             :         }
     473             : 
     474         348 :         ret = krb5_kt_resolve(context, keytab_name, &keytab);
     475         348 :         if (ret) {
     476           0 :                 *perror_string = smb_get_krb5_error_message(context,
     477             :                                                            ret, parent_ctx);
     478           0 :                 return ret;
     479             :         }
     480             : 
     481         348 :         DEBUG(5, ("Opened keytab %s\n", keytab_name));
     482             : 
     483         348 :         tmp_ctx = talloc_new(parent_ctx);
     484         348 :         if (!tmp_ctx) {
     485           0 :                 *perror_string = talloc_strdup(parent_ctx,
     486             :                                               "Failed to allocate memory context");
     487           0 :                 ret = ENOMEM;
     488           0 :                 goto done;
     489             :         }
     490             : 
     491         348 :         upper_realm = strupper_talloc(tmp_ctx, realm);
     492         348 :         if (upper_realm == NULL) {
     493           0 :                 *perror_string = talloc_strdup(parent_ctx,
     494             :                                               "Cannot allocate memory to upper case realm");
     495           0 :                 ret = ENOMEM;
     496           0 :                 goto done;
     497             :         }
     498             : 
     499         348 :         ret = smb_krb5_create_principals_array(tmp_ctx,
     500             :                                                context,
     501             :                                                samAccountName,
     502             :                                                upper_realm,
     503             :                                                num_SPNs,
     504             :                                                SPNs,
     505             :                                                &num_principals,
     506             :                                                &principals,
     507             :                                                &error_string);
     508         348 :         if (ret != 0) {
     509           0 :                 *perror_string = talloc_asprintf(parent_ctx,
     510             :                         "Failed to load principals from ldb message: %s\n",
     511             :                         error_string);
     512           0 :                 goto done;
     513             :         }
     514             : 
     515         348 :         ret = smb_krb5_remove_obsolete_keytab_entries(tmp_ctx,
     516             :                                                       context,
     517             :                                                       keytab,
     518             :                                                       num_principals,
     519             :                                                       principals,
     520             :                                                       kvno,
     521             :                                                       &found_previous,
     522             :                                                       &error_string);
     523         348 :         if (ret != 0) {
     524           0 :                 *perror_string = talloc_asprintf(parent_ctx,
     525             :                         "Failed to remove old principals from keytab: %s\n",
     526             :                         error_string);
     527           0 :                 goto done;
     528             :         }
     529             : 
     530         348 :         if (!delete_all_kvno) {
     531             :                 /* Create a new keytab.  If during the cleanout we found
     532             :                  * entries for kvno -1, then don't try and duplicate them.
     533             :                  * Otherwise, add kvno, and kvno -1 */
     534         346 :                 if (saltPrincipal == NULL) {
     535           0 :                         *perror_string = talloc_strdup(parent_ctx,
     536             :                                                        "No saltPrincipal provided");
     537           0 :                         ret = EINVAL;
     538           0 :                         goto done;
     539             :                 }
     540             : 
     541         372 :                 ret = smb_krb5_fill_keytab(tmp_ctx,
     542             :                                     saltPrincipal,
     543             :                                     kvno, new_secret, old_secret,
     544             :                                     supp_enctypes,
     545             :                                     num_principals,
     546             :                                     principals,
     547             :                                     context, keytab,
     548         346 :                                     found_previous ? false : true,
     549             :                                     &error_string);
     550         346 :                 if (ret) {
     551           0 :                         *perror_string = talloc_steal(parent_ctx, error_string);
     552             :                 }
     553             :         }
     554             : 
     555         348 :         if (ret == 0 && _keytab != NULL) {
     556             :                 /* caller wants the keytab handle back */
     557          97 :                 *_keytab = keytab;
     558             :         }
     559             : 
     560         251 : done:
     561         348 :         keytab_principals_free(context, num_principals, principals);
     562         348 :         if (ret != 0 || _keytab == NULL) {
     563         251 :                 krb5_kt_close(context, keytab);
     564             :         }
     565         348 :         talloc_free(tmp_ctx);
     566         348 :         return ret;
     567             : }
     568             : 
     569             : /**
     570             :  * @brief Wrapper around smb_krb5_update_keytab() for creating an in-memory keytab
     571             :  *
     572             :  * @param[in] parent_ctx        Talloc memory context
     573             :  * @param[in] context           Kerberos context
     574             :  * @param[in] new_secret        New password
     575             :  * @param[in] samAccountName    User account to update
     576             :  * @param[in] realm             Kerberos realm
     577             :  * @param[in] salt_principal    Salt used for AES encryption.
     578             :  *                              Required, unless delete_all_kvno is set.
     579             :  * @param[in] kvno              Current key version number
     580             :  * @param[out] keytab           If supplied, returns the keytab
     581             :  * @param[out] keytab_name      Returns the created keytab name
     582             :  *
     583             :  * @return                      0 on success, errno on failure
     584             :  */
     585          97 : krb5_error_code smb_krb5_create_memory_keytab(TALLOC_CTX *parent_ctx,
     586             :                                 krb5_context context,
     587             :                                 const char *new_secret,
     588             :                                 const char *samAccountName,
     589             :                                 const char *realm,
     590             :                                 const char *salt_principal,
     591             :                                 int kvno,
     592             :                                 krb5_keytab *keytab,
     593             :                                 const char **keytab_name)
     594             : {
     595           0 :         krb5_error_code ret;
     596          97 :         TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
     597           0 :         const char *rand_string;
     598          97 :         const char *error_string = NULL;
     599          97 :         if (!mem_ctx) {
     600           0 :                 return ENOMEM;
     601             :         }
     602             : 
     603          97 :         rand_string = generate_random_str(mem_ctx, 16);
     604          97 :         if (!rand_string) {
     605           0 :                 talloc_free(mem_ctx);
     606           0 :                 return ENOMEM;
     607             :         }
     608             : 
     609          97 :         *keytab_name = talloc_asprintf(mem_ctx, "MEMORY:%s", rand_string);
     610          97 :         if (*keytab_name == NULL) {
     611           0 :                 talloc_free(mem_ctx);
     612           0 :                 return ENOMEM;
     613             :         }
     614             : 
     615          97 :         ret = smb_krb5_update_keytab(mem_ctx, context,
     616             :                                      *keytab_name, samAccountName, realm,
     617             :                                      NULL, 0, salt_principal, new_secret, NULL,
     618             :                                      kvno, ENC_ALL_TYPES,
     619             :                                      false, keytab, &error_string);
     620          97 :         if (ret == 0) {
     621          97 :                 talloc_steal(parent_ctx, *keytab_name);
     622             :         } else {
     623           0 :                 DEBUG(0, ("Failed to create in-memory keytab: %s\n",
     624             :                           error_string));
     625           0 :                 *keytab_name = NULL;
     626             :         }
     627          97 :         talloc_free(mem_ctx);
     628          97 :         return ret;
     629             : }

Generated by: LCOV version 1.14