- (djm) OpenBSD CVS changes:

- markus@cvs.openbsd.org  2000/07/22 03:14:37
     [servconf.c servconf.h sshd.8 sshd.c sshd_config]
     random early drop; ok theo, niels
   - deraadt@cvs.openbsd.org 2000/07/26 11:46:51
     [ssh.1]
     typo
   - deraadt@cvs.openbsd.org 2000/08/01 11:46:11
     [sshd.8]
     many fixes from pepper@mail.reppep.com
   - provos@cvs.openbsd.org  2000/08/01 13:01:42
     [Makefile.in util.c aux.c]
     rename aux.c to util.c to help with cygwin port
   - deraadt@cvs.openbsd.org 2000/08/02 00:23:31
     [authfd.c]
     correct sun_len; Alexander@Leidinger.net
   - provos@cvs.openbsd.org  2000/08/02 10:27:17
     [readconf.c sshd.8]
     disable kerberos authentication by default
   - provos@cvs.openbsd.org  2000/08/02 11:27:05
     [sshd.8 readconf.c auth-krb4.c]
     disallow kerberos authentication if we can't verify the TGT; from
     dugsong@
     kerberos authentication is on by default only if you have a srvtab.
   - markus@cvs.openbsd.org  2000/08/04 14:30:07
     [auth.c]
     unused
   - markus@cvs.openbsd.org  2000/08/04 14:30:35
     [sshd_config]
     MaxStartups
   - markus@cvs.openbsd.org  2000/08/15 13:20:46
     [authfd.c]
     cleanup; ok niels@
   - markus@cvs.openbsd.org  2000/08/17 14:05:10
     [session.c]
     cleanup login(1)-like jobs, no duplicate utmp entries
   - markus@cvs.openbsd.org  2000/08/17 14:06:34
     [session.c sshd.8 sshd.c]
      sshd -u len, similar to telnetd
This commit is contained in:
Damien Miller 2000-08-18 13:59:06 +10:00
parent 11fa2cc383
commit 942da039d2
16 changed files with 403 additions and 340 deletions

View File

@ -1,3 +1,44 @@
20000818
- (djm) OpenBSD CVS changes:
- markus@cvs.openbsd.org 2000/07/22 03:14:37
[servconf.c servconf.h sshd.8 sshd.c sshd_config]
random early drop; ok theo, niels
- deraadt@cvs.openbsd.org 2000/07/26 11:46:51
[ssh.1]
typo
- deraadt@cvs.openbsd.org 2000/08/01 11:46:11
[sshd.8]
many fixes from pepper@mail.reppep.com
- provos@cvs.openbsd.org 2000/08/01 13:01:42
[Makefile.in util.c aux.c]
rename aux.c to util.c to help with cygwin port
- deraadt@cvs.openbsd.org 2000/08/02 00:23:31
[authfd.c]
correct sun_len; Alexander@Leidinger.net
- provos@cvs.openbsd.org 2000/08/02 10:27:17
[readconf.c sshd.8]
disable kerberos authentication by default
- provos@cvs.openbsd.org 2000/08/02 11:27:05
[sshd.8 readconf.c auth-krb4.c]
disallow kerberos authentication if we can't verify the TGT; from
dugsong@
kerberos authentication is on by default only if you have a srvtab.
- markus@cvs.openbsd.org 2000/08/04 14:30:07
[auth.c]
unused
- markus@cvs.openbsd.org 2000/08/04 14:30:35
[sshd_config]
MaxStartups
- markus@cvs.openbsd.org 2000/08/15 13:20:46
[authfd.c]
cleanup; ok niels@
- markus@cvs.openbsd.org 2000/08/17 14:05:10
[session.c]
cleanup login(1)-like jobs, no duplicate utmp entries
- markus@cvs.openbsd.org 2000/08/17 14:06:34
[session.c sshd.8 sshd.c]
sshd -u len, similar to telnetd
20000816 20000816
- (djm) Replacement for inet_ntoa for Irix (which breaks on gcc) - (djm) Replacement for inet_ntoa for Irix (which breaks on gcc)
- (djm) Fix strerror replacement for old SunOS. Based on patch from - (djm) Fix strerror replacement for old SunOS. Based on patch from

View File

@ -34,7 +34,7 @@ INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS) TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS)
LIBSSH_OBJS=atomicio.o authfd.o authfile.o aux.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o dsa.o fingerprint.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o dsa.o fingerprint.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o util.o uuencode.o xmalloc.o
LIBOPENBSD_COMPAT_OBJS=bsd-arc4random.o bsd-base64.o bsd-bindresvport.o bsd-daemon.o bsd-inet_aton.o bsd-inet_ntoa.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-sigaction.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bsd-strsep.o fake-getaddrinfo.o fake-getnameinfo.o next-posix.o LIBOPENBSD_COMPAT_OBJS=bsd-arc4random.o bsd-base64.o bsd-bindresvport.o bsd-daemon.o bsd-inet_aton.o bsd-inet_ntoa.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-sigaction.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bsd-strsep.o fake-getaddrinfo.o fake-getnameinfo.o next-posix.o

View File

@ -6,6 +6,9 @@
@TOP@ @TOP@
/* Define if your system's struct sockaddr_un has a sun_len member */
#undef HAVE_SUN_LEN_IN_SOCKADDR_UN
/* Define if you system's inet_ntoa is busted (e.g. Irix gcc issue) */ /* Define if you system's inet_ntoa is busted (e.g. Irix gcc issue) */
#undef BROKEN_INET_NTOA #undef BROKEN_INET_NTOA

View File

