|
|
8f2528 |
diff -up openssh-6.3p1/auth-krb5.c.ccache_name openssh-6.3p1/auth-krb5.c
|
|
|
8f2528 |
--- openssh-6.3p1/auth-krb5.c.ccache_name 2013-10-23 22:03:52.322950759 +0200
|
|
|
8f2528 |
+++ openssh-6.3p1/auth-krb5.c 2013-10-23 22:04:24.295799873 +0200
|
|
|
8f2528 |
@@ -50,7 +50,9 @@
|
|
|
8f2528 |
#include <errno.h>
|
|
|
8f2528 |
#include <unistd.h>
|
|
|
8f2528 |
#include <string.h>
|
|
|
8f2528 |
+#include <sys/stat.h>
|
|
|
8f2528 |
#include <krb5.h>
|
|
|
8f2528 |
+#include <profile.h>
|
|
|
8f2528 |
|
|
|
8f2528 |
extern ServerOptions options;
|
|
|
8f2528 |
|
|
|
8f2528 |
@@ -91,6 +93,7 @@ auth_krb5_password(Authctxt *authctxt, c
|
|
|
8f2528 |
#endif
|
|
|
8f2528 |
krb5_error_code problem;
|
|
|
8f2528 |
krb5_ccache ccache = NULL;
|
|
|
8f2528 |
+ const char *ccache_type;
|
|
|
8f2528 |
int len;
|
|
|
8f2528 |
char *client, *platform_client;
|
|
|
8f2528 |
const char *errmsg;
|
|
|
8f2528 |
@@ -191,12 +194,30 @@ auth_krb5_password(Authctxt *authctxt, c
|
|
|
8f2528 |
goto out;
|
|
|
8f2528 |
#endif
|
|
|
8f2528 |
|
|
|
8f2528 |
+ ccache_type = krb5_cc_get_type(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
|
|
|
8f2528 |
authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
|
|
|
8f2528 |
|
|
|
8f2528 |
- len = strlen(authctxt->krb5_ticket_file) + 6;
|
|
|
8f2528 |
+ if (authctxt->krb5_ticket_file[0] == ':')
|
|
|
8f2528 |
+ authctxt->krb5_ticket_file++;
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ len = strlen(authctxt->krb5_ticket_file) + strlen(ccache_type) + 2;
|
|
|
8f2528 |
authctxt->krb5_ccname = xmalloc(len);
|
|
|
8f2528 |
- snprintf(authctxt->krb5_ccname, len, "FILE:%s",
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+#ifdef USE_CCAPI
|
|
|
8f2528 |
+ snprintf(authctxt->krb5_ccname, len, "API:%s",
|
|
|
8f2528 |
authctxt->krb5_ticket_file);
|
|
|
8f2528 |
+#else
|
|
|
8f2528 |
+ snprintf(authctxt->krb5_ccname, len, "%s:%s",
|
|
|
8f2528 |
+ ccache_type, authctxt->krb5_ticket_file);
|
|
|
8f2528 |
+#endif
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ if (strcmp(ccache_type, "DIR") == 0) {
|
|
|
8f2528 |
+ char *p;
|
|
|
8f2528 |
+ p = strrchr(authctxt->krb5_ccname, '/');
|
|
|
8f2528 |
+ if (p)
|
|
|
8f2528 |
+ *p = '\0';
|
|
|
8f2528 |
+ }
|
|
|
8f2528 |
+
|
|
|
8f2528 |
|
|
|
8f2528 |
#ifdef USE_PAM
|
|
|
8f2528 |
if (options.use_pam)
|
|
|
8f2528 |
@@ -235,10 +256,34 @@ auth_krb5_password(Authctxt *authctxt, c
|
|
|
8f2528 |
void
|
|
|
8f2528 |
krb5_cleanup_proc(Authctxt *authctxt)
|
|
|
8f2528 |
{
|
|
|
8f2528 |
+ struct stat krb5_ccname_stat;
|
|
|
8f2528 |
+ char krb5_ccname[128], *krb5_ccname_dir_start, *krb5_ccname_dir_end;
|
|
|
8f2528 |
+
|
|
|
8f2528 |
debug("krb5_cleanup_proc called");
|
|
|
8f2528 |
if (authctxt->krb5_fwd_ccache) {
|
|
|
8f2528 |
krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
|
|
|
8f2528 |
authctxt->krb5_fwd_ccache = NULL;
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ strncpy(krb5_ccname, authctxt->krb5_ccname, sizeof(krb5_ccname) - 10);
|
|
|
8f2528 |
+ krb5_ccname_dir_start = strchr(krb5_ccname, ':') + 1;
|
|
|
8f2528 |
+ *krb5_ccname_dir_start++ = '\0';
|
|
|
8f2528 |
+ if (strcmp(krb5_ccname, "DIR") == 0) {
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ strcat(krb5_ccname_dir_start, "/primary");
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ if (stat(krb5_ccname_dir_start, &krb5_ccname_stat) == 0) {
|
|
|
8f2528 |
+ if (unlink(krb5_ccname_dir_start) == 0) {
|
|
|
8f2528 |
+ krb5_ccname_dir_end = strrchr(krb5_ccname_dir_start, '/');
|
|
|
8f2528 |
+ *krb5_ccname_dir_end = '\0';
|
|
|
8f2528 |
+ if (rmdir(krb5_ccname_dir_start) == -1)
|
|
|
8f2528 |
+ debug("cache dir '%s' remove failed: %s", krb5_ccname_dir_start, strerror(errno));
|
|
|
8f2528 |
+ }
|
|
|
8f2528 |
+ else
|
|
|
8f2528 |
+ debug("cache primary file '%s', remove failed: %s",
|
|
|
8f2528 |
+ krb5_ccname_dir_start, strerror(errno)
|
|
|
8f2528 |
+ );
|
|
|
8f2528 |
+ }
|
|
|
8f2528 |
+ }
|
|
|
8f2528 |
}
|
|
|
8f2528 |
if (authctxt->krb5_user) {
|
|
|
8f2528 |
krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
|
|
|
8f2528 |
@@ -250,34 +295,139 @@ krb5_cleanup_proc(Authctxt *authctxt)
|
|
|
8f2528 |
}
|
|
|
8f2528 |
}
|
|
|
8f2528 |
|
|
|
8f2528 |
+int
|
|
|
8f2528 |
+ssh_asprintf_append(char **dsc, const char *fmt, ...) {
|
|
|
8f2528 |
+ char *src, *old;
|
|
|
8f2528 |
+ va_list ap;
|
|
|
8f2528 |
+ int i;
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ va_start(ap, fmt);
|
|
|
8f2528 |
+ i = vasprintf(&src, fmt, ap);
|
|
|
8f2528 |
+ va_end(ap);
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ if (i == -1 || src == NULL)
|
|
|
8f2528 |
+ return -1;
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ old = *dsc;
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ i = asprintf(dsc, "%s%s", *dsc, src);
|
|
|
8f2528 |
+ if (i == -1 || src == NULL) {
|
|
|
8f2528 |
+ free(src);
|
|
|
8f2528 |
+ return -1;
|
|
|
8f2528 |
+ }
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ free(old);
|
|
|
8f2528 |
+ free(src);
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ return i;
|
|
|
8f2528 |
+}
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+int
|
|
|
8f2528 |
+ssh_krb5_expand_template(char **result, const char *template) {
|
|
|
8f2528 |
+ char *p_n, *p_o, *r, *tmp_template;
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ if (template == NULL)
|
|
|
8f2528 |
+ return -1;
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ tmp_template = p_n = p_o = xstrdup(template);
|
|
|
8f2528 |
+ r = xstrdup("");
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ while ((p_n = strstr(p_o, "%{")) != NULL) {
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ *p_n++ = '\0';
|
|
|
8f2528 |
+ if (ssh_asprintf_append(&r, "%s", p_o) == -1)
|
|
|
8f2528 |
+ goto cleanup;
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ if (strncmp(p_n, "{uid}", 5) == 0 || strncmp(p_n, "{euid}", 6) == 0 ||
|
|
|
8f2528 |
+ strncmp(p_n, "{USERID}", 8) == 0) {
|
|
|
8f2528 |
+ p_o = strchr(p_n, '}') + 1;
|
|
|
8f2528 |
+ if (ssh_asprintf_append(&r, "%d", geteuid()) == -1)
|
|
|
8f2528 |
+ goto cleanup;
|
|
|
8f2528 |
+ continue;
|
|
|
8f2528 |
+ }
|
|
|
8f2528 |
+ else if (strncmp(p_n, "{TEMP}", 6) == 0) {
|
|
|
8f2528 |
+ p_o = strchr(p_n, '}') + 1;
|
|
|
8f2528 |
+ if (ssh_asprintf_append(&r, "/tmp") == -1)
|
|
|
8f2528 |
+ goto cleanup;
|
|
|
8f2528 |
+ continue;
|
|
|
8f2528 |
+ } else {
|
|
|
8f2528 |
+ p_o = strchr(p_n, '}') + 1;
|
|
|
8f2528 |
+ p_o = '\0';
|
|
|
8f2528 |
+ debug("%s: unsupported token %s in %s", __func__, p_n, template);
|
|
|
8f2528 |
+ /* unknown token, fallback to the default */
|
|
|
8f2528 |
+ goto cleanup;
|
|
|
8f2528 |
+ }
|
|
|
8f2528 |
+ }
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ if (ssh_asprintf_append(&r, "%s", p_o) == -1)
|
|
|
8f2528 |
+ goto cleanup;
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ *result = r;
|
|
|
8f2528 |
+ free(tmp_template);
|
|
|
8f2528 |
+ return 0;
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+cleanup:
|
|
|
8f2528 |
+ free(r);
|
|
|
8f2528 |
+ free(tmp_template);
|
|
|
8f2528 |
+ return -1;
|
|
|
8f2528 |
+}
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+krb5_error_code
|
|
|
8f2528 |
+ssh_krb5_get_cctemplate(krb5_context ctx, char **ccname) {
|
|
|
8f2528 |
+ profile_t p;
|
|
|
8f2528 |
+ int ret = 0;
|
|
|
8f2528 |
+ char *value = NULL;
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ ret = krb5_get_profile(ctx, &p);
|
|
|
8f2528 |
+ if (ret)
|
|
|
8f2528 |
+ return ret;
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ ret = profile_get_string(p, "libdefaults", "default_ccache_name", NULL, NULL, &value);
|
|
|
8f2528 |
+ if (ret)
|
|
|
8f2528 |
+ return ret;
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ ret = ssh_krb5_expand_template(ccname, value);
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ return ret;
|
|
|
8f2528 |
+}
|
|
|
8f2528 |
+
|
|
|
8f2528 |
#ifndef HEIMDAL
|
|
|
8f2528 |
krb5_error_code
|
|
|
8f2528 |
ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
|
|
|
8f2528 |
int tmpfd, ret, oerrno;
|
|
|
8f2528 |
- char ccname[40];
|
|
|
8f2528 |
+ char *ccname;
|
|
|
8f2528 |
+#ifdef USE_CCAPI
|
|
|
8f2528 |
+ char cctemplate[] = "API:krb5cc_%d";
|
|
|
8f2528 |
+#else
|
|
|
8f2528 |
mode_t old_umask;
|
|
|
8f2528 |
+ char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX";
|
|
|
8f2528 |
|
|
|
8f2528 |
- ret = snprintf(ccname, sizeof(ccname),
|
|
|
8f2528 |
- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
|
|
|
8f2528 |
- if (ret < 0 || (size_t)ret >= sizeof(ccname))
|
|
|
8f2528 |
- return ENOMEM;
|
|
|
8f2528 |
-
|
|
|
8f2528 |
- old_umask = umask(0177);
|
|
|
8f2528 |
- tmpfd = mkstemp(ccname + strlen("FILE:"));
|
|
|
8f2528 |
- oerrno = errno;
|
|
|
8f2528 |
- umask(old_umask);
|
|
|
8f2528 |
- if (tmpfd == -1) {
|
|
|
8f2528 |
- logit("mkstemp(): %.100s", strerror(oerrno));
|
|
|
8f2528 |
- return oerrno;
|
|
|
8f2528 |
- }
|
|
|
8f2528 |
+#endif
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ ret = ssh_krb5_get_cctemplate(ctx, &ccname);
|
|
|
8f2528 |
|
|
|
8f2528 |
- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
|
|
|
8f2528 |
+ if (ret) {
|
|
|
8f2528 |
+ ret = asprintf(&ccname, cctemplate, geteuid());
|
|
|
8f2528 |
+ if (ret == -1)
|
|
|
8f2528 |
+ return ENOMEM;
|
|
|
8f2528 |
+ old_umask = umask(0177);
|
|
|
8f2528 |
+ tmpfd = mkstemp(ccname + strlen("FILE:"));
|
|
|
8f2528 |
oerrno = errno;
|
|
|
8f2528 |
- logit("fchmod(): %.100s", strerror(oerrno));
|
|
|
8f2528 |
+ umask(old_umask);
|
|
|
8f2528 |
+ if (tmpfd == -1) {
|
|
|
8f2528 |
+ logit("mkstemp(): %.100s", strerror(oerrno));
|
|
|
8f2528 |
+ return oerrno;
|
|
|
8f2528 |
+ }
|
|
|
8f2528 |
+
|
|
|
8f2528 |
+ if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
|
|
|
8f2528 |
+ oerrno = errno;
|
|
|
8f2528 |
+ logit("fchmod(): %.100s", strerror(oerrno));
|
|
|
8f2528 |
+ close(tmpfd);
|
|
|
8f2528 |
+ return oerrno;
|
|
|
8f2528 |
+ }
|
|
|
8f2528 |
close(tmpfd);
|
|
|
8f2528 |
- return oerrno;
|
|
|
8f2528 |
}
|
|
|
8f2528 |
- close(tmpfd);
|
|
|
8f2528 |
+ debug("%s: Setting ccname to %s", __func__, ccname);
|
|
|
8f2528 |
|
|
|
8f2528 |
return (krb5_cc_resolve(ctx, ccname, ccache));
|
|
|
8f2528 |
}
|