vishalmishra434 / rpms / openssh

Forked from rpms/openssh 3 months ago
Clone
Petr Lautrbach 9fe1af
diff -up openssh-6.1p1/auth2-pubkey.c.akc openssh-6.1p1/auth2-pubkey.c
Petr Lautrbach c9e43c
--- openssh-6.1p1/auth2-pubkey.c.akc	2013-02-14 17:46:45.259546968 +0100
Petr Lautrbach c9e43c
+++ openssh-6.1p1/auth2-pubkey.c	2013-02-14 17:48:19.072137541 +0100
bach f7f8b4
@@ -27,9 +27,13 @@
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 #include <sys/types.h>
Jan F. Chadima 69dd72
 #include <sys/stat.h>
Jan F. Chadima 69dd72
+#include <sys/wait.h>
Jan F. Chadima 69dd72
 
bach f7f8b4
+#include <errno.h>
Jan F. Chadima 69dd72
 #include <fcntl.h>
bach f7f8b4
+#include <paths.h>
Jan F. Chadima 69dd72
 #include <pwd.h>
bach f7f8b4
+#include <signal.h>
bach f7f8b4
 #include <stdio.h>
bach f7f8b4
 #include <stdarg.h>
bach f7f8b4
 #include <string.h>
bach f7f8b4
@@ -260,7 +264,7 @@ match_principals_file(char *file, struct
bach f7f8b4
 			if (strcmp(cp, cert->principals[i]) == 0) {
bach f7f8b4
 				debug3("matched principal \"%.100s\" "
bach f7f8b4
 				    "from file \"%s\" on line %lu",
bach f7f8b4
-			    	    cert->principals[i], file, linenum);
bach f7f8b4
+				    cert->principals[i], file, linenum);
bach f7f8b4
 				if (auth_parse_options(pw, line_opts,
bach f7f8b4
 				    file, linenum) != 1)
bach f7f8b4
 					continue;
bach f7f8b4
@@ -273,31 +277,22 @@ match_principals_file(char *file, struct
bach f7f8b4
 	fclose(f);
bach f7f8b4
 	restore_uid();
bach f7f8b4
 	return 0;
bach f7f8b4
-}	
bach f7f8b4
+}
Jan F. Chadima 69dd72
 
bach f7f8b4
-/* return 1 if user allows given key */
bach f7f8b4
+/*
bach f7f8b4
+ * Checks whether key is allowed in authorized_keys-format file,
bach f7f8b4
+ * returns 1 if the key is allowed or 0 otherwise.
bach f7f8b4
+ */
Jan F. Chadima 69dd72
 static int
Jan F. Chadima 69dd72
-user_key_allowed2(struct passwd *pw, Key *key, char *file)
bach f7f8b4
+check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
Jan F. Chadima 69dd72
 {
Jan F. Chadima 69dd72
 	char line[SSH_MAX_PUBKEY_BYTES];
Jan F. Chadima 69dd72
 	const char *reason;
Jan F. Chadima 69dd72
 	int found_key = 0;
Jan F. Chadima 69dd72
-	FILE *f;
Jan F. Chadima 69dd72
 	u_long linenum = 0;
Jan F. Chadima 69dd72
 	Key *found;
Jan F. Chadima 69dd72
 	char *fp;
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
-	/* Temporarily use the user's uid. */
Jan F. Chadima 69dd72
-	temporarily_use_uid(pw);
Jan F. Chadima 69dd72
-
Jan F. Chadima 69dd72
-	debug("trying public key file %s", file);
Jan F. Chadima 69dd72
-	f = auth_openkeyfile(file, pw, options.strict_modes);
Jan F. Chadima 69dd72
-
Jan F. Chadima 69dd72
-	if (!f) {
Jan F. Chadima 69dd72
-		restore_uid();
Jan F. Chadima 69dd72
-		return 0;
Jan F. Chadima 69dd72
-	}
Jan F. Chadima 69dd72
-
Jan F. Chadima 69dd72
 	found_key = 0;
Jan F. Chadima 69dd72
 	found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
Jan F. Chadima 69dd72
 
bach f7f8b4
@@ -390,8 +385,6 @@ user_key_allowed2(struct passwd *pw, Key
Jan F. Chadima 69dd72
 			break;
Jan F. Chadima 69dd72
 		}
Jan F. Chadima 69dd72
 	}
Jan F. Chadima 69dd72
-	restore_uid();
Jan F. Chadima 69dd72
-	fclose(f);
Jan F. Chadima 69dd72
 	key_free(found);
Jan F. Chadima 69dd72
 	if (!found_key)
Jan F. Chadima 69dd72
 		debug2("key not found");
