Bugzilla – Attachment 3051 Details for
Bug 2775
Improve kerberos credential forwarding support
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
proposed patch from Fedora (rebased on master)
file_2775.txt (text/plain), 11.45 KB, created by
Jakub Jelen
on 2017-09-11 23:14:54 AEST
(
hide
)
Description:
proposed patch from Fedora (rebased on master)
Filename:
MIME Type:
Creator:
Jakub Jelen
Created:
2017-09-11 23:14:54 AEST
Size:
11.45 KB
patch
obsolete
>diff --git a/auth-krb5.c b/auth-krb5.c >index a5a81ed2..992cba59 100644 >--- a/auth-krb5.c >+++ b/auth-krb5.c >@@ -50,7 +50,9 @@ > #include <errno.h> > #include <unistd.h> > #include <string.h> >+#include <sys/stat.h> > #include <krb5.h> >+#include <profile.h> > > extern ServerOptions options; > >@@ -77,6 +79,7 @@ auth_krb5_password(Authctxt *authctxt, const char *password) > #endif > krb5_error_code problem; > krb5_ccache ccache = NULL; >+ const char *ccache_type; > int len; > char *client, *platform_client; > const char *errmsg; >@@ -163,7 +166,8 @@ auth_krb5_password(Authctxt *authctxt, const char *password) > goto out; > } > >- problem = ssh_krb5_cc_gen(authctxt->krb5_ctx, &authctxt->krb5_fwd_ccache); >+ problem = ssh_krb5_cc_gen(authctxt->krb5_ctx, >+ &authctxt->krb5_fwd_ccache, &authctxt->krb5_set_env); > if (problem) > goto out; > >@@ -172,21 +176,31 @@ auth_krb5_password(Authctxt *authctxt, const char *password) > if (problem) > goto out; > >- problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, >+ problem = krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, > &creds); > if (problem) > 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) + 2; > 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 > > #ifdef USE_PAM >- if (options.use_pam) >+ if (options.use_pam && authctxt->krb5_set_env) > do_pam_putenv("KRB5CCNAME", authctxt->krb5_ccname); > #endif > >@@ -237,34 +251,144 @@ 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) { >+ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache, int *need_environment) { > 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 > >- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { >+ if (need_environment) >+ *need_environment = 0; >+ ret = ssh_krb5_get_cctemplate(ctx, &ccname); >+ /* fallback to the ccache in /tmp */ >+ 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; >+ } >+ /* make sure the KRBCCNAME is set for non-standard location */ >+ if (need_environment) >+ *need_environment = 1; > close(tmpfd); >- return oerrno; > } >- close(tmpfd); >+ debug("%s: Setting ccname to %s", __func__, ccname); > > return (krb5_cc_resolve(ctx, ccname, ccache)); > } >diff --git a/auth.h b/auth.h >index 29835ae9..bbb9eb73 100644 >--- a/auth.h >+++ b/auth.h >@@ -80,6 +80,7 @@ struct Authctxt { > krb5_principal krb5_user; > char *krb5_ticket_file; > char *krb5_ccname; >+ int krb5_set_env; > #endif > struct sshbuf *loginmsg; > >@@ -227,6 +228,6 @@ int sys_auth_passwd(Authctxt *, const char *); > > #if defined(KRB5) && !defined(HEIMDAL) > #include <krb5.h> >-krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *); >+krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *, int *); > #endif > #endif >diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c >index 795992d9..85bc046f 100644 >--- a/gss-serv-krb5.c >+++ b/gss-serv-krb5.c >@@ -114,7 +114,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) > /* This writes out any forwarded credentials from the structure populated > * during userauth. Called after we have setuid to the user */ > >-static void >+static int > ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) > { > krb5_ccache ccache; >@@ -123,14 +123,15 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) > OM_uint32 maj_status, min_status; > int len; > const char *errmsg; >+ int set_env = 0; > > if (client->creds == NULL) { > debug("No credentials stored"); >- return; >+ return 0; > } > > if (ssh_gssapi_krb5_init() == 0) >- return; >+ return 0; > > #ifdef HEIMDAL > # ifdef HAVE_KRB5_CC_NEW_UNIQUE >@@ -144,14 +145,14 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) > krb5_get_err_text(krb_context, problem)); > # endif > krb5_free_error_message(krb_context, errmsg); >- return; >+ return 0; > } > #else >- if ((problem = ssh_krb5_cc_gen(krb_context, &ccache))) { >+ if ((problem = ssh_krb5_cc_gen(krb_context, &ccache, &set_env))) { > errmsg = krb5_get_error_message(krb_context, problem); > logit("ssh_krb5_cc_gen(): %.100s", errmsg); > krb5_free_error_message(krb_context, errmsg); >- return; >+ return 0; > } > #endif /* #ifdef HEIMDAL */ > >@@ -160,7 +161,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) > errmsg = krb5_get_error_message(krb_context, problem); > logit("krb5_parse_name(): %.100s", errmsg); > krb5_free_error_message(krb_context, errmsg); >- return; >+ return 0; > } > > if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) { >@@ -169,7 +170,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) > krb5_free_error_message(krb_context, errmsg); > krb5_free_principal(krb_context, princ); > krb5_cc_destroy(krb_context, ccache); >- return; >+ return 0; > } > > krb5_free_principal(krb_context, princ); >@@ -178,7 +179,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) > client->creds, ccache))) { > logit("gss_krb5_copy_ccache() failed"); > krb5_cc_destroy(krb_context, ccache); >- return; >+ return 0; > } > > client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); >@@ -188,13 +189,13 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) > snprintf(client->store.envval, len, "FILE:%s", client->store.filename); > > #ifdef USE_PAM >- if (options.use_pam) >+ if (options.use_pam && set_env) > do_pam_putenv(client->store.envvar, client->store.envval); > #endif > > krb5_cc_close(krb_context, ccache); > >- return; >+ return set_env; > } > > ssh_gssapi_mech gssapi_kerberos_mech = { >diff --git a/gss-serv.c b/gss-serv.c >index 6cae720e..9af5362c 100644 >--- a/gss-serv.c >+++ b/gss-serv.c >@@ -329,13 +329,15 @@ ssh_gssapi_cleanup_creds(void) > } > > /* As user */ >-void >+int > ssh_gssapi_storecreds(void) > { > if (gssapi_client.mech && gssapi_client.mech->storecreds) { >- (*gssapi_client.mech->storecreds)(&gssapi_client); >+ return (*gssapi_client.mech->storecreds)(&gssapi_client); > } else > debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism"); >+ >+ return 0; > } > > /* This allows GSSAPI methods to do things to the childs environment based >diff --git a/session.c b/session.c >index cd03fd42..ead3b0f7 100644 >--- a/session.c >+++ b/session.c >@@ -994,7 +994,8 @@ do_setup_env(Session *s, const char *shell) > /* Allow any GSSAPI methods that we've used to alter > * the childs environment as they see fit > */ >- ssh_gssapi_do_child(&env, &envsize); >+ if (s->authctxt->krb5_set_env) >+ ssh_gssapi_do_child(&env, &envsize); > #endif > > /* Set basic environment. */ >@@ -1108,7 +1109,7 @@ do_setup_env(Session *s, const char *shell) > } > #endif > #ifdef KRB5 >- if (s->authctxt->krb5_ccname) >+ if (s->authctxt->krb5_ccname && s->authctxt->krb5_set_env) > child_set_env(&env, &envsize, "KRB5CCNAME", > s->authctxt->krb5_ccname); > #endif >diff --git a/ssh-gss.h b/ssh-gss.h >index 6593e422..b9528fb8 100644 >--- a/ssh-gss.h >+++ b/ssh-gss.h >@@ -83,7 +83,7 @@ typedef struct ssh_gssapi_mech_struct { > int (*dochild) (ssh_gssapi_client *); > int (*userok) (ssh_gssapi_client *, char *); > int (*localname) (ssh_gssapi_client *, char **); >- void (*storecreds) (ssh_gssapi_client *); >+ int (*storecreds) (ssh_gssapi_client *); > } ssh_gssapi_mech; > > typedef struct { >@@ -127,7 +127,7 @@ int ssh_gssapi_userok(char *name); > OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); > void ssh_gssapi_do_child(char ***, u_int *); > void ssh_gssapi_cleanup_creds(void); >-void ssh_gssapi_storecreds(void); >+int ssh_gssapi_storecreds(void); > const char *ssh_gssapi_displayname(void); > > #endif /* GSSAPI */ >diff --git a/sshd.c b/sshd.c >index 1d19ce67..a58cb276 100644 >--- a/sshd.c >+++ b/sshd.c >@@ -2056,7 +2056,7 @@ main(int ac, char **av) > #ifdef GSSAPI > if (options.gss_authentication) { > temporarily_use_uid(authctxt->pw); >- ssh_gssapi_storecreds(); >+ authctxt->krb5_set_env = ssh_gssapi_storecreds(); > restore_uid(); > } > #endif
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 2775
:
3051
|
3161