vishalmishra434 / rpms / openssh

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