From d088f94bd9bbbfe0d43de30ce1155638d9a57024 Mon Sep 17 00:00:00 2001 From: Petr Lautrbach Date: Oct 23 2013 20:08:19 +0000 Subject: use default_ccache_name from /etc/krb5.conf for a kerberos cache (#991186) --- diff --git a/openssh-6.3p1-krb5-use-default_ccache_name.patch b/openssh-6.3p1-krb5-use-default_ccache_name.patch new file mode 100644 index 0000000..b9c8000 --- /dev/null +++ b/openssh-6.3p1-krb5-use-default_ccache_name.patch @@ -0,0 +1,247 @@ +diff -up openssh-6.3p1/auth-krb5.c.ccache_name openssh-6.3p1/auth-krb5.c +--- openssh-6.3p1/auth-krb5.c.ccache_name 2013-10-23 22:03:52.322950759 +0200 ++++ openssh-6.3p1/auth-krb5.c 2013-10-23 22:04:24.295799873 +0200 +@@ -50,7 +50,9 @@ + #include + #include + #include ++#include + #include ++#include + + extern ServerOptions options; + +@@ -91,6 +93,7 @@ auth_krb5_password(Authctxt *authctxt, c + #endif + krb5_error_code problem; + krb5_ccache ccache = NULL; ++ const char *ccache_type; + int len; + char *client, *platform_client; + const char *errmsg; +@@ -191,12 +194,30 @@ auth_krb5_password(Authctxt *authctxt, c + goto out; + #endif + ++ ccache_type = krb5_cc_get_type(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); + authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); + +- len = strlen(authctxt->krb5_ticket_file) + 6; ++ if (authctxt->krb5_ticket_file[0] == ':') ++ authctxt->krb5_ticket_file++; ++ ++ len = strlen(authctxt->krb5_ticket_file) + strlen(ccache_type); + authctxt->krb5_ccname = xmalloc(len); +- snprintf(authctxt->krb5_ccname, len, "FILE:%s", ++ ++#ifdef USE_CCAPI ++ snprintf(authctxt->krb5_ccname, len, "API:%s", + authctxt->krb5_ticket_file); ++#else ++ snprintf(authctxt->krb5_ccname, len, "%s:%s", ++ ccache_type, authctxt->krb5_ticket_file); ++#endif ++ ++ if (strcmp(ccache_type, "DIR") == 0) { ++ char *p; ++ p = strrchr(authctxt->krb5_ccname, '/'); ++ if (p) ++ *p = '\0'; ++ } ++ + + #ifdef USE_PAM + if (options.use_pam) +@@ -235,10 +256,34 @@ auth_krb5_password(Authctxt *authctxt, c + void + krb5_cleanup_proc(Authctxt *authctxt) + { ++ struct stat krb5_ccname_stat; ++ char krb5_ccname[128], *krb5_ccname_dir_start, *krb5_ccname_dir_end; ++ + debug("krb5_cleanup_proc called"); + if (authctxt->krb5_fwd_ccache) { + krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); + authctxt->krb5_fwd_ccache = NULL; ++ ++ strncpy(krb5_ccname, authctxt->krb5_ccname, sizeof(krb5_ccname) - 10); ++ krb5_ccname_dir_start = strchr(krb5_ccname, ':') + 1; ++ *krb5_ccname_dir_start++ = '\0'; ++ if (strcmp(krb5_ccname, "DIR") == 0) { ++ ++ strcat(krb5_ccname_dir_start, "/primary"); ++ ++ if (stat(krb5_ccname_dir_start, &krb5_ccname_stat) == 0) { ++ if (unlink(krb5_ccname_dir_start) == 0) { ++ krb5_ccname_dir_end = strrchr(krb5_ccname_dir_start, '/'); ++ *krb5_ccname_dir_end = '\0'; ++ if (rmdir(krb5_ccname_dir_start) == -1) ++ debug("cache dir '%s' remove failed: %s", krb5_ccname_dir_start, strerror(errno)); ++ } ++ else ++ debug("cache primary file '%s', remove failed: %s", ++ krb5_ccname_dir_start, strerror(errno) ++ ); ++ } ++ } + } + if (authctxt->krb5_user) { + krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user); +@@ -250,34 +295,139 @@ krb5_cleanup_proc(Authctxt *authctxt) + } + } + ++int ++ssh_asprintf_append(char **dsc, const char *fmt, ...) { ++ char *src, *old; ++ va_list ap; ++ int i; ++ ++ va_start(ap, fmt); ++ i = vasprintf(&src, fmt, ap); ++ va_end(ap); ++ ++ if (i == -1 || src == NULL) ++ return -1; ++ ++ old = *dsc; ++ ++ i = asprintf(dsc, "%s%s", *dsc, src); ++ if (i == -1 || src == NULL) { ++ free(src); ++ return -1; ++ } ++ ++ free(old); ++ free(src); ++ ++ return i; ++} ++ ++int ++ssh_krb5_expand_template(char **result, const char *template) { ++ char *p_n, *p_o, *r, *tmp_template; ++ ++ if (template == NULL) ++ return -1; ++ ++ tmp_template = p_n = p_o = xstrdup(template); ++ r = xstrdup(""); ++ ++ while ((p_n = strstr(p_o, "%{")) != NULL) { ++ ++ *p_n++ = '\0'; ++ if (ssh_asprintf_append(&r, "%s", p_o) == -1) ++ goto cleanup; ++ ++ if (strncmp(p_n, "{uid}", 5) == 0 || strncmp(p_n, "{euid}", 6) == 0 || ++ strncmp(p_n, "{USERID}", 8) == 0) { ++ p_o = strchr(p_n, '}') + 1; ++ if (ssh_asprintf_append(&r, "%d", geteuid()) == -1) ++ goto cleanup; ++ continue; ++ } ++ else if (strncmp(p_n, "{TEMP}", 6) == 0) { ++ p_o = strchr(p_n, '}') + 1; ++ if (ssh_asprintf_append(&r, "/tmp") == -1) ++ goto cleanup; ++ continue; ++ } else { ++ p_o = strchr(p_n, '}') + 1; ++ p_o = '\0'; ++ debug("%s: unsupported token %s in %s", __func__, p_n, template); ++ /* unknown token, fallback to the default */ ++ goto cleanup; ++ } ++ } ++ ++ if (ssh_asprintf_append(&r, "%s", p_o) == -1) ++ goto cleanup; ++ ++ *result = r; ++ free(tmp_template); ++ return 0; ++ ++cleanup: ++ free(r); ++ free(tmp_template); ++ return -1; ++} ++ ++krb5_error_code ++ssh_krb5_get_cctemplate(krb5_context ctx, char **ccname) { ++ profile_t p; ++ int ret = 0; ++ char *value = NULL; ++ ++ ret = krb5_get_profile(ctx, &p); ++ if (ret) ++ return ret; ++ ++ ret = profile_get_string(p, "libdefaults", "default_ccache_name", NULL, NULL, &value); ++ if (ret) ++ return ret; ++ ++ ret = ssh_krb5_expand_template(ccname, value); ++ ++ return ret; ++} ++ + #ifndef HEIMDAL + krb5_error_code + ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { + int tmpfd, ret, oerrno; +- char ccname[40]; ++ char *ccname; ++#ifdef USE_CCAPI ++ char cctemplate[] = "API:krb5cc_%d"; ++#else + mode_t old_umask; ++ char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX"; + +- ret = snprintf(ccname, sizeof(ccname), +- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); +- if (ret < 0 || (size_t)ret >= sizeof(ccname)) +- return ENOMEM; +- +- old_umask = umask(0177); +- tmpfd = mkstemp(ccname + strlen("FILE:")); +- oerrno = errno; +- umask(old_umask); +- if (tmpfd == -1) { +- logit("mkstemp(): %.100s", strerror(oerrno)); +- return oerrno; +- } ++#endif ++ ++ ret = ssh_krb5_get_cctemplate(ctx, &ccname); + +- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { ++ if (ret) { ++ ret = asprintf(&ccname, cctemplate, geteuid()); ++ if (ret == -1) ++ return ENOMEM; ++ old_umask = umask(0177); ++ tmpfd = mkstemp(ccname + strlen("FILE:")); + oerrno = errno; +- logit("fchmod(): %.100s", strerror(oerrno)); ++ umask(old_umask); ++ if (tmpfd == -1) { ++ logit("mkstemp(): %.100s", strerror(oerrno)); ++ return oerrno; ++ } ++ ++ if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { ++ oerrno = errno; ++ logit("fchmod(): %.100s", strerror(oerrno)); ++ close(tmpfd); ++ return oerrno; ++ } + close(tmpfd); +- return oerrno; + } +- close(tmpfd); ++ debug("%s: Setting ccname to %s", __func__, ccname); + + return (krb5_cc_resolve(ctx, ccname, ccache)); + } diff --git a/openssh.spec b/openssh.spec index 388c7e7..d829fba 100644 --- a/openssh.spec +++ b/openssh.spec @@ -176,6 +176,8 @@ Patch801: openssh-6.3p1-force_krb.patch Patch900: openssh-6.1p1-gssapi-canohost.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1780 Patch901: openssh-6.3p1-kuserok.patch +# use default_ccache_name from /etc/krb5.conf (#991186) +Patch902: openssh-6.3p1-krb5-use-default_ccache_name.patch License: BSD @@ -395,6 +397,7 @@ popd %patch900 -p1 -b .canohost %patch901 -p1 -b .kuserok +%patch902 -p1 -b .ccache_name %if 0 # Nothing here yet