@ -9,7 +9,7 @@
#include "ssh.h" #include "ssh.h"
#include "servconf.h" #include "servconf.h"
RCSID("$OpenBSD: auth-krb4.c,v 1.15 2000/06/22 23:54:59 djm Exp $"); RCSID("$OpenBSD: auth-krb4.c,v 1.16 2000/08/02 17:27:04 provos Exp $");
#ifdef KRB4 #ifdef KRB4
char *ticket = NULL; char *ticket = NULL;
@ -82,11 +82,12 @@ auth_krb4_password(struct passwd * pw, const char *password)
if (r == RD_AP_UNDEC) { if (r == RD_AP_UNDEC) {
/* /*
* Probably didn't have a srvtab on * Probably didn't have a srvtab on
* localhost. Allow login. * localhost. Disallow login.
*/ */
log("Kerberos V4 TGT for %s unverifiable, " log("Kerberos V4 TGT for %s unverifiable, "
"no srvtab installed? krb_rd_req: %s", "no srvtab installed? krb_rd_req: %s",
pw->pw_name, krb_err_txt[r]); pw->pw_name, krb_err_txt[r]);
goto kerberos_auth_failure;
} else if (r != KSUCCESS) { } else if (r != KSUCCESS) {
log("Kerberos V4 %s ticket unverifiable: %s", log("Kerberos V4 %s ticket unverifiable: %s",
KRB4_SERVICE_NAME, krb_err_txt[r]); KRB4_SERVICE_NAME, krb_err_txt[r]);
@ -94,12 +95,13 @@ auth_krb4_password(struct passwd * pw, const char *password)
} }
} else if (r == KDC_PR_UNKNOWN) { } else if (r == KDC_PR_UNKNOWN) {
/* /*
* Allow login if no rcmd service exists, but * Disallow login if no rcmd service exists, and
* log the error. * log the error.
*/ */
log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s " log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s "
"not registered, or srvtab is wrong?", pw->pw_name, "not registered, or srvtab is wrong?", pw->pw_name,
krb_err_txt[r], KRB4_SERVICE_NAME, phost); krb_err_txt[r], KRB4_SERVICE_NAME, phost);
goto kerberos_auth_failure;
} else { } else {
/* /*
* TGT is bad, forget it. Possibly spoofed! * TGT is bad, forget it. Possibly spoofed!

4
auth.c
View File

@ -5,7 +5,7 @@
*/ */
#include "includes.h" #include "includes.h"
RCSID("$OpenBSD: auth.c,v 1.7 2000/05/17 21:37:24 deraadt Exp $"); RCSID("$OpenBSD: auth.c,v 1.8 2000/08/04 20:30:07 markus Exp $");
#include "xmalloc.h" #include "xmalloc.h"
#include "rsa.h" #include "rsa.h"
@ -30,8 +30,6 @@ RCSID("$OpenBSD: auth.c,v 1.7 2000/05/17 21:37:24 deraadt Exp $");
#include "ssh2.h" #include "ssh2.h"
#include "auth.h" #include "auth.h"
#include "session.h" #include "session.h"
#include "dispatch.h"
/* import */ /* import */
extern ServerOptions options; extern ServerOptions options;

331
authfd.c
View File

@ -14,7 +14,7 @@
*/ */
#include "includes.h" #include "includes.h"
RCSID("$OpenBSD: authfd.c,v 1.22 2000/07/16 08:27:20 markus Exp $"); RCSID("$OpenBSD: authfd.c,v 1.24 2000/08/15 19:20:46 markus Exp $");
#include "ssh.h" #include "ssh.h"
#include "rsa.h" #include "rsa.h"
@ -31,7 +31,7 @@ RCSID("$OpenBSD: authfd.c,v 1.22 2000/07/16 08:27:20 markus Exp $");
#include "kex.h" #include "kex.h"
/* helper */ /* helper */
int ssh_agent_get_reply(AuthenticationConnection *auth); int decode_reply(int type);
/* Returns the number of the authentication fd, or -1 if there is none. */ /* Returns the number of the authentication fd, or -1 if there is none. */
@ -39,7 +39,7 @@ int
ssh_get_authentication_socket() ssh_get_authentication_socket()
{ {
const char *authsocket; const char *authsocket;
int sock; int sock, len;
struct sockaddr_un sunaddr; struct sockaddr_un sunaddr;
authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
@ -48,6 +48,11 @@ ssh_get_authentication_socket()
sunaddr.sun_family = AF_UNIX; sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
#ifdef HAVE_SUN_LEN_IN_SOCKADDR_UN
sunaddr.sun_len = len = SUN_LEN(&sunaddr)+1;
#else /* HAVE_SUN_LEN_IN_SOCKADDR_UN */
len = SUN_LEN(&sunaddr)+1;
#endif /* HAVE_SUN_LEN_IN_SOCKADDR_UN */
sock = socket(AF_UNIX, SOCK_STREAM, 0); sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) if (sock < 0)
@ -58,13 +63,67 @@ ssh_get_authentication_socket()
close(sock); close(sock);
return -1; return -1;
} }
if (connect(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) { if (connect(sock, (struct sockaddr *) & sunaddr, len) < 0) {
close(sock); close(sock);
return -1; return -1;
} }
return sock; return sock;
} }
int
ssh_request_reply(AuthenticationConnection *auth,
Buffer *request, Buffer *reply)
{
int l, len;
char buf[1024];
/* Get the length of the message, and format it in the buffer. */
len = buffer_len(request);
PUT_32BIT(buf, len);
/* Send the length and then the packet to the agent. */
if (atomicio(write, auth->fd, buf, 4) != 4 ||
atomicio(write, auth->fd, buffer_ptr(request),
buffer_len(request)) != buffer_len(request)) {
error("Error writing to authentication socket.");
return 0;
}
/*
* Wait for response from the agent. First read the length of the
* response packet.
*/
len = 4;
while (len > 0) {
l = read(auth->fd, buf + 4 - len, len);
if (l <= 0) {
error("Error reading response length from authentication socket.");
return 0;
}
len -= l;
}
/* Extract the length, and check it for sanity. */
len = GET_32BIT(buf);
if (len > 256 * 1024)
fatal("Authentication response too long: %d", len);
/* Read the rest of the response in to the buffer. */
buffer_clear(reply);
while (len > 0) {
l = len;
if (l > sizeof(buf))
l = sizeof(buf);
l = read(auth->fd, buf, l);
if (l <= 0) {
error("Error reading response from authentication socket.");
return 0;
}
buffer_append(reply, (char *) buf, l);
len -= l;
}
return 1;
}
/* /*
* Closes the agent socket if it should be closed (depends on how it was * Closes the agent socket if it should be closed (depends on how it was
* obtained). The argument must have been returned by * obtained). The argument must have been returned by
@ -133,62 +192,35 @@ ssh_close_authentication_connection(AuthenticationConnection *ac)
int int
ssh_get_first_identity(AuthenticationConnection *auth, ssh_get_first_identity(AuthenticationConnection *auth,
BIGNUM *e, BIGNUM *n, char **comment) BIGNUM *e, BIGNUM *n, char **comment)
{ {
unsigned char msg[8192]; Buffer request;
int len, l; int type;
/* /*
* Send a message to the agent requesting for a list of the * Send a message to the agent requesting for a list of the
* identities it can represent. * identities it can represent.
*/ */
PUT_32BIT(msg, 1); buffer_init(&request);
msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES; buffer_put_char(&request, SSH_AGENTC_REQUEST_RSA_IDENTITIES);
if (atomicio(write, auth->fd, msg, 5) != 5) {
error("write auth->fd: %.100s", strerror(errno)); buffer_clear(&auth->identities);
if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
buffer_free(&request);
return 0; return 0;
} }
/* Read the length of the response. XXX implement timeouts here. */ buffer_free(&request);
len = 4;
while (len > 0) {
l = read(auth->fd, msg + 4 - len, len);
if (l <= 0) {
error("read auth->fd: %.100s", strerror(errno));
return 0;
}
len -= l;
}
/*
* Extract the length, and check it for sanity. (We cannot trust
* authentication agents).
*/
len = GET_32BIT(msg);
if (len < 1 || len > 256 * 1024)
fatal("Authentication reply message too long: %d\n", len);
/* Read the packet itself. */
buffer_clear(&auth->identities);
while (len > 0) {
l = len;
if (l > sizeof(msg))
l = sizeof(msg);
l = read(auth->fd, msg, l);
if (l <= 0)
fatal("Incomplete authentication reply.");
buffer_append(&auth->identities, (char *) msg, l);
len -= l;
}
/* Get message type, and verify that we got a proper answer. */ /* Get message type, and verify that we got a proper answer. */
buffer_get(&auth->identities, (char *) msg, 1); type = buffer_get_char(&auth->identities);
if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER) if (type != SSH_AGENT_RSA_IDENTITIES_ANSWER)
fatal("Bad authentication reply message type: %d", msg[0]); fatal("Bad authentication reply message type: %d", type);
/* Get the number of entries in the response and check it for sanity. */ /* Get the number of entries in the response and check it for sanity. */
auth->howmany = buffer_get_int(&auth->identities); auth->howmany = buffer_get_int(&auth->identities);
if (auth->howmany > 1024) if (auth->howmany > 1024)
fatal("Too many identities in authentication reply: %d\n", auth->howmany); fatal("Too many identities in authentication reply: %d\n",
auth->howmany);
/* Return the first entry (if any). */ /* Return the first entry (if any). */
return ssh_get_next_identity(auth, e, n, comment); return ssh_get_next_identity(auth, e, n, comment);
@ -203,7 +235,7 @@ ssh_get_first_identity(AuthenticationConnection *auth,
int int
ssh_get_next_identity(AuthenticationConnection *auth, ssh_get_next_identity(AuthenticationConnection *auth,
BIGNUM *e, BIGNUM *n, char **comment) BIGNUM *e, BIGNUM *n, char **comment)
{ {
unsigned int bits; unsigned int bits;
@ -240,23 +272,22 @@ ssh_get_next_identity(AuthenticationConnection *auth,
int int
ssh_decrypt_challenge(AuthenticationConnection *auth, ssh_decrypt_challenge(AuthenticationConnection *auth,
BIGNUM* e, BIGNUM *n, BIGNUM *challenge, BIGNUM* e, BIGNUM *n, BIGNUM *challenge,
unsigned char session_id[16], unsigned char session_id[16],
unsigned int response_type, unsigned int response_type,
unsigned char response[16]) unsigned char response[16])
{ {
Buffer buffer; Buffer buffer;
unsigned char buf[8192]; int success = 0;
int len, l, i; int i;
int type;
/* Response type 0 is no longer supported. */
if (response_type == 0) if (response_type == 0)
fatal("Compatibility with ssh protocol version 1.0 no longer supported."); fatal("Compatibility with ssh protocol version "
"1.0 no longer supported.");
/* Format a message to the agent. */
buf[0] = SSH_AGENTC_RSA_CHALLENGE;
buffer_init(&buffer); buffer_init(&buffer);
buffer_append(&buffer, (char *) buf, 1); buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE);
buffer_put_int(&buffer, BN_num_bits(n)); buffer_put_int(&buffer, BN_num_bits(n));
buffer_put_bignum(&buffer, e); buffer_put_bignum(&buffer, e);
buffer_put_bignum(&buffer, n); buffer_put_bignum(&buffer, n);
@ -264,77 +295,27 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
buffer_append(&buffer, (char *) session_id, 16); buffer_append(&buffer, (char *) session_id, 16);
buffer_put_int(&buffer, response_type); buffer_put_int(&buffer, response_type);
/* Get the length of the message, and format it in the buffer. */ if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
len = buffer_len(&buffer);
PUT_32BIT(buf, len);
/* Send the length and then the packet to the agent. */
if (atomicio(write, auth->fd, buf, 4) != 4 ||
atomicio(write, auth->fd, buffer_ptr(&buffer),
buffer_len(&buffer)) != buffer_len(&buffer)) {
error("Error writing to authentication socket.");
error_cleanup:
buffer_free(&buffer); buffer_free(&buffer);
return 0; return 0;
} }
/* type = buffer_get_char(&buffer);
* Wait for response from the agent. First read the length of the
* response packet.
*/
len = 4;
while (len > 0) {
l = read(auth->fd, buf + 4 - len, len);
if (l <= 0) {
error("Error reading response length from authentication socket.");
goto error_cleanup;
}
len -= l;
}
/* Extract the length, and check it for sanity. */ if (type == SSH_AGENT_FAILURE) {
len = GET_32BIT(buf);
if (len > 256 * 1024)
fatal("Authentication response too long: %d", len);
/* Read the rest of the response in tothe buffer. */
buffer_clear(&buffer);
while (len > 0) {
l = len;
if (l > sizeof(buf))
l = sizeof(buf);
l = read(auth->fd, buf, l);
if (l <= 0) {
error("Error reading response from authentication socket.");
goto error_cleanup;
}
buffer_append(&buffer, (char *) buf, l);
len -= l;
}
/* Get the type of the packet. */
buffer_get(&buffer, (char *) buf, 1);
/* Check for agent failure message. */
if (buf[0] == SSH_AGENT_FAILURE) {
log("Agent admitted failure to authenticate using the key."); log("Agent admitted failure to authenticate using the key.");
goto error_cleanup; } else if (type != SSH_AGENT_RSA_RESPONSE) {
fatal("Bad authentication response: %d", type);
} else {
success = 1;
/*
* Get the response from the packet. This will abort with a
* fatal error if the packet is corrupt.
*/
for (i = 0; i < 16; i++)
response[i] = buffer_get_char(&buffer);
} }
/* Now it must be an authentication response packet. */
if (buf[0] != SSH_AGENT_RSA_RESPONSE)
fatal("Bad authentication response: %d", buf[0]);
/*
* Get the response from the packet. This will abort with a fatal
* error if the packet is corrupt.
*/
for (i = 0; i < 16; i++)
response[i] = buffer_get_char(&buffer);
/* The buffer containing the packet is no longer needed. */
buffer_free(&buffer); buffer_free(&buffer);
return success;
/* Correct answer. */
return 1;
} }
/* Encode key for a message to the agent. */ /* Encode key for a message to the agent. */
@ -378,8 +359,7 @@ int
ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment) ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
{ {
Buffer buffer; Buffer buffer;
unsigned char buf[8192]; int type;
int len;
buffer_init(&buffer); buffer_init(&buffer);
@ -395,21 +375,13 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
return 0; return 0;
break; break;
} }
if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
/* Get the length of the message, and format it in the buffer. */
len = buffer_len(&buffer);
PUT_32BIT(buf, len);
/* Send the length and then the packet to the agent. */
if (atomicio(write, auth->fd, buf, 4) != 4 ||
atomicio(write, auth->fd, buffer_ptr(&buffer),
buffer_len(&buffer)) != buffer_len(&buffer)) {
error("Error writing to authentication socket.");
buffer_free(&buffer); buffer_free(&buffer);
return 0; return 0;
} }
type = buffer_get_char(&buffer);
buffer_free(&buffer); buffer_free(&buffer);
return ssh_agent_get_reply(auth); return decode_reply(type);
} }
/* /*
@ -421,30 +393,21 @@ int
ssh_remove_identity(AuthenticationConnection *auth, RSA *key) ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
{ {
Buffer buffer; Buffer buffer;
unsigned char buf[5]; int type;
int len;
/* Format a message to the agent. */
buffer_init(&buffer); buffer_init(&buffer);
buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY); buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
buffer_put_int(&buffer, BN_num_bits(key->n)); buffer_put_int(&buffer, BN_num_bits(key->n));
buffer_put_bignum(&buffer, key->e); buffer_put_bignum(&buffer, key->e);
buffer_put_bignum(&buffer, key->n); buffer_put_bignum(&buffer, key->n);
/* Get the length of the message, and format it in the buffer. */ if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
len = buffer_len(&buffer);
PUT_32BIT(buf, len);
/* Send the length and then the packet to the agent. */
if (atomicio(write, auth->fd, buf, 4) != 4 ||
atomicio(write, auth->fd, buffer_ptr(&buffer),
buffer_len(&buffer)) != buffer_len(&buffer)) {
error("Error writing to authentication socket.");
buffer_free(&buffer); buffer_free(&buffer);
return 0; return 0;
} }
type = buffer_get_char(&buffer);
buffer_free(&buffer); buffer_free(&buffer);
return ssh_agent_get_reply(auth); return decode_reply(type);
} }
/* /*
@ -455,73 +418,27 @@ ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
int int
ssh_remove_all_identities(AuthenticationConnection *auth) ssh_remove_all_identities(AuthenticationConnection *auth)
{ {
unsigned char buf[5]; Buffer buffer;
int type;
/* Get the length of the message, and format it in the buffer. */ buffer_init(&buffer);
PUT_32BIT(buf, 1); buffer_put_char(&buffer, SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES);
buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
/* Send the length and then the packet to the agent. */ if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
if (atomicio(write, auth->fd, buf, 5) != 5) { buffer_free(&buffer);
error("Error writing to authentication socket.");
return 0; return 0;
} }
return ssh_agent_get_reply(auth);
}
/*
* Read for reply from agent. returns 1 for success, 0 on error
*/
int
ssh_agent_get_reply(AuthenticationConnection *auth)
{
Buffer buffer;
unsigned char buf[8192];
int len, l, type;
/*
* Wait for response from the agent. First read the length of the
* response packet.
*/
len = 4;
while (len > 0) {
l = read(auth->fd, buf + 4 - len, len);
if (l <= 0) {
error("Error reading response length from authentication socket.");
buffer_free(&buffer);
return 0;
}
len -= l;
}
/* Extract the length, and check it for sanity. */
len = GET_32BIT(buf);
if (len > 256 * 1024)
fatal("Response from agent too long: %d", len);
/* Read the rest of the response in to the buffer. */
buffer_init(&buffer);
while (len > 0) {
l = len;
if (l > sizeof(buf))
l = sizeof(buf);
l = read(auth->fd, buf, l);
if (l <= 0) {
error("Error reading response from authentication socket.");
buffer_free(&buffer);
return 0;
}
buffer_append(&buffer, (char *) buf, l);
len -= l;
}
/* Get the type of the packet. */
type = buffer_get_char(&buffer); type = buffer_get_char(&buffer);
buffer_free(&buffer); buffer_free(&buffer);
return decode_reply(type);
}
int
decode_reply(int type)
{
switch (type) { switch (type) {
case SSH_AGENT_FAILURE: case SSH_AGENT_FAILURE:
log("SSH_AGENT_FAILURE"); log("SSH_AGENT_FAILURE");
return 0; return 0;
case SSH_AGENT_SUCCESS: case SSH_AGENT_SUCCESS:
return 1; return 1;

View File

@ -52,6 +52,7 @@ static char rcsid[] = "$OpenBSD: mktemp.c,v 1.13 1998/06/30 23:03:13 deraadt Exp
#include <unistd.h> #include <unistd.h>
#include "bsd-misc.h" #include "bsd-misc.h"
#include "bsd-arc4random.h"
static int _gettemp(char *, int *, int, int); static int _gettemp(char *, int *, int, int);

View File

@ -686,6 +686,22 @@ OSSH_CHECK_HEADER_FOR_FIELD(ut_time, utmp.h, HAVE_TIME_IN_UTMP)
OSSH_CHECK_HEADER_FOR_FIELD(ut_time, utmpx.h, HAVE_TIME_IN_UTMPX) OSSH_CHECK_HEADER_FOR_FIELD(ut_time, utmpx.h, HAVE_TIME_IN_UTMPX)
OSSH_CHECK_HEADER_FOR_FIELD(ut_tv, utmpx.h, HAVE_TV_IN_UTMPX) OSSH_CHECK_HEADER_FOR_FIELD(ut_tv, utmpx.h, HAVE_TV_IN_UTMPX)
AC_CACHE_CHECK([for sun_len field in struct sockaddr_un],
ac_cv_have_sun_len_in_struct_sockaddr_un, [
AC_TRY_COMPILE(
[
#include <sys/types.h>
#include <sys/socket.h>
],
[ struct sockaddr_un s; s.sun_len = 1; ],
[ ac_cv_have_sun_len_in_struct_sockaddr_un="yes" ],
[ ac_cv_have_sun_len_in_struct_sockaddr_un="no" ],
)
])
if test "x$ac_cv_have_sun_len_in_struct_sockaddr_un" = "xyes" ; then
AC_DEFINE(HAVE_SUN_LEN_IN_SOCKADDR_UN)
fi
AC_CACHE_CHECK([for ss_family field in struct sockaddr_storage], AC_CACHE_CHECK([for ss_family field in struct sockaddr_storage],
ac_cv_have_ss_family_in_struct_ss, [ ac_cv_have_ss_family_in_struct_ss, [
AC_TRY_COMPILE( AC_TRY_COMPILE(

View File

@ -14,7 +14,7 @@
*/ */
#include "includes.h" #include "includes.h"
RCSID("$OpenBSD: readconf.c,v 1.43 2000/07/14 22:59:46 markus Exp $"); RCSID("$OpenBSD: readconf.c,v 1.45 2000/08/02 17:27:04 provos Exp $");
#include "ssh.h" #include "ssh.h"
#include "cipher.h" #include "cipher.h"

View File

@ -12,7 +12,7 @@
*/ */
#include "includes.h" #include "includes.h"
RCSID("$OpenBSD: servconf.c,v 1.49 2000/07/14 22:59:46 markus Exp $"); RCSID("$OpenBSD: servconf.c,v 1.50 2000/07/22 09:14:36 markus Exp $");
#include "ssh.h" #include "ssh.h"
#include "servconf.h" #include "servconf.h"
@ -76,6 +76,8 @@ initialize_server_options(ServerOptions *options)
options->protocol = SSH_PROTO_UNKNOWN; options->protocol = SSH_PROTO_UNKNOWN;
options->gateway_ports = -1; options->gateway_ports = -1;
options->num_subsystems = 0; options->num_subsystems = 0;
options->max_startups_begin = -1;
options->max_startups_rate = -1;
options->max_startups = -1; options->max_startups = -1;
} }
@ -162,6 +164,10 @@ fill_default_server_options(ServerOptions *options)
options->gateway_ports = 0; options->gateway_ports = 0;
if (options->max_startups == -1) if (options->max_startups == -1)
options->max_startups = 10; options->max_startups = 10;
if (options->max_startups_rate == -1)
options->max_startups_rate = 100; /* 100% */
if (options->max_startups_begin == -1)
options->max_startups_begin = options->max_startups;
} }
/* Keyword tokens. */ /* Keyword tokens. */
@ -644,6 +650,22 @@ parse_flag:
break; break;
case sMaxStartups: case sMaxStartups:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing MaxStartups spec.",
filename, linenum);
if (sscanf(arg, "%d:%d:%d",
&options->max_startups_begin,
&options->max_startups_rate,
&options->max_startups) == 3) {
if (options->max_startups_begin >
options->max_startups ||
options->max_startups_rate > 100 ||
options->max_startups_rate < 1)
fatal("%s line %d: Illegal MaxStartups spec.",
filename, linenum);
break;
}
intptr = &options->max_startups; intptr = &options->max_startups;
goto parse_int; goto parse_int;

View File

@ -13,7 +13,7 @@
* *
*/ */
/* RCSID("$OpenBSD: servconf.h,v 1.26 2000/06/26 21:59:18 markus Exp $"); */ /* RCSID("$OpenBSD: servconf.h,v 1.27 2000/07/22 09:14:36 markus Exp $"); */
#ifndef SERVCONF_H #ifndef SERVCONF_H
#define SERVCONF_H #define SERVCONF_H
@ -100,6 +100,8 @@ typedef struct {
char *subsystem_name[MAX_SUBSYSTEMS]; char *subsystem_name[MAX_SUBSYSTEMS];
char *subsystem_command[MAX_SUBSYSTEMS]; char *subsystem_command[MAX_SUBSYSTEMS];
int max_startups_begin;
int max_startups_rate;
int max_startups; int max_startups;
} ServerOptions; } ServerOptions;

194
session.c
View File

@ -8,7 +8,7 @@
*/ */
#include "includes.h" #include "includes.h"
RCSID("$OpenBSD: session.c,v 1.23 2000/07/11 08:11:33 deraadt Exp $"); RCSID("$OpenBSD: session.c,v 1.25 2000/08/17 20:06:34 markus Exp $");
#include "xmalloc.h" #include "xmalloc.h"
#include "ssh.h" #include "ssh.h"
@ -85,6 +85,7 @@ void session_pty_cleanup(Session *s);
void session_proctitle(Session *s); void session_proctitle(Session *s);
void do_exec_pty(Session *s, const char *command, struct passwd * pw); void do_exec_pty(Session *s, const char *command, struct passwd * pw);
void do_exec_no_pty(Session *s, const char *command, struct passwd * pw); void do_exec_no_pty(Session *s, const char *command, struct passwd * pw);
void do_login(Session *s);
void void
do_child(const char *command, struct passwd * pw, const char *term, do_child(const char *command, struct passwd * pw, const char *term,
@ -101,6 +102,7 @@ static const char *__progname = "sshd";
extern int log_stderr; extern int log_stderr;
extern int debug_flag; extern int debug_flag;
extern unsigned int utmp_len;
extern int startup_pipe; extern int startup_pipe;
@ -523,35 +525,14 @@ do_exec_no_pty(Session *s, const char *command, struct passwd * pw)
void void
do_exec_pty(Session *s, const char *command, struct passwd * pw) do_exec_pty(Session *s, const char *command, struct passwd * pw)
{ {
FILE *f;
char buf[100], *time_string;
char line[256];
const char *hostname;
int fdout, ptyfd, ttyfd, ptymaster; int fdout, ptyfd, ttyfd, ptymaster;
int quiet_login;
pid_t pid; pid_t pid;
socklen_t fromlen;
struct sockaddr_storage from;
struct stat st;
time_t last_login_time;
if (s == NULL) if (s == NULL)
fatal("do_exec_pty: no session"); fatal("do_exec_pty: no session");
ptyfd = s->ptyfd; ptyfd = s->ptyfd;
ttyfd = s->ttyfd; ttyfd = s->ttyfd;
/* Get remote host name. */
hostname = get_canonical_hostname();
/*
* Get the time when the user last logged in. Buf will be set to
* contain the hostname the last login was from.
*/
if (!options.use_login) {
last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
buf, sizeof(buf));
}
#ifdef USE_PAM #ifdef USE_PAM
do_pam_session(pw->pw_name, s->tty); do_pam_session(pw->pw_name, s->tty);
do_pam_setcred(); do_pam_setcred();
@ -559,10 +540,7 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw)
/* Fork the child. */ /* Fork the child. */
if ((pid = fork()) == 0) { if ((pid = fork()) == 0) {
pid = getpid(); /* Child. Reinitialize the log because the pid has changed. */
/* Child. Reinitialize the log because the pid has
changed. */
log_init(__progname, options.log_level, options.log_facility, log_stderr); log_init(__progname, options.log_level, options.log_facility, log_stderr);
/* Close the master side of the pseudo tty. */ /* Close the master side of the pseudo tty. */
@ -586,82 +564,10 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw)
/* Close the extra descriptor for the pseudo tty. */ /* Close the extra descriptor for the pseudo tty. */
close(ttyfd); close(ttyfd);
/* XXXX ? move to do_child() ??*/ /* record login, etc. similar to login(1) */
/* if (command == NULL && !options.use_login)
* Get IP address of client. This is needed because we want do_login(s);
* to record where the user logged in from. If the
* connection is not a socket, let the ip address be 0.0.0.0.
*/
memset(&from, 0, sizeof(from));
if (packet_connection_is_on_socket()) {
fromlen = sizeof(from);
if (getpeername(packet_get_connection_in(),
(struct sockaddr *) & from, &fromlen) < 0) {
debug("getpeername: %.100s", strerror(errno));
fatal_cleanup();
}
}
/* Record that there was a login on that terminal. */
if (!options.use_login || command != NULL)
record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
hostname, (struct sockaddr *)&from);
/* Check if .hushlogin exists. */
snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir);
quiet_login = stat(line, &st) >= 0;
#ifdef USE_PAM
if (!quiet_login)
print_pam_messages();
#endif /* USE_PAM */
/*
* If the user has logged in before, display the time of last
* login. However, don't display anything extra if a command
* has been specified (so that ssh can be used to execute
* commands on a remote machine without users knowing they
* are going to another machine). Login(1) will do this for
* us as well, so check if login(1) is used
*/
if (command == NULL && last_login_time != 0 && !quiet_login &&
!options.use_login) {
/* Convert the date to a string. */
time_string = ctime(&last_login_time);
/* Remove the trailing newline. */
if (strchr(time_string, '\n'))
*strchr(time_string, '\n') = 0;
/* Display the last login time. Host if displayed
if known. */
if (strcmp(buf, "") == 0)
printf("Last login: %s\r\n", time_string);
else
printf("Last login: %s from %s\r\n", time_string, buf);
}
/*
* Print /etc/motd unless a command was specified or printing
* it was disabled in server options or login(1) will be
* used. Note that some machines appear to print it in
* /etc/profile or similar.
*/
if (command == NULL && options.print_motd && !quiet_login &&
!options.use_login) {
/* Print /etc/motd if it exists. */
f = fopen("/etc/motd", "r");
if (f) {
while (fgets(line, sizeof(line), f))
fputs(line, stdout);
fclose(f);
}
}
#if defined(WITH_AIXAUTHENTICATE)
/*
* AIX handles the lastlog info differently. Display it here.
*/
if (command == NULL && aixloginmsg && *aixloginmsg &&
!quiet_login && !options.use_login) {
printf("%s\n", aixloginmsg);
}
#endif
/* Do common processing for the child, such as execing the command. */ /* Do common processing for the child, such as execing the command. */
do_child(command, pw, s->term, s->display, s->auth_proto, do_child(command, pw, s->term, s->display, s->auth_proto,
s->auth_data, s->tty); s->auth_data, s->tty);
@ -699,6 +605,87 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw)
} }
} }
const char *
get_remote_name_or_ip(void)
{
static const char *remote = "";
if (utmp_len > 0)
remote = get_canonical_hostname();
if (utmp_len == 0 || strlen(remote) > utmp_len)
remote = get_remote_ipaddr();
return remote;
}
/* administrative, login(1)-like work */
void
do_login(Session *s)
{
FILE *f;
char *time_string;
char buf[256];
socklen_t fromlen;
struct sockaddr_storage from;
struct stat st;
time_t last_login_time;
struct passwd * pw = s->pw;
pid_t pid = getpid();
/*
* Get IP address of client. If the connection is not a socket, let
* the address be 0.0.0.0.
*/
memset(&from, 0, sizeof(from));
if (packet_connection_is_on_socket()) {
fromlen = sizeof(from);
if (getpeername(packet_get_connection_in(),
(struct sockaddr *) & from, &fromlen) < 0) {
debug("getpeername: %.100s", strerror(errno));
fatal_cleanup();
}
}
/* Record that there was a login on that tty from the remote host. */
record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
get_remote_name_or_ip(), (struct sockaddr *)&from);
/* Done if .hushlogin exists. */
snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
if (stat(buf, &st) >= 0)
return;
#ifdef USE_PAM
print_pam_messages();
#endif /* USE_PAM */
#ifdef WITH_AIXAUTHENTICATE
if (aixloginmsg && *aixloginmsg)
printf("%s\n", aixloginmsg);
#endif /* WITH_AIXAUTHENTICATE */
/*
* Get the time when the user last logged in. 'buf' will be set
* to contain the hostname the last login was from.
*/
last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
buf, sizeof(buf));
if (last_login_time != 0) {
time_string = ctime(&last_login_time);
if (strchr(time_string, '\n'))
*strchr(time_string, '\n') = 0;
if (strcmp(buf, "") == 0)
printf("Last login: %s\r\n", time_string);
else
printf("Last login: %s from %s\r\n", time_string, buf);
}
if (options.print_motd) {
f = fopen("/etc/motd", "r");
if (f) {
while (fgets(buf, sizeof(buf), f))
fputs(buf, stdout);
fclose(f);
}
}
}
/* /*
* Sets the value of the given variable in the environment. If the variable * Sets the value of the given variable in the environment. If the variable
* already exists, its value is overriden. * already exists, its value is overriden.
@ -1265,8 +1252,9 @@ do_child(const char *command, struct passwd * pw, const char *term,
} else { } else {
/* Launch login(1). */ /* Launch login(1). */
execl(LOGIN_PROGRAM, "login", "-h", get_remote_ipaddr(), execl(LOGIN_PROGRAM, "login",
"-p", "-f", "--", pw->pw_name, NULL); "-h", get_remote_name_or_ip(),
"-p", "-f", "--", pw->pw_name, NULL);
/* Login couldn't be executed, die. */ /* Login couldn't be executed, die. */

