[auth-rsa.c auth.c auth.h auth2.c servconf.c servconf.h sshd.8
      sshd_config]
     configurable authorized_keys{,2} location; originally from peter@;
     ok djm@
This commit is contained in:
Ben Lindstrom 2001-06-05 20:25:05 +00:00
parent e259544876
commit bfb3a0e973
9 changed files with 247 additions and 94 deletions

View File

@ -42,6 +42,11 @@
- stevesk@cvs.openbsd.org 2001/05/19 19:57:09
[channels.c]
typo in error message
- markus@cvs.openbsd.org 2001/05/20 17:20:36
[auth-rsa.c auth.c auth.h auth2.c servconf.c servconf.h sshd.8
sshd_config]
configurable authorized_keys{,2} location; originally from peter@;
ok djm@
20010528
- (tim) [conifgure.in] add setvbuf test needed for sftp-int.c
@ -5472,4 +5477,4 @@
- Wrote replacements for strlcpy and mkdtemp
- Released 1.0pre1
$Id: ChangeLog,v 1.1235 2001/06/05 20:01:39 mouring Exp $
$Id: ChangeLog,v 1.1236 2001/06/05 20:25:05 mouring Exp $

View File

@ -14,7 +14,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth-rsa.c,v 1.40 2001/04/06 21:00:07 markus Exp $");
RCSID("$OpenBSD: auth-rsa.c,v 1.41 2001/05/20 17:20:35 markus Exp $");
#include <openssl/rsa.h>
#include <openssl/md5.h>
@ -122,7 +122,7 @@ auth_rsa_challenge_dialog(RSA *pk)
int
auth_rsa(struct passwd *pw, BIGNUM *client_n)
{
char line[8192], file[MAXPATHLEN];
char line[8192], *file;
int authenticated;
u_int bits;
FILE *f;
@ -138,13 +138,14 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
temporarily_use_uid(pw);
/* The authorized keys. */
snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
_PATH_SSH_USER_PERMITTED_KEYS);
file = authorized_keys_file(pw);
debug("trying public RSA key 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. */
@ -154,43 +155,17 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
restore_uid();
packet_send_debug("Could not open %.900s for reading.", file);
packet_send_debug("If your home is on an NFS volume, it may need to be world-readable.");
xfree(file);
return 0;
}
if (options.strict_modes) {
int fail = 0;
char buf[1024];
/* Check open file in order to avoid open/stat races */
if (fstat(fileno(f), &st) < 0 ||
(st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0) {
snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
"bad ownership or modes for '%s'.", pw->pw_name, file);
fail = 1;
} else {
/* Check path to _PATH_SSH_USER_PERMITTED_KEYS */
int i;
static const char *check[] = {
"", _PATH_SSH_USER_DIR, NULL
};
for (i = 0; check[i]; i++) {
snprintf(line, sizeof line, "%.500s/%.100s", pw->pw_dir, check[i]);
if (stat(line, &st) < 0 ||
(st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0) {
snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
"bad ownership or modes for '%s'.", pw->pw_name, line);
fail = 1;
break;
}
}
}
if (fail) {
fclose(f);
log("%s", buf);
packet_send_debug("%s", buf);
restore_uid();
return 0;
}
if (options.strict_modes &&
secure_filename(f, file, pw->pw_uid, line, sizeof(line)) != 0) {
xfree(file);
fclose(f);
log("Authentication refused: %s", line);
packet_send_debug("Authentication refused: %s", line);
restore_uid();
return 0;
}
/* Flag indicating whether authentication has succeeded. */
authenticated = 0;
@ -285,6 +260,7 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
restore_uid();
/* Close the file. */
xfree(file);
fclose(f);
RSA_free(pk);

135
auth.c
View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth.c,v 1.21 2001/03/19 17:07:23 markus Exp $");
RCSID("$OpenBSD: auth.c,v 1.22 2001/05/20 17:20:35 markus Exp $");
#ifdef HAVE_LOGIN_H
#include <login.h>
@ -32,6 +32,8 @@ RCSID("$OpenBSD: auth.c,v 1.21 2001/03/19 17:07:23 markus Exp $");
#include <shadow.h>
#endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */
#include <libgen.h>
#include "xmalloc.h"
#include "match.h"
#include "groupaccess.h"
@ -40,6 +42,8 @@ RCSID("$OpenBSD: auth.c,v 1.21 2001/03/19 17:07:23 markus Exp $");
#include "auth.h"
#include "auth-options.h"
#include "canohost.h"
#include "buffer.h"
#include "bufaux.h"
/* import */
extern ServerOptions options;
@ -222,3 +226,132 @@ auth_root_allowed(char *method)
log("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr());
return 0;
}
/*
* Given a template and a passwd structure, build a filename
* by substituting % tokenised options. Currently, %% becomes '%',
* %h becomes the home directory and %u the username.
*
* This returns a buffer allocated by xmalloc.
*/
char *
expand_filename(const char *filename, struct passwd *pw)
{
Buffer buffer;
char *file;
const char *cp;
/*
* Build the filename string in the buffer by making the appropriate
* substitutions to the given file name.
*/
buffer_init(&buffer);
for (cp = filename; *cp; cp++) {
if (cp[0] == '%' && cp[1] == '%') {
buffer_append(&buffer, "%", 1);
cp++;
continue;
}
if (cp[0] == '%' && cp[1] == 'h') {
buffer_append(&buffer, pw->pw_dir, strlen(pw->pw_dir));
cp++;
continue;
}
if (cp[0] == '%' && cp[1] == 'u') {
buffer_append(&buffer, pw->pw_name,
strlen(pw->pw_name));
cp++;
continue;
}
buffer_append(&buffer, cp, 1);
}
buffer_append(&buffer, "\0", 1);
/*
* Ensure that filename starts anchored. If not, be backward
* compatible and prepend the '%h/'
*/
file = xmalloc(MAXPATHLEN);
cp = buffer_ptr(&buffer);
if (*cp != '/')
snprintf(file, MAXPATHLEN, "%s/%s", pw->pw_dir, cp);
else
strlcpy(file, cp, MAXPATHLEN);
buffer_free(&buffer);
return file;
}
char *
authorized_keys_file(struct passwd *pw)
{
return expand_filename(options.authorized_keys_file, pw);
}
char *
authorized_keys_file2(struct passwd *pw)
{
return expand_filename(options.authorized_keys_file2, pw);
}
/*
* Check a given file for security. This is defined as all components
* of the path to the file must either be owned by either the owner of
* of the file or root and no directories must be world writable.
*
* XXX Should any specific check be done for sym links ?
*
* Takes an open file descriptor, the file name, a uid and and
* error buffer plus max size as arguments.
*
* Returns 0 on success and -1 on failure
*/
int
secure_filename(FILE *f, const char *file, uid_t uid, char *err, size_t errlen)
{
char buf[MAXPATHLEN];
char *cp;
struct stat st;
if (realpath(file, buf) == NULL) {
snprintf(err, errlen, "realpath %s failed: %s", file,
strerror(errno));
return -1;
}
/* check the open file to avoid races */
if (fstat(fileno(f), &st) < 0 ||
(st.st_uid != 0 && st.st_uid != uid) ||
(st.st_mode & 022) != 0) {
snprintf(err, errlen, "bad ownership or modes for file %s",
buf);
return -1;
}
/* for each component of the canonical path, walking upwards */
for (;;) {
if ((cp = dirname(buf)) == NULL) {
snprintf(err, errlen, "dirname() failed");
return -1;
}
strlcpy(buf, cp, sizeof(buf));
debug3("secure_filename: checking '%s'", buf);
if (stat(buf, &st) < 0 ||
(st.st_uid != 0 && st.st_uid != uid) ||
(st.st_mode & 022) != 0) {
snprintf(err, errlen,
"bad ownership or modes for directory %s", buf);
return -1;
}
/*
* dirname should always complete with a "/" path,
* but we can be paranoid and check for "." too
*/
if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
break;
}
return 0;
}

12
auth.h
View File

@ -21,7 +21,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $OpenBSD: auth.h,v 1.16 2001/05/18 14:13:28 markus Exp $
* $OpenBSD: auth.h,v 1.17 2001/05/20 17:20:35 markus Exp $
*/
#ifndef AUTH_H
#define AUTH_H
@ -159,6 +159,16 @@ int verify_response(Authctxt *authctxt, const char *response);
struct passwd * auth_get_user(void);
/* expand a filename - return buffer is allocated by xmalloc */
char *expand_filename(const char *template, struct passwd *pw);
char *authorized_keys_file(struct passwd *pw);
char *authorized_keys_file2(struct passwd *pw);
/* check a file and the path to it */
int
secure_filename(FILE *f, const char *file, uid_t u, char *err, size_t errlen);
#define AUTH_FAIL_MAX 6
#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"

58
auth2.c
View File

@ -23,7 +23,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: auth2.c,v 1.57 2001/05/18 14:13:28 markus Exp $");
RCSID("$OpenBSD: auth2.c,v 1.58 2001/05/20 17:20:35 markus Exp $");
#include <openssl/evp.h>
@ -666,7 +666,7 @@ authmethod_lookup(const char *name)
int
user_key_allowed(struct passwd *pw, Key *key)
{
char line[8192], file[MAXPATHLEN];
char line[8192], *file;
int found_key = 0;
FILE *f;
u_long linenum = 0;
@ -680,13 +680,14 @@ user_key_allowed(struct passwd *pw, Key *key)
temporarily_use_uid(pw);
/* The authorized keys. */
snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
_PATH_SSH_USER_PERMITTED_KEYS2);
file = authorized_keys_file2(pw);
debug("trying public key 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. */
@ -694,48 +695,18 @@ user_key_allowed(struct passwd *pw, Key *key)
if (!f) {
/* Restore the privileged uid. */
restore_uid();
xfree(file);
return 0;
}
if (options.strict_modes) {
int fail = 0;
char buf[1024];
/* Check open file in order to avoid open/stat races */
if (fstat(fileno(f), &st) < 0 ||
(st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0) {
snprintf(buf, sizeof buf,
"%s authentication refused for %.100s: "
"bad ownership or modes for '%s'.",
key_type(key), pw->pw_name, file);
fail = 1;
} else {
/* Check path to _PATH_SSH_USER_PERMITTED_KEYS */
int i;
static const char *check[] = {
"", _PATH_SSH_USER_DIR, NULL
};
for (i = 0; check[i]; i++) {
snprintf(line, sizeof line, "%.500s/%.100s",
pw->pw_dir, check[i]);
if (stat(line, &st) < 0 ||
(st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0) {
snprintf(buf, sizeof buf,
"%s authentication refused for %.100s: "
"bad ownership or modes for '%s'.",
key_type(key), pw->pw_name, line);
fail = 1;
break;
}
}
}
if (fail) {
fclose(f);
log("%s", buf);
restore_uid();
return 0;
}
if (options.strict_modes &&
secure_filename(f, file, pw->pw_uid, line, sizeof(line)) != 0) {
xfree(file);
fclose(f);
log("Authentication refused: %s", line);
restore_uid();
return 0;
}
found_key = 0;
found = key_new(key->type);
@ -778,6 +749,7 @@ user_key_allowed(struct passwd *pw, Key *key)
}
restore_uid();
fclose(f);
xfree(file);
key_free(found);
if (!found_key)
debug2("key not found");

View File

@ -10,7 +10,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: servconf.c,v 1.81 2001/05/19 19:43:57 stevesk Exp $");
RCSID("$OpenBSD: servconf.c,v 1.82 2001/05/20 17:20:35 markus Exp $");
#ifdef KRB4
#include <krb.h>
@ -101,6 +101,8 @@ initialize_server_options(ServerOptions *options)
options->reverse_mapping_check = -1;
options->client_alive_interval = -1;
options->client_alive_count_max = -1;
options->authorized_keys_file = NULL;
options->authorized_keys_file2 = NULL;
options->pam_authentication_via_kbd_int = -1;
}
@ -208,6 +210,10 @@ fill_default_server_options(ServerOptions *options)
options->client_alive_interval = 0;
if (options->client_alive_count_max == -1)
options->client_alive_count_max = 3;
if (options->authorized_keys_file == NULL)
options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
if (options->authorized_keys_file2 == NULL)
options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2;
if (options->pam_authentication_via_kbd_int == -1)
options->pam_authentication_via_kbd_int = 0;
}
@ -235,7 +241,8 @@ typedef enum {
sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
sBanner, sReverseMappingCheck, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
sClientAliveCountMax, sPAMAuthenticationViaKbdInt
sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
sPAMAuthenticationViaKbdInt
} ServerOpCodes;
/* Textual representation of the tokens. */
@ -301,6 +308,8 @@ static struct {
{ "reversemappingcheck", sReverseMappingCheck },
{ "clientaliveinterval", sClientAliveInterval },
{ "clientalivecountmax", sClientAliveCountMax },
{ "authorizedkeysfile", sAuthorizedKeysFile },
{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
{ "PAMAuthenticationViaKbdInt", sPAMAuthenticationViaKbdInt },
{ NULL, 0 }
};
@ -802,6 +811,18 @@ parse_flag:
case sBanner:
charptr = &options->banner;
goto parse_filename;
/*
* These options can contain %X options expanded at
* connect time, so that you can specify paths like:
*
* AuthorizedKeysFile /etc/ssh_keys/%u
*/
case sAuthorizedKeysFile:
case sAuthorizedKeysFile2:
charptr = (opcode == sAuthorizedKeysFile ) ?
&options->authorized_keys_file :
&options->authorized_keys_file2;
goto parse_filename;
case sClientAliveInterval:
intptr = &options->client_alive_interval;

View File

@ -11,7 +11,7 @@
* called by a name other than "ssh" or "Secure Shell".
*/
/* RCSID("$OpenBSD: servconf.h,v 1.42 2001/05/18 14:13:29 markus Exp $"); */
/* RCSID("$OpenBSD: servconf.h,v 1.43 2001/05/20 17:20:35 markus Exp $"); */
#ifndef SERVCONF_H
#define SERVCONF_H
@ -124,6 +124,8 @@ typedef struct {
* for this many intervals, above
* diconnect the session
*/
char *authorized_keys_file; /* File containing public RSA keys */
char *authorized_keys_file2; /* File containing public SSH2 keys */
int pam_authentication_via_kbd_int;
} ServerOptions;
/*

41
sshd.8
View File

@ -34,7 +34,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: sshd.8,v 1.124 2001/05/19 19:43:57 stevesk Exp $
.\" $OpenBSD: sshd.8,v 1.125 2001/05/20 17:20:35 markus Exp $
.Dd September 25, 1999
.Dt SSHD 8
.Os
@ -331,6 +331,34 @@ wildcards in the patterns.
Only user names are valid; a numerical user ID isn't recognized.
By default login is allowed regardless of the user name.
.Pp
.It Cm AuthorizedKeysFile
Specifies the file that contains the public RSA keys that can be used
for RSA authentication in protocol version 1.
.Cm AuthorizedKeysFile
may contain tokens of the form %T which are substituted during connection
set-up. The following tokens are defined; %% is replaces 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 AuthorizedKeysFile
is taken to be an absolute path or one realtive to the user's home
directory.
The default is
.Dq .ssh/authorized_keys
.It Cm AuthorizedKeysFile2
Specifies the file that contains the public keys that can be used
for public key authentication in protocol version 2.
.Cm AuthorizedKeysFile2
may contain tokens of the form %T which are substituted during connection
set-up. The following tokens are defined; %% is replaces 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 AuthorizedKeysFile2
is taken to be an absolute path or one realtive to the user's home
directory.
The default is
.Dq .ssh/authorized_keys2
.It Cm Banner
In some jurisdictions, sending a warning message before authentication
may be relevant for getting legal protection.
@ -883,15 +911,18 @@ authentication protocol and cookie in standard input.
Runs user's shell or command.
.El
.Sh AUTHORIZED_KEYS FILE FORMAT
The
.Pa $HOME/.ssh/authorized_keys
file lists the RSA keys that are
is the default file that lists the RSA keys that are
permitted for RSA authentication in protocol version 1.
Similarly, the
.Cm AuthorizedKeysFile
may be used to specify an alternative file.
Similarly,
.Pa $HOME/.ssh/authorized_keys2
file lists the DSA and RSA keys that are
is the default file that lists the DSA and RSA keys that are
permitted for public key authentication (PubkeyAuthentication)
in protocol version 2.
.Cm AuthorizedKeysFile2
may be used to specify an alternative file.
.Pp
Each line of the file contains one
key (empty lines and lines starting with a

View File

@ -1,4 +1,4 @@
# $OpenBSD: sshd_config,v 1.38 2001/04/15 21:41:29 deraadt Exp $
# $OpenBSD: sshd_config,v 1.39 2001/05/20 17:20:36 markus Exp $
# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
@ -41,6 +41,9 @@ RhostsRSAAuthentication no
HostbasedAuthentication no
#
RSAAuthentication yes
PubkeyAuthentication yes
#AuthorizedKeysFile %h/.ssh/authorized_keys
#AuthorizedKeysFile2 %h/.ssh/authorized_keys2
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication yes