Petr Lautrbach c9e43c
@@ -453,7 +446,180 @@ user_cert_trusted_ca(struct passwd *pw,
Jan F. Chadima 69dd72
 	return ret;
Jan F. Chadima 69dd72
 }
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
-/* check whether given key is in .ssh/authorized_keys* */
bach f7f8b4
+/*
bach f7f8b4
+ * Checks whether key is allowed in file.
bach f7f8b4
+ * returns 1 if the key is allowed or 0 otherwise.
bach f7f8b4
+ */
Jan F. Chadima 69dd72
+static int
Jan F. Chadima 69dd72
+user_key_allowed2(struct passwd *pw, Key *key, char *file)
Jan F. Chadima 69dd72
+{
Jan F. Chadima 69dd72
+	FILE *f;
Jan F. Chadima 69dd72
+	int found_key = 0;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	/* Temporarily use the user's uid. */
Jan F. Chadima 69dd72
+	temporarily_use_uid(pw);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	debug("trying public key file %s", file);
bach f7f8b4
+	if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) {
bach f7f8b4
+		found_key = check_authkeys_file(f, file, key, pw);
Jan F. Chadima 69dd72
+		fclose(f);
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	restore_uid();
Jan F. Chadima 69dd72
+	return found_key;
Jan F. Chadima 69dd72
+}
Jan F. Chadima 69dd72
+
bach f7f8b4
+/*
bach f7f8b4
+ * Checks whether key is allowed in output of command.
bach f7f8b4
+ * returns 1 if the key is allowed or 0 otherwise.
bach f7f8b4
+ */
Jan F. Chadima 69dd72
+static int
bach f7f8b4
+user_key_command_allowed2(struct passwd *user_pw, Key *key)
Jan F. Chadima 69dd72
+{
Jan F. Chadima 69dd72
+	FILE *f;
bach f7f8b4
+	int ok, found_key = 0;
bach f7f8b4
+	struct passwd *pw;
Jan F. Chadima 69dd72
+	struct stat st;
bach f7f8b4
+	int status, devnull, p[2], i;
bach f7f8b4
+	pid_t pid;
Petr Lautrbach c9e43c
+	char *username, errmsg[512];
Jan F. Chadima 69dd72
+
bach f7f8b4
+	if (options.authorized_keys_command == NULL ||
bach f7f8b4
+	    options.authorized_keys_command[0] != '/')
Jan F. Chadima 1df0cf
+		return 0;
Jan F. Chadima 69dd72
+
Petr Lautrbach c9e43c
+	if (options.authorized_keys_command_user == NULL) {
Petr Lautrbach c9e43c
+		error("No user for AuthorizedKeysCommand specified, skipping");
Petr Lautrbach c9e43c
+		return 0;
Petr Lautrbach c9e43c
+	}
Petr Lautrbach c9e43c
+
Petr Lautrbach c9e43c
+	username = percent_expand(options.authorized_keys_command_user,
Petr Lautrbach c9e43c
+	    "u", user_pw->pw_name, (char *)NULL);
Petr Lautrbach c9e43c
+	pw = getpwnam(username);
Petr Lautrbach c9e43c
+	if (pw == NULL) {
Petr Lautrbach c9e43c
+		error("AuthorizedKeyCommandUser \"%s\" not found: %s",
Petr Lautrbach c9e43c
+		    username, strerror(errno));
Petr Lautrbach c9e43c
+		free(username);
Petr Lautrbach c9e43c
+		return 0;
Jan F. Chadima 69dd72
+	}
Petr Lautrbach c9e43c
+	free(username);
Jan F. Chadima 69dd72
+
bach f7f8b4
+	temporarily_use_uid(pw);
Petr Lautrbach c9e43c
+
bach f7f8b4
+	if (stat(options.authorized_keys_command, &st) < 0) {
bach f7f8b4
+		error("Could not stat AuthorizedKeysCommand \"%s\": %s",
bach f7f8b4
+		    options.authorized_keys_command, strerror(errno));
bach f7f8b4
+		goto out;
Jan F. Chadima 69dd72
+	}
bach f7f8b4
+	if (auth_secure_path(options.authorized_keys_command, &st, NULL, 0,
bach f7f8b4
+	    errmsg, sizeof(errmsg)) != 0) {
bach f7f8b4
+		error("Unsafe AuthorizedKeysCommand: %s", errmsg);
bach f7f8b4
+		goto out;
Jan F. Chadima 69dd72
+	}
Jan F. Chadima 69dd72
+
bach f7f8b4
+	if (pipe(p) != 0) {
bach f7f8b4
+		error("%s: pipe: %s", __func__, strerror(errno));
bach f7f8b4
+		goto out;
Petr Lautrbach c9e43c
+	}
bach f7f8b4
+
Petr Lautrbach c9e43c
+	debug3("Running AuthorizedKeysCommand: \"%s %s\" as \"%s\"",
Petr Lautrbach c9e43c
+	    options.authorized_keys_command, user_pw->pw_name, pw->pw_name);
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+	/*
bach f7f8b4
+	 * Don't want to call this in the child, where it can fatal() and
bach f7f8b4
+	 * run cleanup_exit() code.
Jan F. Chadima 69dd72
+	 */
bach f7f8b4
+	restore_uid();
Jan F. Chadima 69dd72
+
bach f7f8b4
+	switch ((pid = fork())) {
bach f7f8b4
+	case -1: /* error */
bach f7f8b4
+		error("%s: fork: %s", __func__, strerror(errno));
bach f7f8b4
+		close(p[0]);
bach f7f8b4
+		close(p[1]);
bach f7f8b4
+		return 0;
bach f7f8b4
+	case 0: /* child */
bach f7f8b4
+		for (i = 0; i < NSIG; i++)
bach f7f8b4
+			signal(i, SIG_DFL);
bach f7f8b4
+
Petr Lautrbach c9e43c
+		if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
Petr Lautrbach c9e43c
+			error("%s: open %s: %s", __func__, _PATH_DEVNULL,
Petr Lautrbach c9e43c
+			    strerror(errno));
Petr Lautrbach c9e43c
+			_exit(1);
Petr Lautrbach c9e43c
+		}
Petr Lautrbach c9e43c
+		/* Keep stderr around a while longer to catch errors */
Petr Lautrbach c9e43c
+		if (dup2(devnull, STDIN_FILENO) == -1 ||
Petr Lautrbach c9e43c
+		    dup2(p[1], STDOUT_FILENO) == -1) {
Petr Lautrbach c9e43c
+			error("%s: dup2: %s", __func__, strerror(errno));
Petr Lautrbach c9e43c
+			_exit(1);
Petr Lautrbach c9e43c
+		}
Petr Lautrbach c9e43c
+		closefrom(STDERR_FILENO + 1);
Petr Lautrbach c9e43c
+
bach f7f8b4
+		/* Don't use permanently_set_uid() here to avoid fatal() */
bach f7f8b4
+		if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
bach f7f8b4
+			error("setresgid %u: %s", (u_int)pw->pw_gid,
bach f7f8b4
+			    strerror(errno));
bach f7f8b4
+			_exit(1);
Jan F. Chadima 69dd72
+		}
bach f7f8b4
+		if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
bach f7f8b4
+			error("setresuid %u: %s", (u_int)pw->pw_uid,
bach f7f8b4
+			    strerror(errno));
bach f7f8b4
+			_exit(1);
Jan F. Chadima 69dd72
+		}
Petr Lautrbach c9e43c
+		/* stdin is pointed to /dev/null at this point */
Petr Lautrbach c9e43c
+		if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
bach f7f8b4
+			error("%s: dup2: %s", __func__, strerror(errno));
bach f7f8b4
+			_exit(1);
Jan F. Chadima 69dd72
+		}
Jan F. Chadima 69dd72
+
bach f7f8b4
+		execl(options.authorized_keys_command,
Petr Lautrbach c9e43c
+		    options.authorized_keys_command, user_pw->pw_name, NULL);
Jan F. Chadima 69dd72
+
bach f7f8b4
+		error("AuthorizedKeysCommand %s exec failed: %s",
bach f7f8b4
+		    options.authorized_keys_command, strerror(errno));
Jan F. Chadima 69dd72
+		_exit(127);
bach f7f8b4
+	default: /* parent */
bach f7f8b4
+		break;
Jan F. Chadima 69dd72
+	}
Petr Lautrbach c9e43c
+
bach f7f8b4
+	temporarily_use_uid(pw);
Jan F. Chadima 69dd72
+
bach f7f8b4
+	close(p[1]);
bach f7f8b4
+	if ((f = fdopen(p[0], "r")) == NULL) {
bach f7f8b4
+		error("%s: fdopen: %s", __func__, strerror(errno));
bach f7f8b4
+		close(p[0]);
bach f7f8b4
+		/* Don't leave zombie child */
Petr Lautrbach c9e43c
+		kill(pid, SIGTERM);
bach f7f8b4
+		while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
bach f7f8b4
+			;
bach f7f8b4
+		goto out;
bach f7f8b4
+	}
bach f7f8b4
+	ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
bach f7f8b4
+	fclose(f);
Jan F. Chadima 69dd72
+
bach f7f8b4
+	while (waitpid(pid, &status, 0) == -1) {
bach f7f8b4
+		if (errno != EINTR) {
bach f7f8b4
+			error("%s: waitpid: %s", __func__, strerror(errno));
bach f7f8b4
+			goto out;
bach f7f8b4
+		}
bach f7f8b4
+	}
bach f7f8b4
+	if (WIFSIGNALED(status)) {
bach f7f8b4
+		error("AuthorizedKeysCommand %s exited on signal %d",
bach f7f8b4
+		    options.authorized_keys_command, WTERMSIG(status));
bach f7f8b4
+		goto out;
bach f7f8b4
+	} else if (WEXITSTATUS(status) != 0) {
bach f7f8b4
+		error("AuthorizedKeysCommand %s returned status %d",
bach f7f8b4
+		    options.authorized_keys_command, WEXITSTATUS(status));
bach f7f8b4
+		goto out;
bach f7f8b4
+	}
bach f7f8b4
+	found_key = ok;
bach f7f8b4
+ out:
bach f7f8b4
+	restore_uid();
Jan F. Chadima 69dd72
+	return found_key;
Jan F. Chadima 69dd72
+}
Jan F. Chadima 69dd72
+
bach f7f8b4
+/*
bach f7f8b4
+ * Check whether key authenticates and authorises the user.
bach f7f8b4
+ */
Jan F. Chadima 69dd72
 int