4
ssh.1
View File

@ -9,7 +9,7 @@
.\" .\"
.\" Created: Sat Apr 22 21:55:14 1995 ylo .\" Created: Sat Apr 22 21:55:14 1995 ylo
.\" .\"
.\" $Id: ssh.1,v 1.28 2000/06/07 09:55:44 djm Exp $ .\" $Id: ssh.1,v 1.29 2000/08/18 03:59:06 djm Exp $
.\" .\"
.Dd September 25, 1999 .Dd September 25, 1999
.Dt SSH 1 .Dt SSH 1
@ -994,7 +994,7 @@ If the current session has no tty,
this variable is not set. this variable is not set.
.It Ev TZ .It Ev TZ
The timezone variable is set to indicate the present timezone if it The timezone variable is set to indicate the present timezone if it
was set when the daemon was started (e.i., the daemon passes the value was set when the daemon was started (i.e., the daemon passes the value
on to new connections). on to new connections).
.It Ev USER .It Ev USER
Set to the name of the user logging in. Set to the name of the user logging in.

65
sshd.8
View File

@ -9,7 +9,7 @@
.\" .\"
.\" Created: Sat Apr 22 21:55:14 1995 ylo .\" Created: Sat Apr 22 21:55:14 1995 ylo
.\" .\"
.\" $Id: sshd.8,v 1.25 2000/07/11 07:31:39 djm Exp $ .\" $Id: sshd.8,v 1.26 2000/08/18 03:59:06 djm Exp $
.\" .\"
.Dd September 25, 1999 .Dd September 25, 1999
.Dt SSHD 8 .Dt SSHD 8
@ -26,6 +26,7 @@
.Op Fl h Ar host_key_file .Op Fl h Ar host_key_file
.Op Fl k Ar key_gen_time .Op Fl k Ar key_gen_time
.Op Fl p Ar port .Op Fl p Ar port
.Op Fl u Ar len
.Op Fl V Ar client_protocol_id .Op Fl V Ar client_protocol_id
.Sh DESCRIPTION .Sh DESCRIPTION
.Nm .Nm
@ -104,7 +105,7 @@ into the machine).
.Pp .Pp
.Ss SSH protocol version 2 .Ss SSH protocol version 2
.Pp .Pp
Version 2 works similar: Version 2 works similarly:
Each host has a host-specific DSA key used to identify the host. Each host has a host-specific DSA key used to identify the host.
However, when the daemon starts, it does not generate a server key. However, when the daemon starts, it does not generate a server key.
Forward security is provided through a Diffie-Hellman key agreement. Forward security is provided through a Diffie-Hellman key agreement.
@ -211,6 +212,22 @@ Quiet mode.
Nothing is sent to the system log. Nothing is sent to the system log.
Normally the beginning, Normally the beginning,
authentication, and termination of each connection is logged. authentication, and termination of each connection is logged.
.It Fl u Ar len
This option is used to specify the size of the field
in the
.Li utmp
structure that holds the remote host name.
If the resolved host name is longer than
.Ar len ,
the dotted decimal value will be used instead.
This allows hosts with very long host names that
overflow this field to still be uniquely identified.
Specifying
.Fl u0
indicates that only dotted decimal addresses
should be put into the
.Pa utmp
file.
.It Fl Q .It Fl Q
Do not print an error message if RSA support is missing. Do not print an error message if RSA support is missing.
.It Fl V Ar client_protocol_id .It Fl V Ar client_protocol_id
@ -257,7 +274,7 @@ and
.Ql ? .Ql ?
can be used as can be used as
wildcards in the patterns. wildcards in the patterns.
Only group names are valid, a numerical group ID isn't recognized. Only group names are valid; a numerical group ID isn't recognized.
By default login is allowed regardless of the primary group. By default login is allowed regardless of the primary group.
.Pp .Pp
.It Cm AllowUsers .It Cm AllowUsers
@ -270,7 +287,7 @@ and
.Ql ? .Ql ?
can be used as can be used as
wildcards in the patterns. wildcards in the patterns.
Only user names are valid, a numerical user ID isn't recognized. Only user names are valid; a numerical user ID isn't recognized.
By default login is allowed regardless of the user name. By default login is allowed regardless of the user name.
.Pp .Pp
.It Cm Ciphers .It Cm Ciphers
@ -294,7 +311,7 @@ and
.Ql ? .Ql ?
can be used as can be used as
wildcards in the patterns. wildcards in the patterns.
Only group names are valid, a numerical group ID isn't recognized. Only group names are valid; a numerical group ID isn't recognized.
By default login is allowed regardless of the primary group. By default login is allowed regardless of the primary group.
.Pp .Pp
.It Cm DenyUsers .It Cm DenyUsers
@ -305,7 +322,7 @@ Login is disallowed for user names that match one of the patterns.
and and
.Ql ? .Ql ?
can be used as wildcards in the patterns. can be used as wildcards in the patterns.
Only user names are valid, a numerical user ID isn't recognized. Only user names are valid; a numerical user ID isn't recognized.
By default login is allowed regardless of the user name. By default login is allowed regardless of the user name.
.It Cm DSAAuthentication .It Cm DSAAuthentication
Specifies whether DSA authentication is allowed. Specifies whether DSA authentication is allowed.
@ -321,7 +338,7 @@ or
.Dq no . .Dq no .
The default is The default is
.Dq no . .Dq no .
.It Cm HostDsaKey .It Cm HostDSAKey
Specifies the file containing the private DSA host key (default Specifies the file containing the private DSA host key (default
.Pa /etc/ssh_host_dsa_key ) .Pa /etc/ssh_host_dsa_key )
used by SSH protocol 2.0. used by SSH protocol 2.0.
@ -383,7 +400,8 @@ Specifies whether Kerberos authentication is allowed.
This can be in the form of a Kerberos ticket, or if This can be in the form of a Kerberos ticket, or if
.Cm PasswordAuthentication .Cm PasswordAuthentication
is yes, the password provided by the user will be validated through is yes, the password provided by the user will be validated through
the Kerberos KDC. the Kerberos KDC. To use this option, the server needs a
Kerberos servtab which allows the verification of the KDC's identity.
Default is Default is
.Dq yes . .Dq yes .
.It Cm KerberosOrLocalPasswd .It Cm KerberosOrLocalPasswd
@ -443,11 +461,28 @@ Additional connections will be dropped until authentication succeeds or the
.Cm LoginGraceTime .Cm LoginGraceTime
expires for a connection. expires for a connection.
The default is 10. The default is 10.
.Pp
Alternatively, random early drop can be enabled by specifying
the three colon separated values
.Dq start:rate:full
(e.g. "10:30:60").
.Nm
will refuse connection attempts with a probabillity of
.Dq rate/100
(30%)
if there are currently
.Dq start
(10)
unauthenticated connections.
The probabillity increases linearly and all connection attempts
are refused if the number of unauthenticated connections reaches
.Dq full
(60).
.It Cm PasswordAuthentication .It Cm PasswordAuthentication
Specifies whether password authentication is allowed. Specifies whether password authentication is allowed.
The default is The default is
.Dq yes . .Dq yes .
Note that this option applies to both protocol version 1 and 2. Note that this option applies to both protocol versions 1 and 2.
.It Cm PermitEmptyPasswords .It Cm PermitEmptyPasswords
When password authentication is allowed, it specifies whether the When password authentication is allowed, it specifies whether the
server allows login to accounts with empty password strings. server allows login to accounts with empty password strings.
@ -568,7 +603,7 @@ Specifies whether
is used for interactive login sessions. is used for interactive login sessions.
Note that Note that
.Xr login 1 .Xr login 1
is not never for remote command execution. is never used for remote command execution.
The default is The default is
.Dq no . .Dq no .
.It Cm X11DisplayOffset .It Cm X11DisplayOffset
@ -666,7 +701,7 @@ You don't want to type them in; instead, copy the
.Pa identity.pub .Pa identity.pub
file and edit it. file and edit it.
.Pp .Pp
The options (if present) consists of comma-separated option The options (if present) consist of comma-separated option
specifications. specifications.
No spaces are permitted, except within double quotes. No spaces are permitted, except within double quotes.
The following option specifications are supported: The following option specifications are supported:
@ -740,7 +775,7 @@ and
files contain host public keys for all known hosts. files contain host public keys for all known hosts.
The global file should The global file should
be prepared by the administrator (optional), and the per-user file is be prepared by the administrator (optional), and the per-user file is
maintained automatically: whenever the user connects an unknown host maintained automatically: whenever the user connects from an unknown host
its key is added to the per-user file. its key is added to the per-user file.
.Pp .Pp
Each line in these files contains the following fields: hostnames, Each line in these files contains the following fields: hostnames,
@ -815,7 +850,7 @@ Contains the process ID of the
listening for connections (if there are several daemons running listening for connections (if there are several daemons running
concurrently for different ports, this contains the pid of the one concurrently for different ports, this contains the pid of the one
started last). started last).
The contents of this file are not sensitive; it can be world-readable. The content of this file is not sensitive; it can be world-readable.
.It Pa $HOME/.ssh/authorized_keys .It Pa $HOME/.ssh/authorized_keys
Lists the RSA keys that can be used to log into the user's account. Lists the RSA keys that can be used to log into the user's account.
This file must be readable by root (which may on some machines imply This file must be readable by root (which may on some machines imply
@ -843,7 +878,7 @@ These files are consulted when using rhosts with RSA host
authentication to check the public key of the host. authentication to check the public key of the host.
The key must be listed in one of these files to be accepted. The key must be listed in one of these files to be accepted.
The client uses the same files The client uses the same files
to verify that the remote host is the one we intended to connect. to verify that the remote host is the one it intended to connect.
These files should be writable only by root/the owner. These files should be writable only by root/the owner.
.Pa /etc/ssh_known_hosts .Pa /etc/ssh_known_hosts
should be world-readable, and should be world-readable, and
@ -882,7 +917,7 @@ this file is exactly the same as for
.Pa .rhosts . .Pa .rhosts .
However, this file is However, this file is
not used by rlogin and rshd, so using this permits access using SSH only. not used by rlogin and rshd, so using this permits access using SSH only.
.Pa /etc/hosts.equiv .It Pa /etc/hosts.equiv
This file is used during This file is used during
.Pa .rhosts .Pa .rhosts
authentication. authentication.

43
sshd.c
View File

@ -14,7 +14,7 @@
*/ */
#include "includes.h" #include "includes.h"
RCSID("$OpenBSD: sshd.c,v 1.123 2000/07/18 01:25:01 djm Exp $"); RCSID("$OpenBSD: sshd.c,v 1.125 2000/08/17 20:06:34 markus Exp $");
#include "xmalloc.h" #include "xmalloc.h"
#include "rsa.h" #include "rsa.h"
@ -139,6 +139,9 @@ unsigned char session_id[16];
unsigned char *session_id2 = NULL; unsigned char *session_id2 = NULL;
int session_id2_len = 0; int session_id2_len = 0;
/* record remote hostname or ip */
unsigned int utmp_len = MAXHOSTNAMELEN;
/* Prototypes for various functions defined later in this file. */ /* Prototypes for various functions defined later in this file. */
void do_ssh1_kex(); void do_ssh1_kex();
void do_ssh2_kex(); void do_ssh2_kex();
@ -400,6 +403,35 @@ destroy_sensitive_data(void)
key_free(sensitive_data.dsa_host_key); key_free(sensitive_data.dsa_host_key);
} }
/*
* returns 1 if connection should be dropped, 0 otherwise.
* dropping starts at connection #max_startups_begin with a probability
* of (max_startups_rate/100). the probability increases linearly until
* all connections are dropped for startups > max_startups
*/
int
drop_connection(int startups)
{
double p, r;
if (startups < options.max_startups_begin)
return 0;
if (startups >= options.max_startups)
return 1;
if (options.max_startups_rate == 100)
return 1;
p = 100 - options.max_startups_rate;
p *= startups - options.max_startups_begin;
p /= (double) (options.max_startups - options.max_startups_begin);
p += options.max_startups_rate;
p /= 100.0;
r = arc4random() / (double) UINT_MAX;
debug("drop_connection: p %g, r %g", p, r);
return (r < p) ? 1 : 0;
}
int *startup_pipes = NULL; /* options.max_startup sized array of fd ints */ int *startup_pipes = NULL; /* options.max_startup sized array of fd ints */
int startup_pipe; /* in child */ int startup_pipe; /* in child */
@ -441,7 +473,7 @@ main(int ac, char **av)
initialize_server_options(&options); initialize_server_options(&options);
/* Parse command-line arguments. */ /* Parse command-line arguments. */
while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:diqQ46")) != EOF) { while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:diqQ46")) != EOF) {
switch (opt) { switch (opt) {
case '4': case '4':
IPv4or6 = AF_INET; IPv4or6 = AF_INET;
@ -488,6 +520,9 @@ main(int ac, char **av)
/* only makes sense with inetd_flag, i.e. no listen() */ /* only makes sense with inetd_flag, i.e. no listen() */
inetd_flag = 1; inetd_flag = 1;
break; break;
case 'u':
utmp_len = atoi(optarg);
break;
case '?': case '?':
default: default:
fprintf(stderr, "sshd version %s\n", SSH_VERSION); fprintf(stderr, "sshd version %s\n", SSH_VERSION);
@ -503,6 +538,7 @@ main(int ac, char **av)
fprintf(stderr, " -b bits Size of server RSA key (default: 768 bits)\n"); fprintf(stderr, " -b bits Size of server RSA key (default: 768 bits)\n");
fprintf(stderr, " -h file File from which to read host key (default: %s)\n", fprintf(stderr, " -h file File from which to read host key (default: %s)\n",
HOST_KEY_FILE); HOST_KEY_FILE);
fprintf(stderr, " -u len Maximum hostname length for utmp recording\n");
fprintf(stderr, " -4 Use IPv4 only\n"); fprintf(stderr, " -4 Use IPv4 only\n");
fprintf(stderr, " -6 Use IPv6 only\n"); fprintf(stderr, " -6 Use IPv6 only\n");
exit(1); exit(1);
@ -823,7 +859,8 @@ main(int ac, char **av)
error("newsock del O_NONBLOCK: %s", strerror(errno)); error("newsock del O_NONBLOCK: %s", strerror(errno));
continue; continue;
} }
if (startups >= options.max_startups) { if (drop_connection(startups) == 1) {
debug("drop connection #%d", startups);
close(newsock); close(newsock);
continue; continue;
} }

View File

@ -51,3 +51,4 @@ CheckMail no
UseLogin no UseLogin no
#Subsystem sftp /usr/local/sbin/sftpd #Subsystem sftp /usr/local/sbin/sftpd
#MaxStartups 10:30:60