diff -up openssh-5.3p1/auth2-pubkey.c.pka openssh-5.3p1/auth2-pubkey.c
--- openssh-5.3p1/auth2-pubkey.c.pka 2009-03-08 01:40:28.000000000 +0100
+++ openssh-5.3p1/auth2-pubkey.c 2010-01-04 16:07:53.000000000 +0100
@@ -175,26 +175,14 @@ done:
/* return 1 if user allows given key */
static int
-user_key_allowed2(struct passwd *pw, Key *key, char *file)
+user_search_key_in_file(FILE *f, char *file, Key* key, struct passwd *pw)
{
char line[SSH_MAX_PUBKEY_BYTES];
int found_key = 0;
- FILE *f;
u_long linenum = 0;
Key *found;
char *fp;
- /* Temporarily use the user's uid. */
- temporarily_use_uid(pw);
-
- debug("trying public key file %s", file);
- f = auth_openkeyfile(file, pw, options.strict_modes);
-
- if (!f) {
- restore_uid();
- return 0;
- }
-
found_key = 0;
found = key_new(key->type);
@@ -239,21 +227,160 @@ user_key_allowed2(struct passwd *pw, Key
break;
}
}
- restore_uid();
- fclose(f);
key_free(found);
if (!found_key)
debug2("key not found");
return found_key;
}
-/* check whether given key is in .ssh/authorized_keys* */
+
+/* return 1 if user allows given key */
+static int
+user_key_allowed2(struct passwd *pw, Key *key, char *file)
+{
+ FILE *f;
+ int found_key = 0;
+
+ /* Temporarily use the user's uid. */
+ temporarily_use_uid(pw);
+
+ debug("trying public key file %s", file);
+ f = auth_openkeyfile(file, pw, options.strict_modes);
+
+ if (f) {
+ found_key = user_search_key_in_file (f, file, key, pw);
+ fclose(f);
+ }
+
+ restore_uid();
+ return found_key;
+}
+
+#ifdef WITH_PUBKEY_AGENT
+
+#define WHITESPACE " \t\r\n"
+
+/* return 1 if user allows given key */
+static int
+user_key_via_agent_allowed2(struct passwd *pw, Key *key)
+{
+ FILE *f;
+ int found_key = 0;
+ char *pubkey_agent_string = NULL;
+ char *tmp_pubkey_agent_string = NULL;
+ char *progname;
+ char *cp;
+ struct passwd *runas_pw;
+ struct stat st;
+
+ if (options.pubkey_agent == NULL || options.pubkey_agent[0] != '/')
+ return -1;
+
+ /* get the run as identity from config */
+ runas_pw = (options.pubkey_agent_runas == NULL)? pw
+ : getpwnam (options.pubkey_agent_runas);
+ if (!runas_pw) {
+ error("%s: getpwnam(\"%s\"): %s", __func__,
+ options.pubkey_agent_runas, strerror(errno));
+ return 0;
+ }
+
+ /* Temporarily use the specified uid. */
+ if (runas_pw->pw_uid != 0)
+ temporarily_use_uid(runas_pw);
+
+ pubkey_agent_string = percent_expand(options.pubkey_agent,
+ "h", pw->pw_dir, "u", pw->pw_name, (char *)NULL);
+
+ /* Test whether agent can be modified by non root user */
+ tmp_pubkey_agent_string = xstrdup (pubkey_agent_string);
+ progname = strtok (tmp_pubkey_agent_string, WHITESPACE);
+
+ debug3("%s: checking program '%s'", __func__, progname);
+
+ if (stat (progname, &st) < 0) {
+ error("%s: stat(\"%s\"): %s", __func__,
+ progname, strerror(errno));
+ goto go_away;
+ }
+
+ if (st.st_uid != 0 || (st.st_mode & 022) != 0) {
+ error("bad ownership or modes for pubkey agent \"%s\"",
+ progname);
+ goto go_away;
+ }
+
+ if (!S_ISREG(st.st_mode)) {
+ error("pubkey agent \"%s\" is not a regular file",
+ progname);
+ goto go_away;
+ }
+
+ /*
+ * Descend the path, checking that each component is a
+ * root-owned directory with strict permissions.
+ */
+ do {
+ if ((cp = strrchr(progname, '/')) == NULL)
+ break;
+ else
+ *cp = '\0';
+
+ debug3("%s: checking component '%s'", __func__, progname);
+
+ if (stat(progname, &st) != 0) {
+ error("%s: stat(\"%s\"): %s", __func__,
+ progname, strerror(errno));
+ goto go_away;
+ }
+ if (st.st_uid != 0 || (st.st_mode & 022) != 0) {
+ error("bad ownership or modes for pubkey agent path component \"%s\"",
+ progname);
+ goto go_away;
+ }
+ if (!S_ISDIR(st.st_mode)) {
+ error("pubkey agent path component \"%s\" is not a directory",
+ progname);
+ goto go_away;
+ }
+ } while (0);
+
+ /* open the pipe and read the keys */
+ f = popen (pubkey_agent_string, "r");
+ if (!f) {
+ error("%s: popen (\"%s\", \"r\"): %s", __func__,
+ pubkey_agent_string, strerror (errno));
+ goto go_away;
+ }
+
+ found_key = user_search_key_in_file (f, options.pubkey_agent, key, pw);
+ pclose (f);
+
+go_away:
+ if (tmp_pubkey_agent_string)
+ xfree (tmp_pubkey_agent_string);
+ if (pubkey_agent_string)
+ xfree (pubkey_agent_string);
+
+ if (runas_pw->pw_uid != 0)
+ restore_uid();
+ return found_key;
+}
+#endif
+
+/* check whether given key is in <pkey_agent or .ssh/authorized_keys* */
int
user_key_allowed(struct passwd *pw, Key *key)
{
int success;
char *file;
+#ifdef WITH_PUBKEY_AGENT
+ success = user_key_via_agent_allowed2(pw, key);
+ if (success >= 0)
+ return success;
+#endif
+
file = authorized_keys_file(pw);
success = user_key_allowed2(pw, key, file);
xfree(file);
diff -up openssh-5.3p1/configure.pka openssh-5.3p1/configure
--- openssh-5.3p1/configure.pka 2009-10-13 19:27:51.000000000 +0200
+++ openssh-5.3p1/configure 2009-10-15 06:26:33.000000000 +0200
@@ -769,6 +769,7 @@ with_skey
with_tcp_wrappers
with_libedit
with_audit
+with_pka
with_ssl_dir
with_openssl_header_check
with_ssl_engine
@@ -1473,6 +1474,7 @@ Optional Packages:
--with-tcp-wrappers[=PATH] Enable tcpwrappers support (optionally in PATH)
--with-libedit[=PATH] Enable libedit support for sftp
--with-audit=module Enable EXPERIMENTAL audit support (modules=debug,bsm)
+ --with-pka Enable pubkey agent support
--with-ssl-dir=PATH Specify path to OpenSSL installation
--without-openssl-header-check Disable OpenSSL version consistency check
--with-ssl-engine Enable OpenSSL (hardware) ENGINE support
@@ -13443,6 +13445,25 @@ $as_echo "$as_me: error: Unknown audit m
fi
+# Check whether user wants pubkey agent support
+PKA_MSG="no"
+
+# Check whether --with-pka was given.
+if test "${with_pka+set}" = set; then
+ withval=$with_pka;
+ if test "x$withval" != "xno" ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define WITH_PUBKEY_AGENT 1
+_ACEOF
+
+ PKA_MSG="yes"
+ fi
+
+
+fi
+
+
@@ -32772,6 +32793,7 @@ echo " Linux audit support
echo " Smartcard support: $SCARD_MSG"
echo " S/KEY support: $SKEY_MSG"
echo " TCP Wrappers support: $TCPW_MSG"
+echo " PKA support: $PKA_MSG"
echo " MD5 password support: $MD5_MSG"
echo " libedit support: $LIBEDIT_MSG"
echo " Solaris process contract support: $SPC_MSG"
diff -up openssh-5.3p1/configure.ac.pka openssh-5.3p1/configure.ac
--- openssh-5.3p1/configure.ac.pka 2009-09-11 06:56:08.000000000 +0200
+++ openssh-5.3p1/configure.ac 2010-01-04 16:07:53.000000000 +0100
@@ -1319,6 +1319,18 @@ AC_ARG_WITH(audit,
esac ]
)
+# Check whether user wants pubkey agent support
+PKA_MSG="no"
+AC_ARG_WITH(pka,
+ [ --with-pka Enable pubkey agent support],
+ [
+ if test "x$withval" != "xno" ; then
+ AC_DEFINE([WITH_PUBKEY_AGENT], 1, [Enable pubkey agent support])
+ PKA_MSG="yes"
+ fi
+ ]
+)
+
dnl Checks for library functions. Please keep in alphabetical order
AC_CHECK_FUNCS( \
arc4random \
@@ -4229,6 +4241,7 @@ echo " SELinux support
echo " Smartcard support: $SCARD_MSG"
echo " S/KEY support: $SKEY_MSG"
echo " TCP Wrappers support: $TCPW_MSG"
+echo " PKA support: $PKA_MSG"
echo " MD5 password support: $MD5_MSG"
echo " libedit support: $LIBEDIT_MSG"
echo " Solaris process contract support: $SPC_MSG"
diff -up openssh-5.3p1/servconf.c.pka openssh-5.3p1/servconf.c
--- openssh-5.3p1/servconf.c.pka 2009-06-21 12:26:17.000000000 +0200
+++ openssh-5.3p1/servconf.c 2010-01-04 16:07:53.000000000 +0100
@@ -127,6 +127,8 @@ initialize_server_options(ServerOptions
options->num_permitted_opens = -1;
options->adm_forced_command = NULL;
options->chroot_directory = NULL;
+ options->pubkey_agent = NULL;
+ options->pubkey_agent_runas = NULL;
options->zero_knowledge_password_authentication = -1;
}
@@ -306,6 +308,7 @@ typedef enum {
sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding,
sZeroKnowledgePasswordAuthentication,
+ sPubkeyAgent, sPubkeyAgentRunAs,
sDeprecated, sUnsupported
} ServerOpCodes;
@@ -424,6 +427,13 @@ static struct {
{ "permitopen", sPermitOpen, SSHCFG_ALL },
{ "forcecommand", sForceCommand, SSHCFG_ALL },
{ "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
+#ifdef WITH_PUBKEY_AGENT
+ { "pubkeyagent", sPubkeyAgent, SSHCFG_ALL },
+ { "pubkeyagentrunas", sPubkeyAgentRunAs, SSHCFG_ALL },
+#else
+ { "pubkeyagent", sUnsupported, SSHCFG_ALL },
+ { "pubkeyagentrunas", sUnsupported, SSHCFG_ALL },
+#endif
{ NULL, sBadOption, 0 }
};
@@ -1294,6 +1304,20 @@ process_server_config_line(ServerOptions
*charptr = xstrdup(arg);
break;
+ case sPubkeyAgent:
+ len = strspn(cp, WHITESPACE);
+ if (*activep && options->pubkey_agent == NULL)
+ options->pubkey_agent = xstrdup(cp + len);
+ return 0;
+
+ case sPubkeyAgentRunAs:
+ charptr = &options->pubkey_agent_runas;
+
+ arg = strdelim(&cp);
+ if (*activep && *charptr == NULL)
+ *charptr = xstrdup(arg);
+ break;
+
case sDeprecated:
logit("%s line %d: Deprecated option %s",
filename, linenum, arg);
@@ -1387,6 +1411,8 @@ copy_set_server_options(ServerOptions *d
M_CP_INTOPT(gss_authentication);
M_CP_INTOPT(rsa_authentication);
M_CP_INTOPT(pubkey_authentication);
+ M_CP_STROPT(pubkey_agent);
+ M_CP_STROPT(pubkey_agent_runas);
M_CP_INTOPT(kerberos_authentication);
M_CP_INTOPT(hostbased_authentication);
M_CP_INTOPT(kbd_interactive_authentication);
@@ -1626,6 +1652,10 @@ dump_config(ServerOptions *o)
dump_cfg_string(sAuthorizedKeysFile, o->authorized_keys_file);
dump_cfg_string(sAuthorizedKeysFile2, o->authorized_keys_file2);
dump_cfg_string(sForceCommand, o->adm_forced_command);
+#ifdef WITH_PUBKEY_AGENT
+ dump_cfg_string(sPubkeyAgent, o->pubkey_agent);
+ dump_cfg_string(sPubkeyAgentRunAs, o->pubkey_agent_runas);
+#endif
/* string arguments requiring a lookup */
dump_cfg_string(sLogLevel, log_level_name(o->log_level));
diff -up openssh-5.3p1/servconf.h.pka openssh-5.3p1/servconf.h
--- openssh-5.3p1/servconf.h.pka 2009-01-28 06:31:23.000000000 +0100
+++ openssh-5.3p1/servconf.h 2010-01-04 16:07:53.000000000 +0100
@@ -151,6 +151,8 @@ typedef struct {
int num_permitted_opens;
char *chroot_directory;
+ char *pubkey_agent;
+ char *pubkey_agent_runas;
} ServerOptions;
void initialize_server_options(ServerOptions *);
diff -up openssh-5.3p1/sshd_config.0.pka openssh-5.3p1/sshd_config.0
--- openssh-5.3p1/sshd_config.0.pka 2009-09-26 08:31:16.000000000 +0200
+++ openssh-5.3p1/sshd_config.0 2010-01-04 16:07:53.000000000 +0100
@@ -344,10 +344,11 @@ DESCRIPTION
AllowTcpForwarding, Banner, ChrootDirectory, ForceCommand,
GatewayPorts, GSSAPIAuthentication, HostbasedAuthentication,
KbdInteractiveAuthentication, KerberosAuthentication,
- MaxAuthTries, MaxSessions, PasswordAuthentication,
- PermitEmptyPasswords, PermitOpen, PermitRootLogin,
- RhostsRSAAuthentication, RSAAuthentication, X11DisplayOffset,
- X11Forwarding and X11UseLocalHost.
+ MaxAuthTries, MaxSessions, PubkeyAuthentication, PubkeyAgent,
+ PubkeyAgentRunAs, PasswordAuthentication, PermitEmptyPasswords,
+ PermitOpen, PermitRootLogin, RhostsRSAAuthentication,
+ RSAAuthentication, X11DisplayOffset, X11Forwarding and
+ X11UseLocalHost.
MaxAuthTries
Specifies the maximum number of authentication attempts permitted
@@ -455,6 +456,17 @@ DESCRIPTION
fault is ``yes''. Note that this option applies to protocol ver-
sion 2 only.
+ PubkeyAgent
+ Specifies which agent is used for lookup of the user's public
+ keys. Empty string means to use the authorized_keys file. By
+ default there is no PubkeyAgent set. Note that this option has
+ an effect only with PubkeyAuthentication switched on.
+
+ PubkeyAgentRunAs
+ Specifies the user under whose account the PubkeyAgent is run.
+ Empty string (the default value) means the user being authorized
+ is used.
+
RhostsRSAAuthentication
Specifies whether rhosts or /etc/hosts.equiv authentication to-
gether with successful RSA host authentication is allowed. The
diff -up openssh-5.3p1/sshd_config.pka openssh-5.3p1/sshd_config
--- openssh-5.3p1/sshd_config.pka 2008-07-02 14:35:43.000000000 +0200
+++ openssh-5.3p1/sshd_config 2010-01-04 16:07:53.000000000 +0100
@@ -46,6 +46,8 @@ Protocol 2
#RSAAuthentication yes
#PubkeyAuthentication yes
#AuthorizedKeysFile .ssh/authorized_keys
+#PubkeyAgent none
+#PubkeyAgentRunAs nobody
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#RhostsRSAAuthentication no
diff -up openssh-5.3p1/sshd_config.5.pka openssh-5.3p1/sshd_config.5
--- openssh-5.3p1/sshd_config.5.pka 2009-08-28 02:27:08.000000000 +0200
+++ openssh-5.3p1/sshd_config.5 2010-01-04 16:07:53.000000000 +0100
@@ -610,6 +610,9 @@ Available keywords are
.Cm KerberosAuthentication ,
.Cm MaxAuthTries ,
.Cm MaxSessions ,
+.Cm PubkeyAuthentication ,
+.Cm PubkeyAgent ,
+.Cm PubkeyAgentRunAs ,
.Cm PasswordAuthentication ,
.Cm PermitEmptyPasswords ,
.Cm PermitOpen ,
@@ -805,6 +808,16 @@ Specifies whether public key authenticat
The default is
.Dq yes .
Note that this option applies to protocol version 2 only.
+.It Cm PubkeyAgent
+Specifies which agent is used for lookup of the user's public
+keys. Empty string means to use the authorized_keys file.
+By default there is no PubkeyAgent set.
+Note that this option has an effect only with PubkeyAuthentication
+switched on.
+.It Cm PubkeyAgentRunAs
+Specifies the user under whose account the PubkeyAgent is run. Empty
+string (the default value) means the user being authorized is used.
+.Dq
.It Cm RhostsRSAAuthentication
Specifies whether rhosts or /etc/hosts.equiv authentication together
with successful RSA host authentication is allowed.