Jan F. Chadima 69dd72
 user_key_allowed(struct passwd *pw, Key *key)
Jan F. Chadima 69dd72
 {
Petr Lautrbach c9e43c
@@ -469,9 +635,17 @@ user_key_allowed(struct passwd *pw, Key
bach f7f8b4
 	if (success)
bach f7f8b4
 		return success;
Tomas Mraz fc87f2
 
bach f7f8b4
+	success = user_key_command_allowed2(pw, key);
Tomas Mraz fc87f2
+	if (success > 0)
Tomas Mraz fc87f2
+		return success;
Tomas Mraz fc87f2
+
bach f7f8b4
 	for (i = 0; !success && i < options.num_authkeys_files; i++) {
Petr Lautrbach c9e43c
+
Petr Lautrbach c9e43c
+		if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
Petr Lautrbach c9e43c
+			continue;
bach f7f8b4
 		file = expand_authorized_keys(
bach f7f8b4
 		    options.authorized_keys_files[i], pw);
Petr Lautrbach c9e43c
+
Petr Lautrbach c9e43c
 		success = user_key_allowed2(pw, key, file);
Petr Lautrbach c9e43c
 		xfree(file);
Petr Lautrbach c9e43c
 	}
Petr Lautrbach 5039c7
diff -up openssh-6.1p1/auth.c.akc openssh-6.1p1/auth.c
Petr Lautrbach c9e43c
--- openssh-6.1p1/auth.c.akc	2013-02-14 17:46:45.189547274 +0100
Petr Lautrbach c9e43c
+++ openssh-6.1p1/auth.c	2013-02-14 17:46:45.273546907 +0100
Petr Lautrbach c9e43c
@@ -415,39 +415,41 @@ check_key_in_hostfiles(struct passwd *pw
Petr Lautrbach 5039c7
 
Petr Lautrbach 5039c7
 
Petr Lautrbach 5039c7
 /*
Petr Lautrbach 5039c7
- * Check a given file for security. This is defined as all components
Petr Lautrbach 5039c7
+ * Check a given path for security. This is defined as all components
Petr Lautrbach 5039c7
  * of the path to the file must be owned by either the owner of
Petr Lautrbach 5039c7
  * of the file or root and no directories must be group or world writable.
Petr Lautrbach 5039c7
  *
Petr Lautrbach 5039c7
  * XXX Should any specific check be done for sym links ?
Petr Lautrbach 5039c7
  *
Petr Lautrbach 5039c7
- * Takes an open file descriptor, the file name, a uid and and
Petr Lautrbach 5039c7
+ * Takes an the file name, its stat information (preferably from fstat() to
Petr Lautrbach 5039c7
+ * avoid races), the uid of the expected owner, their home directory and an
Petr Lautrbach 5039c7
  * error buffer plus max size as arguments.
Petr Lautrbach 5039c7
  *
Petr Lautrbach 5039c7
  * Returns 0 on success and -1 on failure
Petr Lautrbach 5039c7
  */
Petr Lautrbach 5039c7
-static int
Petr Lautrbach 5039c7
-secure_filename(FILE *f, const char *file, struct passwd *pw,
Petr Lautrbach 5039c7
-    char *err, size_t errlen)
Petr Lautrbach 5039c7
+int
Petr Lautrbach 5039c7
+auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
Petr Lautrbach 5039c7
+    uid_t uid, char *err, size_t errlen)
Petr Lautrbach 5039c7
 {
Petr Lautrbach 5039c7
-	uid_t uid = pw->pw_uid;
Petr Lautrbach 5039c7
 	char buf[MAXPATHLEN], homedir[MAXPATHLEN];
Petr Lautrbach 5039c7
 	char *cp;
Petr Lautrbach 5039c7
 	int comparehome = 0;
Petr Lautrbach 5039c7
 	struct stat st;
Petr Lautrbach 5039c7
 
Petr Lautrbach 5039c7
-	if (realpath(file, buf) == NULL) {
Petr Lautrbach 5039c7
-		snprintf(err, errlen, "realpath %s failed: %s", file,
Petr Lautrbach 5039c7
+	if (realpath(name, buf) == NULL) {
Petr Lautrbach 5039c7
+		snprintf(err, errlen, "realpath %s failed: %s", name,
Petr Lautrbach 5039c7
 		    strerror(errno));
Petr Lautrbach 5039c7
 		return -1;
Petr Lautrbach 5039c7
 	}
Petr Lautrbach 5039c7
-	if (realpath(pw->pw_dir, homedir) != NULL)
Petr Lautrbach 5039c7
+	if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
Petr Lautrbach 5039c7
 		comparehome = 1;
Petr Lautrbach 5039c7
 
Petr Lautrbach 5039c7
-	/* check the open file to avoid races */
Petr Lautrbach 5039c7
-	if (fstat(fileno(f), &st) < 0 ||
Petr Lautrbach 5039c7
-	    (st.st_uid != 0 && st.st_uid != uid) ||
Petr Lautrbach 5039c7
-	    (st.st_mode & 022) != 0) {
Petr Lautrbach 5039c7
+	if (!S_ISREG(stp->st_mode)) {
Petr Lautrbach 5039c7
+		snprintf(err, errlen, "%s is not a regular file", buf);
Petr Lautrbach 5039c7
+		return -1;
Petr Lautrbach 5039c7
+	}
Petr Lautrbach 5039c7
+	if ((stp->st_uid != 0 && stp->st_uid != uid) ||
Petr Lautrbach 5039c7
+	    (stp->st_mode & 022) != 0) {
Petr Lautrbach 5039c7
 		snprintf(err, errlen, "bad ownership or modes for file %s",
Petr Lautrbach 5039c7
 		    buf);
Petr Lautrbach 5039c7
 		return -1;
Petr Lautrbach c9e43c
@@ -483,6 +485,31 @@ secure_filename(FILE *f, const char *fil
Petr Lautrbach 5039c7
 	return 0;
Petr Lautrbach 5039c7
 }
Petr Lautrbach 5039c7
 
Petr Lautrbach 5039c7
+/*
Petr Lautrbach 5039c7
+ * Version of secure_path() that accepts an open file descriptor to
Petr Lautrbach 5039c7
+ * avoid races.
Petr Lautrbach 5039c7
+ *
Petr Lautrbach 5039c7
+ * Returns 0 on success and -1 on failure
Petr Lautrbach 5039c7
+ */
Petr Lautrbach 5039c7
+static int
Petr Lautrbach 5039c7
+secure_filename(FILE *f, const char *file, struct passwd *pw,
Petr Lautrbach 5039c7
+    char *err, size_t errlen)
Petr Lautrbach 5039c7
+{
Petr Lautrbach 5039c7
+	uid_t uid = pw->pw_uid;
Petr Lautrbach 5039c7
+	char buf[MAXPATHLEN], homedir[MAXPATHLEN];
Petr Lautrbach 5039c7
+	char *cp;
Petr Lautrbach 5039c7
+	int comparehome = 0;
Petr Lautrbach 5039c7
+	struct stat st;
Petr Lautrbach 5039c7
+
Petr Lautrbach 5039c7
+	/* check the open file to avoid races */
Petr Lautrbach 5039c7
+	if (fstat(fileno(f), &st) < 0) {
Petr Lautrbach 5039c7
+		snprintf(err, errlen, "cannot stat file %s: %s",
Petr Lautrbach 5039c7
+		    buf, strerror(errno));
Petr Lautrbach 5039c7
+		return -1;
Petr Lautrbach 5039c7
+	}
Petr Lautrbach 5039c7
+	return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
Petr Lautrbach 5039c7
+}
Petr Lautrbach 5039c7
+
Petr Lautrbach 5039c7
 static FILE *
Petr Lautrbach 5039c7
 auth_openfile(const char *file, struct passwd *pw, int strict_modes,
Petr Lautrbach 5039c7
     int log_missing, char *file_type)
Petr Lautrbach 5039c7
diff -up openssh-6.1p1/auth.h.akc openssh-6.1p1/auth.h
Petr Lautrbach c9e43c
--- openssh-6.1p1/auth.h.akc	2013-02-14 17:46:45.259546968 +0100
Petr Lautrbach c9e43c
+++ openssh-6.1p1/auth.h	2013-02-14 17:46:45.274546903 +0100
Petr Lautrbach 5039c7
@@ -125,6 +125,10 @@ int	 auth_rhosts_rsa_key_allowed(struct
Petr Lautrbach 5039c7
 int	 hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
Petr Lautrbach 5039c7
 int	 user_key_allowed(struct passwd *, Key *);
Petr Lautrbach 5039c7
 
Petr Lautrbach 5039c7
+struct stat;
Petr Lautrbach 5039c7
+int	 auth_secure_path(const char *, struct stat *, const char *, uid_t,
Petr Lautrbach 5039c7
+    char *, size_t);
Petr Lautrbach 5039c7
+
Petr Lautrbach 5039c7
 #ifdef KRB5
Petr Lautrbach 5039c7
 int	auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *);
Petr Lautrbach 5039c7
 int	auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt);
Petr Lautrbach 9fe1af
diff -up openssh-6.1p1/servconf.c.akc openssh-6.1p1/servconf.c
Petr Lautrbach c9e43c
--- openssh-6.1p1/servconf.c.akc	2013-02-14 17:46:45.193547257 +0100
Petr Lautrbach c9e43c
+++ openssh-6.1p1/servconf.c	2013-02-14 17:46:45.274546903 +0100
Petr Lautrbach 5039c7
@@ -137,6 +137,8 @@ initialize_server_options(ServerOptions
Jan F. Chadima 69dd72
 	options->num_permitted_opens = -1;
Jan F. Chadima 69dd72
 	options->adm_forced_command = NULL;
Jan F. Chadima 69dd72
 	options->chroot_directory = NULL;
Jan F. Chadima 69dd72
+	options->authorized_keys_command = NULL;
bach f7f8b4
+	options->authorized_keys_command_user = NULL;
Jan F. Chadima 69dd72
 	options->zero_knowledge_password_authentication = -1;
Jan F. Chadima 69dd72
 	options->revoked_keys_file = NULL;
Jan F. Chadima 69dd72
 	options->trusted_user_ca_keys = NULL;
Petr Lautrbach 5039c7
@@ -331,6 +333,7 @@ typedef enum {
Jan F. Chadima 69dd72
 	sZeroKnowledgePasswordAuthentication, sHostCertificate,
Jan F. Chadima 69dd72
 	sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
Petr Lautrbach 9fe1af
 	sKexAlgorithms, sIPQoS, sVersionAddendum,
bach f7f8b4
+	sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
Petr Lautrbach 5039c7
 	sAuthenticationMethods,
Jan F. Chadima 69dd72
 	sDeprecated, sUnsupported
Jan F. Chadima 69dd72
 } ServerOpCodes;
Petr Lautrbach 5039c7
@@ -457,6 +460,9 @@ static struct {
Petr Lautrbach 5039c7
 	{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
Jan F. Chadima 69dd72
 	{ "ipqos", sIPQoS, SSHCFG_ALL },
Petr Lautrbach 5039c7
 	{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
Jan F. Chadima 69dd72
+	{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
bach f7f8b4
+	{ "authorizedkeyscommandrunas", sAuthorizedKeysCommandUser, SSHCFG_ALL },
bach f7f8b4
+	{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
Petr Lautrbach 5039c7
 	{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
Jan F. Chadima 69dd72
 	{ NULL, sBadOption, 0 }
Jan F. Chadima 69dd72
 };
Petr Lautrbach 5039c7
@@ -1520,6 +1526,26 @@ process_server_config_line(ServerOptions
Jan F. Chadima 69dd72
 		}
Petr Lautrbach 9fe1af
 		return 0;
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+	case sAuthorizedKeysCommand:
Jan F. Chadima 69dd72
+		len = strspn(cp, WHITESPACE);
bach f7f8b4
+		if (*activep && options->authorized_keys_command == NULL) {
Jan F. Chadima 69dd72
+			options->authorized_keys_command = xstrdup(cp + len);
bach f7f8b4
+			if (*options->authorized_keys_command != '/') {
bach f7f8b4
+				fatal("%.200s line %d: AuthorizedKeysCommand "
bach f7f8b4
+				    "must be an absolute path",
bach f7f8b4
+				    filename, linenum);
bach f7f8b4
+			}
bach f7f8b4
+		}
Jan F. Chadima 69dd72
+		return 0;
Jan F. Chadima 69dd72
+
bach f7f8b4
+	case sAuthorizedKeysCommandUser:
bach f7f8b4
+		charptr = &options->authorized_keys_command_user;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+		arg = strdelim(&cp;;
Jan F. Chadima 69dd72
+		if (*activep && *charptr == NULL)
Jan F. Chadima 69dd72
+			*charptr = xstrdup(arg);
Jan F. Chadima 69dd72
+		break;
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
 	case sDeprecated:
Jan F. Chadima 69dd72
 		logit("%s line %d: Deprecated option %s",
Jan F. Chadima 69dd72
 		    filename, linenum, arg);
Petr Lautrbach 5039c7
@@ -1670,6 +1696,8 @@ copy_set_server_options(ServerOptions *d
Petr Lautrbach d9e618
 	M_CP_INTOPT(hostbased_uses_name_from_packet_only);
Petr Lautrbach d9e618
 	M_CP_INTOPT(kbd_interactive_authentication);
Jan F. Chadima 69dd72
 	M_CP_INTOPT(zero_knowledge_password_authentication);
Jan F. Chadima 69dd72
+	M_CP_STROPT(authorized_keys_command);
bach f7f8b4
+	M_CP_STROPT(authorized_keys_command_user);
Jan F. Chadima 69dd72
 	M_CP_INTOPT(permit_root_login);
Jan F. Chadima 69dd72
 	M_CP_INTOPT(permit_empty_passwd);
Jan F. Chadima 69dd72
 
Petr Lautrbach 5039c7
@@ -1930,6 +1958,8 @@ dump_config(ServerOptions *o)
Jan F. Chadima 69dd72
 	dump_cfg_string(sAuthorizedPrincipalsFile,
Jan F. Chadima 69dd72
 	    o->authorized_principals_file);
Petr Lautrbach 9fe1af
 	dump_cfg_string(sVersionAddendum, o->version_addendum);
Jan F. Chadima 69dd72
+	dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command);
bach f7f8b4
+	dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user);
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
 	/* string arguments requiring a lookup */
Jan F. Chadima 69dd72
 	dump_cfg_string(sLogLevel, log_level_name(o->log_level));
Petr Lautrbach 9fe1af
diff -up openssh-6.1p1/servconf.h.akc openssh-6.1p1/servconf.h
Petr Lautrbach c9e43c
--- openssh-6.1p1/servconf.h.akc	2013-02-14 17:46:45.194547252 +0100
Petr Lautrbach c9e43c
+++ openssh-6.1p1/servconf.h	2013-02-14 17:46:45.275546898 +0100
Petr Lautrbach 5039c7
@@ -167,6 +167,8 @@ typedef struct {
Jan F. Chadima 69dd72
 	char   *revoked_keys_file;
Jan F. Chadima 69dd72
 	char   *trusted_user_ca_keys;
Jan F. Chadima 69dd72
 	char   *authorized_principals_file;
Jan F. Chadima 69dd72
+	char   *authorized_keys_command;
bach f7f8b4
+	char   *authorized_keys_command_user;
Jan F. Chadima 69dd72
 
Petr Lautrbach 9fe1af
 	char   *version_addendum;	/* Appended to SSH banner */
Petr Lautrbach 5039c7
 
bach f7f8b4
diff -up openssh-6.1p1/sshd.c.akc openssh-6.1p1/sshd.c
Petr Lautrbach c9e43c
--- openssh-6.1p1/sshd.c.akc	2013-02-14 17:46:45.270546920 +0100
Petr Lautrbach c9e43c
+++ openssh-6.1p1/sshd.c	2013-02-14 17:46:45.276546894 +0100
bach f7f8b4
@@ -366,9 +366,20 @@ main_sigchld_handler(int sig)
bach f7f8b4
 static void
bach f7f8b4
 grace_alarm_handler(int sig)
bach f7f8b4
 {
bach f7f8b4
+	pid_t pgid;
bach f7f8b4
+
bach f7f8b4
 	if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0)
bach f7f8b4
 		kill(pmonitor->m_pid, SIGALRM);
bach f7f8b4
 
bach f7f8b4
+	/*
bach f7f8b4
+	 * Try to kill any processes that we have spawned, E.g. authorized
bach f7f8b4
+	 * keys command helpers.
bach f7f8b4
+	 */
bach f7f8b4
+	if ((pgid = getpgid(0)) == getpid()) {
bach f7f8b4
+		signal(SIGTERM, SIG_IGN);
bach f7f8b4
+		killpg(pgid, SIGTERM);
bach f7f8b4
+	}
bach f7f8b4
+
bach f7f8b4
 	/* Log error and exit. */
bach f7f8b4
 	sigdie("Timeout before authentication for %s", get_remote_ipaddr());
bach f7f8b4
 }
Petr Lautrbach 9fe1af
diff -up openssh-6.1p1/sshd_config.0.akc openssh-6.1p1/sshd_config.0
Petr Lautrbach 9fe1af
--- openssh-6.1p1/sshd_config.0.akc	2012-08-29 02:53:04.000000000 +0200
Petr Lautrbach c9e43c
+++ openssh-6.1p1/sshd_config.0	2013-02-14 17:46:45.276546894 +0100
Jan F. Chadima 69dd72
@@ -71,6 +71,23 @@ DESCRIPTION
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
              See PATTERNS in ssh_config(5) for more information on patterns.
Jan F. Chadima 69dd72
 
Jan F. Chadima 69dd72
+     AuthorizedKeysCommand
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+             Specifies a program to be used for lookup of the user's
Jan F. Chadima 69dd72
+	     public keys.  The program will be invoked with its first
Petr Lautrbach d9e618
+	     argument the name of the user being authorized, and should produce
Petr Lautrbach d9e618
+	     on standard output AuthorizedKeys lines (see AUTHORIZED_KEYS
Jan F. Chadima 69dd72
+	     in sshd(8)).  By default (or when set to the empty string) there is no
Jan F. Chadima 69dd72
+	     AuthorizedKeysCommand run.  If the AuthorizedKeysCommand does not successfully
Jan F. Chadima 69dd72
+	     authorize the user, authorization falls through to the
Jan F. Chadima 69dd72
+	     AuthorizedKeysFile.  Note that this option has an effect
Jan F. Chadima 69dd72
+	     only with PubkeyAuthentication turned on.
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
+     AuthorizedKeysCommandRunAs
Jan F. Chadima 69dd72
+             Specifies the user under whose account the AuthorizedKeysCommand is run.
Jan F. Chadima 69dd72
+             Empty string (the default value) means the user being authorized
Jan F. Chadima 69dd72
+             is used.
Jan F. Chadima 69dd72
+
Jan F. Chadima 69dd72
      AuthorizedKeysFile
Jan F. Chadima 69dd72
              Specifies the file that contains the public keys that can be used
Jan F. Chadima 69dd72
              for user authentication.  The format is described in the
Petr Lautrbach 9fe1af
@@ -402,7 +419,8 @@ DESCRIPTION
Jan F. Chadima 69dd72
              Only a subset of keywords may be used on the lines following a
Petr Lautrbach 9fe1af
              Match keyword.  Available keywords are AcceptEnv,
Petr Lautrbach 9fe1af
              AllowAgentForwarding, AllowGroups, AllowTcpForwarding,
Petr Lautrbach 9fe1af
-             AllowUsers, AuthorizedKeysFile, AuthorizedPrincipalsFile, Banner,
Petr Lautrbach 9fe1af
+             AllowUsers, AuthorizedKeysFile, AuthorizedKeysCommand,
Petr Lautrbach 9fe1af
+             AuthorizedKeysCommandRunAs, AuthorizedPrincipalsFile, Banner,
Petr Lautrbach 9fe1af
              ChrootDirectory, DenyGroups, DenyUsers, ForceCommand,
Petr Lautrbach 9fe1af
              GatewayPorts, GSSAPIAuthentication, HostbasedAuthentication,
Jan F. Chadima 69dd72
              HostbasedUsesNameFromPacketOnly, KbdInteractiveAuthentication,
Petr Lautrbach 9fe1af
diff -up openssh-6.1p1/sshd_config.5.akc openssh-6.1p1/sshd_config.5
Petr Lautrbach c9e43c
--- openssh-6.1p1/sshd_config.5.akc	2013-02-14 17:46:45.195547248 +0100
Petr Lautrbach c9e43c
+++ openssh-6.1p1/sshd_config.5	2013-02-14 17:46:45.277546890 +0100
Petr Lautrbach 5039c7
@@ -173,6 +173,20 @@ Note that each authentication method lis
Petr Lautrbach 5039c7
 in the configuration.
Petr Lautrbach 5039c7
 The default is not to require multiple authentication; successful completion
Petr Lautrbach 5039c7
 of a single authentication method is sufficient.
Petr Lautrbach d9e618
+.It Cm AuthorizedKeysCommand
bach f7f8b4
+Specifies a program to be used for lookup of the user's public keys.
bach f7f8b4
+The program will be invoked with a single argument of the username
bach f7f8b4
+being authenticated, and should produce on standard output zero or
bach f7f8b4
+more lines of authorized_keys output (see AUTHORIZED_KEYS in
bach f7f8b4
+.Xr sshd 8 )
bach f7f8b4
+If a key supplied by AuthorizedKeysCommand does not successfully authenticate
bach f7f8b4
+and authorize the user then public key authentication continues using the usual
bach f7f8b4
+.Cm AuthorizedKeysFile
bach f7f8b4
+files.
bach f7f8b4
+By default, no AuthorizedKeysCommand is run.
bach f7f8b4
+.It Cm AuthorizedKeysCommandUser
bach f7f8b4
+Specifies the user under whose account the AuthorizedKeysCommand is run.
bach f7f8b4
+The default is the user being authenticated.
Petr Lautrbach d9e618
 .It Cm AuthorizedKeysFile
Petr Lautrbach d9e618
 Specifies the file that contains the public keys that can be used
Petr Lautrbach d9e618
 for user authentication.
Petr Lautrbach 5039c7
@@ -734,6 +748,8 @@ Available keywords are
Jan F. Chadima 69dd72
 .Cm AllowTcpForwarding ,
Petr Lautrbach 9fe1af
 .Cm AllowUsers ,
Petr Lautrbach 5039c7
 .Cm AuthenticationMethods ,
Jan F. Chadima 69dd72
+.Cm AuthorizedKeysCommand ,
bach f7f8b4
+.Cm AuthorizedKeysCommandUser ,
Petr Lautrbach 5039c7
 .Cm AuthorizedKeysFile ,
Jan F. Chadima 69dd72
 .Cm AuthorizedPrincipalsFile ,
Jan F. Chadima 69dd72
 .Cm Banner ,
Petr Lautrbach 5039c7
@@ -749,6 +765,7 @@ Available keywords are
Jan F. Chadima 69dd72
 .Cm KerberosAuthentication ,
Jan F. Chadima 69dd72
 .Cm MaxAuthTries ,
Jan F. Chadima 69dd72
 .Cm MaxSessions ,
Jan F. Chadima 69dd72
+.Cm PubkeyAuthentication ,
Jan F. Chadima 69dd72
 .Cm PasswordAuthentication ,
Jan F. Chadima 69dd72
 .Cm PermitEmptyPasswords ,
Jan F. Chadima 69dd72
 .Cm PermitOpen ,
Petr Lautrbach 5039c7
diff -up openssh-6.1p1/sshd_config.akc openssh-6.1p1/sshd_config
Petr Lautrbach 5039c7
--- openssh-6.1p1/sshd_config.akc	2012-07-31 04:21:34.000000000 +0200
Petr Lautrbach c9e43c
+++ openssh-6.1p1/sshd_config	2013-02-14 17:46:45.277546890 +0100
Petr Lautrbach 5039c7
@@ -49,6 +49,9 @@
Petr Lautrbach 5039c7
 # but this is overridden so installations will only check .ssh/authorized_keys
Petr Lautrbach 5039c7
 AuthorizedKeysFile	.ssh/authorized_keys
Petr Lautrbach 5039c7
 
Petr Lautrbach 5039c7
+#AuthorizedKeysCommand none
Petr Lautrbach 5039c7
+#AuthorizedKeysCommandUser nobody
Petr Lautrbach 5039c7
+
Petr Lautrbach 5039c7
 #AuthorizedPrincipalsFile none
Petr Lautrbach 5039c7
 
Petr Lautrbach 5039c7
 # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts