diff -uprk.orig openssh-3.6.1p1.orig/auth2-pubkey.c openssh-3.6.1p1/auth2-pubkey.c --- openssh-3.6.1p1.orig/auth2-pubkey.c 2002-06-07 00:27:56 +0400 +++ openssh-3.6.1p1/auth2-pubkey.c 2003-04-11 19:33:27 +0400 @@ -257,8 +257,8 @@ user_key_allowed2(struct passwd *pw, Key } /* check whether given key is in .ssh/authorized_keys* */ -int -user_key_allowed(struct passwd *pw, Key *key) +static int +user_user_key_allowed(struct passwd *pw, Key *key) { int success; char *file; @@ -276,6 +276,60 @@ user_key_allowed(struct passwd *pw, Key return success; } +/* check whether given key is in /etc/openssh/authorized_keys* */ +static int +user_system_key_allowed(struct passwd *pw, Key *key, int *found) +{ + int success = 0; + char *file; + struct stat st; + + *found = 0; + file = authorized_keys_system_file(pw); + debug("checking public key system file %s", file); + if (stat(file, &st) == 0) { + *found = 1; + success = user_key_allowed2(pw, key, file); + xfree(file); + if (success) + return success; + } else + xfree(file); + + /* try suffix "2" for backward compat, too */ + file = authorized_keys_system_file2(pw); + debug("checking public key system file2 %s", file); + if (stat(file, &st) == 0) { + *found = 1; + success = user_key_allowed2(pw, key, file); + xfree(file); + return success; + } + xfree(file); + + return success; +} + +/* + * check whether given key is in /etc/openssh/authorized_keys* + * if not found, check whether given key is in .ssh/authorized_keys* + */ +int +user_key_allowed(struct passwd *pw, Key *key) +{ + int found, success; + + /* no user given */ + if (!pw) + return 0; + + success = user_system_key_allowed(pw, key, &found); + if (!found) + success = user_user_key_allowed(pw, key); + + return success; +} + Authmethod method_pubkey = { "publickey", userauth_pubkey, diff -uprk.orig openssh-3.6.1p1.orig/auth.c openssh-3.6.1p1/auth.c --- openssh-3.6.1p1.orig/auth.c 2003-04-11 19:33:10 +0400 +++ openssh-3.6.1p1/auth.c 2003-04-11 19:33:27 +0400 @@ -360,6 +360,18 @@ expand_filename(const char *filename, st } char * +authorized_keys_system_file(struct passwd *pw) +{ + return expand_filename(options.authorized_keys_system_file, pw); +} + +char * +authorized_keys_system_file2(struct passwd *pw) +{ + return expand_filename(options.authorized_keys_system_file2, pw); +} + +char * authorized_keys_file(struct passwd *pw) { return expand_filename(options.authorized_keys_file, pw); diff -uprk.orig openssh-3.6.1p1.orig/auth.h openssh-3.6.1p1/auth.h --- openssh-3.6.1p1.orig/auth.h 2002-09-27 07:26:01 +0400 +++ openssh-3.6.1p1/auth.h 2003-04-11 19:33:27 +0400 @@ -163,6 +163,8 @@ int verify_response(Authctxt *, const ch struct passwd * auth_get_user(void); char *expand_filename(const char *, struct passwd *); +char *authorized_keys_system_file(struct passwd *); +char *authorized_keys_system_file2(struct passwd *); char *authorized_keys_file(struct passwd *); char *authorized_keys_file2(struct passwd *); diff -uprk.orig openssh-3.6.1p1.orig/auth-rsa.c openssh-3.6.1p1/auth-rsa.c --- openssh-3.6.1p1.orig/auth-rsa.c 2002-06-11 19:47:42 +0400 +++ openssh-3.6.1p1/auth-rsa.c 2003-04-11 19:33:27 +0400 @@ -165,15 +165,21 @@ auth_rsa_key_allowed(struct passwd *pw, temporarily_use_uid(pw); /* The authorized keys. */ - file = authorized_keys_file(pw); - debug("trying public RSA key file %s", file); + file = authorized_keys_system_file(pw); + debug("trying public RSA key system file %s", file); - /* Fail quietly if file does not exist */ if (stat(file, &st) < 0) { - /* Restore the privileged uid. */ - restore_uid(); xfree(file); - return (0); + file = authorized_keys_file(pw); + debug("trying public RSA key user file %s", file); + + /* Fail quietly if file does not exist */ + if (stat(file, &st) < 0) { + /* Restore the privileged uid. */ + restore_uid(); + xfree(file); + return (0); + } } /* Open the file containing the authorized keys. */ f = fopen(file, "r"); diff -uprk.orig openssh-3.6.1p1.orig/pathnames.h openssh-3.6.1p1/pathnames.h --- openssh-3.6.1p1.orig/pathnames.h 2002-06-06 23:57:34 +0400 +++ openssh-3.6.1p1/pathnames.h 2003-04-11 19:33:27 +0400 @@ -92,9 +92,11 @@ * may need to be world-readable. (This file is read by the daemon which is * running as root.) */ +#define _PATH_SSH_SYSTEM_PERMITTED_KEYS SSHDIR "/authorized_keys/%u" #define _PATH_SSH_USER_PERMITTED_KEYS ".ssh/authorized_keys" /* backward compat for protocol v2 */ +#define _PATH_SSH_SYSTEM_PERMITTED_KEYS2 SSHDIR "/authorized_keys2/%u" #define _PATH_SSH_USER_PERMITTED_KEYS2 ".ssh/authorized_keys2" /* diff -uprk.orig openssh-3.6.1p1.orig/servconf.c openssh-3.6.1p1/servconf.c --- openssh-3.6.1p1.orig/servconf.c 2003-04-11 19:33:10 +0400 +++ openssh-3.6.1p1/servconf.c 2003-04-11 19:33:27 +0400 @@ -121,6 +121,8 @@ initialize_server_options(ServerOptions options->verify_reverse_mapping = -1; options->client_alive_interval = -1; options->client_alive_count_max = -1; + options->authorized_keys_system_file = NULL; + options->authorized_keys_system_file2 = NULL; options->authorized_keys_file = NULL; options->authorized_keys_file2 = NULL; @@ -246,6 +248,15 @@ fill_default_server_options(ServerOption options->client_alive_interval = 0; if (options->client_alive_count_max == -1) options->client_alive_count_max = 3; + if (options->authorized_keys_system_file2 == NULL) { + /* authorized_keys_system_file2 falls back to authorized_keys_system_file */ + if (options->authorized_keys_system_file != NULL) + options->authorized_keys_system_file2 = options->authorized_keys_system_file; + else + options->authorized_keys_system_file2 = _PATH_SSH_SYSTEM_PERMITTED_KEYS2; + } + if (options->authorized_keys_system_file == NULL) + options->authorized_keys_system_file = _PATH_SSH_SYSTEM_PERMITTED_KEYS; if (options->authorized_keys_file2 == NULL) { /* authorized_keys_file2 falls back to authorized_keys_file */ if (options->authorized_keys_file != NULL) @@ -301,6 +312,7 @@ typedef enum { sBanner, sVerifyReverseMapping, sHostbasedAuthentication, sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, + sAuthorizedKeysSystemFile, sAuthorizedKeysSystemFile2, sUsePrivilegeSeparation, sDeprecated } ServerOpCodes; @@ -377,6 +389,8 @@ static struct { { "reversemappingcheck", sVerifyReverseMapping }, { "clientaliveinterval", sClientAliveInterval }, { "clientalivecountmax", sClientAliveCountMax }, + { "authorizedkeyssystemfile", sAuthorizedKeysSystemFile }, + { "authorizedkeyssystemfile2", sAuthorizedKeysSystemFile2 }, { "authorizedkeysfile", sAuthorizedKeysFile }, { "authorizedkeysfile2", sAuthorizedKeysFile2 }, { "useprivilegeseparation", sUsePrivilegeSeparation}, @@ -894,6 +908,13 @@ parse_flag: * * AuthorizedKeysFile /etc/ssh_keys/%u */ + case sAuthorizedKeysSystemFile: + case sAuthorizedKeysSystemFile2: + charptr = (opcode == sAuthorizedKeysSystemFile ) ? + &options->authorized_keys_system_file : + &options->authorized_keys_system_file2; + goto parse_filename; + case sAuthorizedKeysFile: case sAuthorizedKeysFile2: charptr = (opcode == sAuthorizedKeysFile ) ? diff -uprk.orig openssh-3.6.1p1.orig/servconf.h openssh-3.6.1p1/servconf.h --- openssh-3.6.1p1.orig/servconf.h 2002-08-01 05:28:39 +0400 +++ openssh-3.6.1p1/servconf.h 2003-04-11 19:33:27 +0400 @@ -129,6 +129,8 @@ typedef struct { * disconnect the session */ + char *authorized_keys_system_file; /* File containing system public keys */ + char *authorized_keys_system_file2; char *authorized_keys_file; /* File containing public keys */ char *authorized_keys_file2; int pam_authentication_via_kbd_int; diff -uprk.orig openssh-3.6.1p1.orig/sshd_config.5 openssh-3.6.1p1/sshd_config.5 --- openssh-3.6.1p1.orig/sshd_config.5 2003-04-01 15:42:14 +0400 +++ openssh-3.6.1p1/sshd_config.5 2003-04-11 19:33:27 +0400 @@ -116,6 +116,23 @@ is taken to be an absolute path or one r directory. The default is .Dq .ssh/authorized_keys . +.It Cm AuthorizedKeysSystemFile +Specifies the file that contains the public keys that can be used +for user authentication. +.Cm AuthorizedKeysSystemFile +may contain tokens of the form %T which are substituted during connection +set-up. The following tokens are defined: %% is replaced by a literal '%', +%h is replaced by the home directory of the user being authenticated and +%u is replaced by the username of that user. +After expansion, +.Cm AuthorizedKeysSystemFile +is taken to be an absolute path or one relative to the user's home +directory. +If that file exists, it will be tried before +.Cm AuthorizedKeysFile +file. +The default is +.Dq /etc/openssh/authorized_keys/%u . .It Cm Banner In some jurisdictions, sending a warning message before authentication may be relevant for getting legal protection.