diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 05:31:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 05:31:45 +0000 |
commit | 74aa0bc6779af38018a03fd2cf4419fe85917904 (patch) | |
tree | 9cb0681aac9a94a49c153d5823e7a55d1513d91f /src/providers/krb5/krb5_keytab.c | |
parent | Initial commit. (diff) | |
download | sssd-74aa0bc6779af38018a03fd2cf4419fe85917904.tar.xz sssd-74aa0bc6779af38018a03fd2cf4419fe85917904.zip |
Adding upstream version 2.9.4.upstream/2.9.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/providers/krb5/krb5_keytab.c')
-rw-r--r-- | src/providers/krb5/krb5_keytab.c | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/src/providers/krb5/krb5_keytab.c b/src/providers/krb5/krb5_keytab.c new file mode 100644 index 0000000..db383d4 --- /dev/null +++ b/src/providers/krb5/krb5_keytab.c @@ -0,0 +1,231 @@ +/* + SSSD + + Kerberos 5 Backend Module -- keytab related utilities + + Authors: + Sumit Bose <sbose@redhat.com> + + Copyright (C) 2014 Red Hat + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "util/util.h" +#include "util/sss_krb5.h" +#include "providers/krb5/krb5_common.h" + +static krb5_error_code do_keytab_copy(krb5_context kctx, krb5_keytab s_keytab, + krb5_keytab d_keytab) +{ + krb5_error_code kerr; + krb5_error_code kt_err; + krb5_kt_cursor cursor; + krb5_keytab_entry entry; + + memset(&cursor, 0, sizeof(cursor)); + kerr = krb5_kt_start_seq_get(kctx, s_keytab, &cursor); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "error reading keytab.\n"); + return kerr; + } + + memset(&entry, 0, sizeof(entry)); + while ((kt_err = krb5_kt_next_entry(kctx, s_keytab, &entry, + &cursor)) == 0) { + kerr = krb5_kt_add_entry(kctx, d_keytab, &entry); + if (kerr != 0) { + DEBUG(SSSDBG_OP_FAILURE, "krb5_kt_add_entry failed.\n"); + kt_err = krb5_kt_end_seq_get(kctx, s_keytab, &cursor); + if (kt_err != 0) { + DEBUG(SSSDBG_TRACE_ALL, + "krb5_kt_end_seq_get failed with [%d], ignored.\n", + kt_err); + } + return kerr; + } + + kerr = sss_krb5_free_keytab_entry_contents(kctx, &entry); + if (kerr != 0) { + DEBUG(SSSDBG_MINOR_FAILURE, "Failed to free keytab entry.\n"); + kt_err = krb5_kt_end_seq_get(kctx, s_keytab, &cursor); + if (kt_err != 0) { + DEBUG(SSSDBG_TRACE_ALL, + "krb5_kt_end_seq_get failed with [%d], ignored.\n", + kt_err); + } + return kerr; + } + memset(&entry, 0, sizeof(entry)); + } + + kerr = krb5_kt_end_seq_get(kctx, s_keytab, &cursor); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "krb5_kt_end_seq_get failed.\n"); + return kerr; + } + + /* check if we got any errors from krb5_kt_next_entry */ + if (kt_err != 0 && kt_err != KRB5_KT_END) { + DEBUG(SSSDBG_CRIT_FAILURE, "error reading keytab.\n"); + return kt_err; + } + + return 0; +} + +krb5_error_code copy_keytab_into_memory(TALLOC_CTX *mem_ctx, krb5_context kctx, + const char *inp_keytab_file, + char **_mem_name, + krb5_keytab *_mem_keytab) +{ + krb5_error_code kerr; + krb5_keytab keytab = NULL; + krb5_keytab mem_keytab = NULL; + krb5_keytab tmp_mem_keytab = NULL; + char keytab_name[MAX_KEYTAB_NAME_LEN]; + char *sep; + char *mem_name = NULL; + char *tmp_mem_name = NULL; + const char *keytab_file; + char default_keytab_name[MAX_KEYTAB_NAME_LEN]; + + keytab_file = inp_keytab_file; + if (keytab_file == NULL) { + kerr = krb5_kt_default_name(kctx, default_keytab_name, + sizeof(default_keytab_name)); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "krb5_kt_default_name failed.\n"); + return kerr; + } + + keytab_file = default_keytab_name; + } + + kerr = krb5_kt_resolve(kctx, keytab_file, &keytab); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "error resolving keytab [%s].\n", + keytab_file); + return kerr; + } + + kerr = sss_krb5_kt_have_content(kctx, keytab); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "keytab [%s] has not entries.\n", + keytab_file); + goto done; + } + + kerr = krb5_kt_get_name(kctx, keytab, keytab_name, sizeof(keytab_name)); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to read name for keytab [%s].\n", + keytab_file); + goto done; + } + + sep = strchr(keytab_name, ':'); + if (sep == NULL || sep[1] == '\0') { + DEBUG(SSSDBG_CRIT_FAILURE, + "Keytab name [%s] does not have delimiter[:] .\n", keytab_name); + kerr = KRB5KRB_ERR_GENERIC; + goto done; + } + + if (strncmp(keytab_name, "MEMORY:", sizeof("MEMORY:") -1) == 0) { + DEBUG(SSSDBG_TRACE_FUNC, "Keytab [%s] is already memory keytab.\n", + keytab_name); + *_mem_name = talloc_strdup(mem_ctx, keytab_name); + if(*_mem_name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + kerr = KRB5KRB_ERR_GENERIC; + goto done; + } + kerr = 0; + goto done; + } + + mem_name = talloc_asprintf(mem_ctx, "MEMORY:%s", sep + 1); + if (mem_name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); + kerr = KRB5KRB_ERR_GENERIC; + goto done; + } + + tmp_mem_name = talloc_asprintf(mem_ctx, "MEMORY:%s.tmp", sep + 1); + if (tmp_mem_name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); + kerr = KRB5KRB_ERR_GENERIC; + goto done; + } + + kerr = krb5_kt_resolve(kctx, mem_name, &mem_keytab); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "error resolving keytab [%s].\n", + mem_name); + goto done; + } + + kerr = krb5_kt_resolve(kctx, tmp_mem_name, &tmp_mem_keytab); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "error resolving keytab [%s].\n", + tmp_mem_name); + goto done; + } + + kerr = do_keytab_copy(kctx, keytab, tmp_mem_keytab); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy keytab [%s] into [%s].\n", + keytab_file, tmp_mem_name); + goto done; + } + + /* krb5_kt_add_entry() adds new entries into MEMORY keytabs at the + * beginning and not at the end as for FILE keytabs. Since we want to keep + * the processing order we have to copy the MEMORY keytab again to retain + * the order from the FILE keytab. */ + + kerr = do_keytab_copy(kctx, tmp_mem_keytab, mem_keytab); + if (kerr != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy keytab [%s] into [%s].\n", + tmp_mem_name, mem_name); + goto done; + } + + *_mem_name = mem_name; + if (_mem_keytab != NULL) { + *_mem_keytab = mem_keytab; + } + + kerr = 0; +done: + + talloc_free(tmp_mem_name); + + if (kerr != 0) { + talloc_free(mem_name); + if ((mem_keytab != NULL) && krb5_kt_close(kctx, mem_keytab) != 0) { + DEBUG(SSSDBG_MINOR_FAILURE, "krb5_kt_close failed.\n"); + } + } + + if (tmp_mem_keytab != NULL && krb5_kt_close(kctx, tmp_mem_keytab) != 0) { + DEBUG(SSSDBG_MINOR_FAILURE, "krb5_kt_close failed.\n"); + } + + if (keytab != NULL && krb5_kt_close(kctx, keytab) != 0) { + DEBUG(SSSDBG_MINOR_FAILURE, "krb5_kt_close failed.\n"); + } + + return kerr; +} |