to compile on more platforms (incl NeXT).
- (djm) Added bsd-inet_aton and configure support for NeXT
- (djm) Misc NeXT fixes from Ben Lindstrom <mouring@pconline.com>
+ - (djm) OpenBSD CVS updates:
+ - markus@cvs.openbsd.org 2000/06/26 03:22:29
+ [authfd.c]
+ cleanup, less cut&paste
+ - markus@cvs.openbsd.org 2000/06/26 15:59:19
+ [servconf.c servconf.h session.c sshd.8 sshd.c]
+ MaxStartups: limit number of unauthenticated connections, work by
+ theo and me
+ - deraadt@cvs.openbsd.org 2000/07/05 14:18:07
+ [session.c]
+ use no_x11_forwarding_flag correctly; provos ok
+ - provos@cvs.openbsd.org 2000/07/05 15:35:57
+ [sshd.c]
+ typo
+ - aaron@cvs.openbsd.org 2000/07/05 22:06:58
+ [scp.1 ssh-agent.1 ssh-keygen.1 sshd.8]
+ Insert more missing .El directives. Our troff really should identify
+ these and spit out a warning.
+ - todd@cvs.openbsd.org 2000/07/06 21:55:04
+ [auth-rsa.c auth2.c ssh-keygen.c]
+ clean code is good code
+ - deraadt@cvs.openbsd.org 2000/07/07 02:14:29
+ [serverloop.c]
+ sense of port forwarding flag test was backwards
+ - provos@cvs.openbsd.org 2000/07/08 17:17:31
+ [compat.c readconf.c]
+ replace strtok with strsep; from David Young <dyoung@onthejob.net>
+ - deraadt@cvs.openbsd.org 2000/07/08 19:21:15
+ [auth.h]
+ KNF
+ - ho@cvs.openbsd.org 2000/07/08 19:27:33
+ [compat.c readconf.c]
+ Better conditions for strsep() ending.
+ - ho@cvs.openbsd.org 2000/07/10 10:27:05
+ [readconf.c]
+ Get the correct message on errors. (niels@ ok)
+ - ho@cvs.openbsd.org 2000/07/10 10:30:25
+ [cipher.c kex.c servconf.c]
+ strtok() --> strsep(). (niels@ ok)
20000709
- (djm) Only enable PAM_TTY kludge for Linux. Problem report from
*/
#include "includes.h"
-RCSID("$OpenBSD: auth-rsa.c,v 1.26 2000/06/20 01:39:38 markus Exp $");
+RCSID("$OpenBSD: auth-rsa.c,v 1.27 2000/07/07 03:55:03 todd Exp $");
#include "rsa.h"
#include "packet.h"
}
if (fail) {
fclose(f);
- log(buf);
- packet_send_debug(buf);
+ log("%s",buf);
+ packet_send_debug("%s",buf);
restore_uid();
return 0;
}
struct passwd *
auth_get_user(void);
-int allowed_user(struct passwd * pw);;
+int allowed_user(struct passwd * pw);
#define AUTH_FAIL_MAX 6
#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
-RCSID("$OpenBSD: auth2.c,v 1.11 2000/06/19 00:50:11 markus Exp $");
+RCSID("$OpenBSD: auth2.c,v 1.12 2000/07/07 03:55:03 todd Exp $");
#include <openssl/dsa.h>
#include <openssl/rsa.h>
}
}
if (fail) {
- log(buf);
fclose(f);
+ log("%s",buf);
restore_uid();
return 0;
}
*/
#include "includes.h"
-RCSID("$OpenBSD: authfd.c,v 1.20 2000/06/20 01:39:38 markus Exp $");
+RCSID("$OpenBSD: authfd.c,v 1.21 2000/06/26 09:22:29 markus Exp $");
#include "ssh.h"
#include "rsa.h"
#include <openssl/rsa.h>
+/* helper */
+int ssh_agent_get_reply(AuthenticationConnection *auth);
+
/* Returns the number of the authentication fd, or -1 if there is none. */
int
{
Buffer buffer;
unsigned char buf[8192];
- int len, l, type;
+ int len;
/* Format a message to the agent. */
buffer_init(&buffer);
atomicio(write, auth->fd, buffer_ptr(&buffer),
buffer_len(&buffer)) != buffer_len(&buffer)) {
error("Error writing to authentication socket.");
-error_cleanup:
buffer_free(&buffer);
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.");
- goto error_cleanup;
- }
- len -= l;
- }
-
- /* Extract the length, and check it for sanity. */
- len = GET_32BIT(buf);
- if (len > 256 * 1024)
- fatal("Add identity 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. */
- type = buffer_get_char(&buffer);
- switch (type) {
- case SSH_AGENT_FAILURE:
- buffer_free(&buffer);
- return 0;
- case SSH_AGENT_SUCCESS:
- buffer_free(&buffer);
- return 1;
- default:
- fatal("Bad response to add identity from authentication agent: %d",
- type);
- }
- /* NOTREACHED */
- return 0;
+ buffer_free(&buffer);
+ return ssh_agent_get_reply(auth);
}
/*
ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
{
Buffer buffer;
- unsigned char buf[8192];
- int len, l, type;
+ unsigned char buf[5];
+ int len;
/* Format a message to the agent. */
buffer_init(&buffer);
atomicio(write, auth->fd, buffer_ptr(&buffer),
buffer_len(&buffer)) != buffer_len(&buffer)) {
error("Error writing to authentication socket.");
-error_cleanup:
buffer_free(&buffer);
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.");
- goto error_cleanup;
- }
- len -= l;
- }
-
- /* Extract the length, and check it for sanity. */
- len = GET_32BIT(buf);
- if (len > 256 * 1024)
- fatal("Remove identity 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. */
- type = buffer_get_char(&buffer);
- switch (type) {
- case SSH_AGENT_FAILURE:
- buffer_free(&buffer);
- return 0;
- case SSH_AGENT_SUCCESS:
- buffer_free(&buffer);
- return 1;
- default:
- fatal("Bad response to remove identity from authentication agent: %d",
- type);
- }
- /* NOTREACHED */
- return 0;
+ buffer_free(&buffer);
+ return ssh_agent_get_reply(auth);
}
/*
int
ssh_remove_all_identities(AuthenticationConnection *auth)
{
- Buffer buffer;
- unsigned char buf[8192];
- int len, l, type;
+ unsigned char buf[5];
/* Get the length of the message, and format it in the buffer. */
PUT_32BIT(buf, 1);
error("Error writing to authentication socket.");
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.
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("Remove identity response too long: %d", len);
+ fatal("Response from agent too long: %d", len);
- /* Read the rest of the response into the buffer. */
+ /* Read the rest of the response in to the buffer. */
buffer_init(&buffer);
while (len > 0) {
l = len;
/* Get the type of the packet. */
type = buffer_get_char(&buffer);
+ buffer_free(&buffer);
switch (type) {
case SSH_AGENT_FAILURE:
- buffer_free(&buffer);
return 0;
case SSH_AGENT_SUCCESS:
- buffer_free(&buffer);
return 1;
default:
- fatal("Bad response to remove identity from authentication agent: %d",
- type);
+ fatal("Bad response from authentication agent: %d", type);
}
/* NOTREACHED */
return 0;
*/
#include "includes.h"
-RCSID("$OpenBSD: cipher.c,v 1.28 2000/06/20 01:39:40 markus Exp $");
+RCSID("$OpenBSD: cipher.c,v 1.29 2000/07/10 16:30:25 ho Exp $");
#include "ssh.h"
#include "cipher.h"
int
ciphers_valid(const char *names)
{
- char *ciphers;
+ char *ciphers, *cp;
char *p;
int i;
if (names == NULL || strcmp(names, "") == 0)
return 0;
- ciphers = xstrdup(names);
- for ((p = strtok(ciphers, CIPHER_SEP)); p; (p = strtok(NULL, CIPHER_SEP))) {
+ ciphers = cp = xstrdup(names);
+ for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
+ (p = strsep(&cp, CIPHER_SEP))) {
i = cipher_number(p);
if (i == -1 || !(cipher_mask2() & (1 << i))) {
xfree(ciphers);
*/
#include "includes.h"
-RCSID("$OpenBSD: compat.c,v 1.17 2000/06/20 01:39:40 markus Exp $");
+RCSID("$OpenBSD: compat.c,v 1.19 2000/07/09 01:27:32 ho Exp $");
#include "ssh.h"
#include "packet.h"
int
proto_spec(const char *spec)
{
- char *s, *p;
+ char *s, *p, *q;
int ret = SSH_PROTO_UNKNOWN;
if (spec == NULL)
return ret;
- s = xstrdup(spec);
- for ((p = strtok(s, SEP)); p; (p = strtok(NULL, SEP))) {
+ q = s = xstrdup(spec);
+ for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) {
switch(atoi(p)) {
case 1:
if (ret == SSH_PROTO_UNKNOWN)
*/
#include "includes.h"
-RCSID("$OpenBSD: kex.c,v 1.8 2000/06/20 01:39:41 markus Exp $");
+RCSID("$OpenBSD: kex.c,v 1.9 2000/07/10 16:30:25 ho Exp $");
#include "ssh.h"
#include "ssh2.h"
get_match(char *client, char *server)
{
char *sproposals[MAX_PROP];
- char *c, *s, *p, *ret;
+ char *c, *s, *p, *ret, *cp, *sp;
int i, j, nproposals;
- c = xstrdup(client);
- s = xstrdup(server);
+ c = cp = xstrdup(client);
+ s = sp = xstrdup(server);
- for ((p = strtok(s, SEP)), i=0; p; (p = strtok(NULL, SEP)), i++) {
+ for ((p = strsep(&sp, SEP)), i=0; p && *p != '\0';
+ (p = strsep(&sp, SEP)), i++) {
if (i < MAX_PROP)
sproposals[i] = p;
else
}
nproposals = i;
- for ((p = strtok(c, SEP)), i=0; p; (p = strtok(NULL, SEP)), i++) {
+ for ((p = strsep(&cp, SEP)), i=0; p && *p != '\0';
+ (p = strsep(&cp, SEP)), i++) {
for (j = 0; j < nproposals; j++) {
if (strcmp(p, sproposals[j]) == 0) {
ret = xstrdup(p);
*/
#include "includes.h"
-RCSID("$OpenBSD: readconf.c,v 1.37 2000/06/20 01:39:43 markus Exp $");
+RCSID("$OpenBSD: readconf.c,v 1.40 2000/07/10 16:27:05 ho Exp $");
#include "ssh.h"
#include "cipher.h"
{ NULL, 0 }
};
-/* Characters considered whitespace in strtok calls. */
+/* Characters considered whitespace in strsep calls. */
#define WHITESPACE " \t\r\n="
char *line, const char *filename, int linenum,
int *activep)
{
- char buf[256], *cp, *string, **charptr, *cp2;
+ char buf[256], *s, *string, **charptr, *endofnumber, *keyword, *arg;
int opcode, *intptr, value;
u_short fwd_port, fwd_host_port;
/* Skip leading whitespace. */
- cp = line + strspn(line, WHITESPACE);
- if (!*cp || *cp == '\n' || *cp == '#')
+ s = line + strspn(line, WHITESPACE);
+ if (!*s || *s == '\n' || *s == '#')
return 0;
/* Get the keyword. (Each line is supposed to begin with a keyword). */
- cp = strtok(cp, WHITESPACE);
- opcode = parse_token(cp, filename, linenum);
+ keyword = strsep(&s, WHITESPACE);
+ opcode = parse_token(keyword, filename, linenum);
switch (opcode) {
case oBadOption:
case oForwardAgent:
intptr = &options->forward_agent;
parse_flag:
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ arg = strsep(&s, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
value = 0; /* To avoid compiler warning... */
- if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
+ if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
value = 1;
- else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
+ else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
value = 0;
else
fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
case oStrictHostKeyChecking:
intptr = &options->strict_host_key_checking;
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ arg = strsep(&s, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing yes/no argument.",
filename, linenum);
value = 0; /* To avoid compiler warning... */
- if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
+ if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
value = 1;
- else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
+ else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
value = 0;
- else if (strcmp(cp, "ask") == 0)
+ else if (strcmp(arg, "ask") == 0)
value = 2;
else
fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
case oIdentityFile:
case oIdentityFile2:
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ arg = strsep(&s, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (*activep) {
intptr = (opcode == oIdentityFile) ?
charptr = (opcode == oIdentityFile) ?
&options->identity_files[*intptr] :
&options->identity_files2[*intptr];
- *charptr = xstrdup(cp);
+ *charptr = xstrdup(arg);
*intptr = *intptr + 1;
}
break;
case oUser:
charptr = &options->user;
parse_string:
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ arg = strsep(&s, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (*activep && *charptr == NULL)
- *charptr = xstrdup(cp);
+ *charptr = xstrdup(arg);
break;
case oGlobalKnownHostsFile:
case oProxyCommand:
charptr = &options->proxy_command;
string = xstrdup("");
- while ((cp = strtok(NULL, WHITESPACE)) != NULL) {
- string = xrealloc(string, strlen(string) + strlen(cp) + 2);
+ while ((arg = strsep(&s, WHITESPACE)) != NULL && *arg != '\0') {
+ string = xrealloc(string, strlen(string) + strlen(arg) + 2);
strcat(string, " ");
- strcat(string, cp);
+ strcat(string, arg);
}
if (*activep && *charptr == NULL)
*charptr = string;
case oPort:
intptr = &options->port;
parse_int:
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ arg = strsep(&s, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (cp[0] < '0' || cp[0] > '9')
+ if (arg[0] < '0' || arg[0] > '9')
fatal("%.200s line %d: Bad number.", filename, linenum);
/* Octal, decimal, or hex format? */
- value = strtol(cp, &cp2, 0);
- if (cp == cp2)
+ value = strtol(arg, &endofnumber, 0);
+ if (arg == endofnumber)
fatal("%.200s line %d: Bad number.", filename, linenum);
if (*activep && *intptr == -1)
*intptr = value;
case oCipher:
intptr = &options->cipher;
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ arg = strsep(&s, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
- value = cipher_number(cp);
+ value = cipher_number(arg);
if (value == -1)
fatal("%.200s line %d: Bad cipher '%s'.",
- filename, linenum, cp ? cp : "<NONE>");
+ filename, linenum, arg ? arg : "<NONE>");
if (*activep && *intptr == -1)
*intptr = value;
break;
case oCiphers:
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ arg = strsep(&s, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (!ciphers_valid(cp))
+ if (!ciphers_valid(arg))
fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
- filename, linenum, cp ? cp : "<NONE>");
+ filename, linenum, arg ? arg : "<NONE>");
if (*activep && options->ciphers == NULL)
- options->ciphers = xstrdup(cp);
+ options->ciphers = xstrdup(arg);
break;
case oProtocol:
intptr = &options->protocol;
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ arg = strsep(&s, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
- value = proto_spec(cp);
+ value = proto_spec(arg);
if (value == SSH_PROTO_UNKNOWN)
fatal("%.200s line %d: Bad protocol spec '%s'.",
- filename, linenum, cp ? cp : "<NONE>");
+ filename, linenum, arg ? arg : "<NONE>");
if (*activep && *intptr == SSH_PROTO_UNKNOWN)
*intptr = value;
break;
case oLogLevel:
intptr = (int *) &options->log_level;
- cp = strtok(NULL, WHITESPACE);
- value = log_level_number(cp);
+ arg = strsep(&s, WHITESPACE);
+ value = log_level_number(arg);
if (value == (LogLevel) - 1)
fatal("%.200s line %d: unsupported log level '%s'\n",
- filename, linenum, cp ? cp : "<NONE>");
+ filename, linenum, arg ? arg : "<NONE>");
if (*activep && (LogLevel) * intptr == -1)
*intptr = (LogLevel) value;
break;
case oRemoteForward:
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ arg = strsep(&s, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (cp[0] < '0' || cp[0] > '9')
+ if (arg[0] < '0' || arg[0] > '9')
fatal("%.200s line %d: Badly formatted port number.",
filename, linenum);
- fwd_port = atoi(cp);
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ fwd_port = atoi(arg);
+ arg = strsep(&s, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing second argument.",
filename, linenum);
- if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
+ if (sscanf(arg, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
fatal("%.200s line %d: Badly formatted host:port.",
filename, linenum);
if (*activep)
break;
case oLocalForward:
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ arg = strsep(&s, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (cp[0] < '0' || cp[0] > '9')
+ if (arg[0] < '0' || arg[0] > '9')
fatal("%.200s line %d: Badly formatted port number.",
filename, linenum);
- fwd_port = atoi(cp);
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ fwd_port = atoi(arg);
+ arg = strsep(&s, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing second argument.",
filename, linenum);
- if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
+ if (sscanf(arg, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
fatal("%.200s line %d: Badly formatted host:port.",
filename, linenum);
if (*activep)
case oHost:
*activep = 0;
- while ((cp = strtok(NULL, WHITESPACE)) != NULL)
- if (match_pattern(host, cp)) {
- debug("Applying options for %.100s", cp);
+ while ((arg = strsep(&s, WHITESPACE)) != NULL && *arg != '\0')
+ if (match_pattern(host, arg)) {
+ debug("Applying options for %.100s", arg);
*activep = 1;
break;
}
- /* Avoid garbage check below, as strtok already returned NULL. */
+ /* Avoid garbage check below, as strsep is done. */
return 0;
case oEscapeChar:
intptr = &options->escape_char;
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ arg = strsep(&s, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
- if (cp[0] == '^' && cp[2] == 0 &&
- (unsigned char) cp[1] >= 64 && (unsigned char) cp[1] < 128)
- value = (unsigned char) cp[1] & 31;
- else if (strlen(cp) == 1)
- value = (unsigned char) cp[0];
- else if (strcmp(cp, "none") == 0)
+ if (arg[0] == '^' && arg[2] == 0 &&
+ (unsigned char) arg[1] >= 64 && (unsigned char) arg[1] < 128)
+ value = (unsigned char) arg[1] & 31;
+ else if (strlen(arg) == 1)
+ value = (unsigned char) arg[0];
+ else if (strcmp(arg, "none") == 0)
value = -2;
else {
fatal("%.200s line %d: Bad escape character.",
}
/* Check that there is no garbage at end of line. */
- if (strtok(NULL, WHITESPACE) != NULL)
- fatal("%.200s line %d: garbage at end of line.",
- filename, linenum);
+ if ((arg = strsep(&s, WHITESPACE)) != NULL && *arg != '\0')
+ {
+ fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
+ filename, linenum, arg);
+ }
return 0;
}
Forces
.Nm
to use IPv6 addresses only.
+.El
.Sh AUTHORS
Timo Rinne <tri@iki.fi> and Tatu Ylonen <ylo@cs.hut.fi>
.Sh HISTORY
*/
#include "includes.h"
-RCSID("$OpenBSD: servconf.c,v 1.45 2000/06/20 01:39:44 markus Exp $");
+RCSID("$OpenBSD: servconf.c,v 1.47 2000/07/10 16:30:25 ho Exp $");
#include "ssh.h"
#include "servconf.h"
options->protocol = SSH_PROTO_UNKNOWN;
options->gateway_ports = -1;
options->num_subsystems = 0;
+ options->max_startups = -1;
}
void
options->protocol = SSH_PROTO_1|SSH_PROTO_2;
if (options->gateway_ports == -1)
options->gateway_ports = 0;
+ if (options->max_startups == -1)
+ options->max_startups = 10;
}
#define WHITESPACE " \t\r\n="
sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile,
- sGatewayPorts, sDSAAuthentication, sXAuthLocation, sSubsystem
+ sGatewayPorts, sDSAAuthentication, sXAuthLocation, sSubsystem, sMaxStartups
} ServerOpCodes;
/* Textual representation of the tokens. */
{ "protocol", sProtocol },
{ "gatewayports", sGatewayPorts },
{ "subsystem", sSubsystem },
+ { "maxstartups", sMaxStartups },
{ NULL, 0 }
};
{
FILE *f;
char line[1024];
- char *cp, **charptr;
+ char *cp, **charptr, *arg;
int linenum, *intptr, value;
int bad_options = 0;
ServerOpCodes opcode;
cp = line + strspn(line, WHITESPACE);
if (!*cp || *cp == '#')
continue;
- cp = strtok(cp, WHITESPACE);
- opcode = parse_token(cp, filename, linenum);
+ arg = strsep(&cp, WHITESPACE);
+ opcode = parse_token(arg, filename, linenum);
switch (opcode) {
case sBadOption:
bad_options++;
if (options->num_ports >= MAX_PORTS)
fatal("%s line %d: too many ports.\n",
filename, linenum);
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ arg = strsep(&cp, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%s line %d: missing port number.\n",
filename, linenum);
- options->ports[options->num_ports++] = atoi(cp);
+ options->ports[options->num_ports++] = atoi(arg);
break;
case sServerKeyBits:
intptr = &options->server_key_bits;
parse_int:
- cp = strtok(NULL, WHITESPACE);
- if (!cp) {
+ arg = strsep(&cp, WHITESPACE);
+ if (!arg || *arg == '\0') {
fprintf(stderr, "%s line %d: missing integer value.\n",
filename, linenum);
exit(1);
}
- value = atoi(cp);
+ value = atoi(arg);
if (*intptr == -1)
*intptr = value;
break;
goto parse_int;
case sListenAddress:
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ arg = strsep(&cp, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%s line %d: missing inet addr.\n",
filename, linenum);
- add_listen_addr(options, cp);
+ add_listen_addr(options, arg);
break;
case sHostKeyFile:
charptr = (opcode == sHostKeyFile ) ?
&options->host_key_file : &options->host_dsa_key_file;
parse_filename:
- cp = strtok(NULL, WHITESPACE);
- if (!cp) {
+ arg = strsep(&cp, WHITESPACE);
+ if (!arg || *arg == '\0') {
fprintf(stderr, "%s line %d: missing file name.\n",
filename, linenum);
exit(1);
}
if (*charptr == NULL)
- *charptr = tilde_expand_filename(cp, getuid());
+ *charptr = tilde_expand_filename(arg, getuid());
break;
case sPidFile:
case sRandomSeedFile:
fprintf(stderr, "%s line %d: \"randomseed\" option is obsolete.\n",
filename, linenum);
- cp = strtok(NULL, WHITESPACE);
+ arg = strsep(&cp, WHITESPACE);
break;
case sPermitRootLogin:
intptr = &options->permit_root_login;
- cp = strtok(NULL, WHITESPACE);
- if (!cp) {
+ arg = strsep(&cp, WHITESPACE);
+ if (!arg || *arg == '\0') {
fprintf(stderr, "%s line %d: missing yes/without-password/no argument.\n",
filename, linenum);
exit(1);
}
- if (strcmp(cp, "without-password") == 0)
+ if (strcmp(arg, "without-password") == 0)
value = 2;
- else if (strcmp(cp, "yes") == 0)
+ else if (strcmp(arg, "yes") == 0)
value = 1;
- else if (strcmp(cp, "no") == 0)
+ else if (strcmp(arg, "no") == 0)
value = 0;
else {
fprintf(stderr, "%s line %d: Bad yes/without-password/no argument: %s\n",
- filename, linenum, cp);
+ filename, linenum, arg);
exit(1);
}
if (*intptr == -1)
case sIgnoreRhosts:
intptr = &options->ignore_rhosts;
parse_flag:
- cp = strtok(NULL, WHITESPACE);
- if (!cp) {
+ arg = strsep(&cp, WHITESPACE);
+ if (!arg || *arg == '\0') {
fprintf(stderr, "%s line %d: missing yes/no argument.\n",
filename, linenum);
exit(1);
}
- if (strcmp(cp, "yes") == 0)
+ if (strcmp(arg, "yes") == 0)
value = 1;
- else if (strcmp(cp, "no") == 0)
+ else if (strcmp(arg, "no") == 0)
value = 0;
else {
fprintf(stderr, "%s line %d: Bad yes/no argument: %s\n",
- filename, linenum, cp);
+ filename, linenum, arg);
exit(1);
}
if (*intptr == -1)
case sLogFacility:
intptr = (int *) &options->log_facility;
- cp = strtok(NULL, WHITESPACE);
- value = log_facility_number(cp);
+ arg = strsep(&cp, WHITESPACE);
+ value = log_facility_number(arg);
if (value == (SyslogFacility) - 1)
fatal("%.200s line %d: unsupported log facility '%s'\n",
- filename, linenum, cp ? cp : "<NONE>");
+ filename, linenum, arg ? arg : "<NONE>");
if (*intptr == -1)
*intptr = (SyslogFacility) value;
break;
case sLogLevel:
intptr = (int *) &options->log_level;
- cp = strtok(NULL, WHITESPACE);
- value = log_level_number(cp);
+ arg = strsep(&cp, WHITESPACE);
+ value = log_level_number(arg);
if (value == (LogLevel) - 1)
fatal("%.200s line %d: unsupported log level '%s'\n",
- filename, linenum, cp ? cp : "<NONE>");
+ filename, linenum, arg ? arg : "<NONE>");
if (*intptr == -1)
*intptr = (LogLevel) value;
break;
case sAllowUsers:
- while ((cp = strtok(NULL, WHITESPACE))) {
+ while ((arg = strsep(&cp, WHITESPACE)) && *arg != '\0') {
if (options->num_allow_users >= MAX_ALLOW_USERS)
fatal("%s line %d: too many allow users.\n",
filename, linenum);
- options->allow_users[options->num_allow_users++] = xstrdup(cp);
+ options->allow_users[options->num_allow_users++] = xstrdup(arg);
}
break;
case sDenyUsers:
- while ((cp = strtok(NULL, WHITESPACE))) {
+ while ((arg = strsep(&cp, WHITESPACE)) && *arg != '\0') {
if (options->num_deny_users >= MAX_DENY_USERS)
fatal( "%s line %d: too many deny users.\n",
filename, linenum);
- options->deny_users[options->num_deny_users++] = xstrdup(cp);
+ options->deny_users[options->num_deny_users++] = xstrdup(arg);
}
break;
case sAllowGroups:
- while ((cp = strtok(NULL, WHITESPACE))) {
+ while ((arg = strsep(&cp, WHITESPACE)) && *arg != '\0') {
if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
fatal("%s line %d: too many allow groups.\n",
filename, linenum);
- options->allow_groups[options->num_allow_groups++] = xstrdup(cp);
+ options->allow_groups[options->num_allow_groups++] = xstrdup(arg);
}
break;
case sDenyGroups:
- while ((cp = strtok(NULL, WHITESPACE))) {
+ while ((arg = strsep(&cp, WHITESPACE)) && *arg != '\0') {
if (options->num_deny_groups >= MAX_DENY_GROUPS)
fatal("%s line %d: too many deny groups.\n",
filename, linenum);
- options->deny_groups[options->num_deny_groups++] = xstrdup(cp);
+ options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
}
break;
case sCiphers:
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ arg = strsep(&cp, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
- if (!ciphers_valid(cp))
+ if (!ciphers_valid(arg))
fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
- filename, linenum, cp ? cp : "<NONE>");
+ filename, linenum, arg ? arg : "<NONE>");
if (options->ciphers == NULL)
- options->ciphers = xstrdup(cp);
+ options->ciphers = xstrdup(arg);
break;
case sProtocol:
intptr = &options->protocol;
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ arg = strsep(&cp, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
- value = proto_spec(cp);
+ value = proto_spec(arg);
if (value == SSH_PROTO_UNKNOWN)
fatal("%s line %d: Bad protocol spec '%s'.",
- filename, linenum, cp ? cp : "<NONE>");
+ filename, linenum, arg ? arg : "<NONE>");
if (*intptr == SSH_PROTO_UNKNOWN)
*intptr = value;
break;
fatal("%s line %d: too many subsystems defined.",
filename, linenum);
}
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ arg = strsep(&cp, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%s line %d: Missing subsystem name.",
filename, linenum);
for (i = 0; i < options->num_subsystems; i++)
- if(strcmp(cp, options->subsystem_name[i]) == 0)
+ if(strcmp(arg, options->subsystem_name[i]) == 0)
fatal("%s line %d: Subsystem '%s' already defined.",
- filename, linenum, cp);
- options->subsystem_name[options->num_subsystems] = xstrdup(cp);
- cp = strtok(NULL, WHITESPACE);
- if (!cp)
+ filename, linenum, arg);
+ options->subsystem_name[options->num_subsystems] = xstrdup(arg);
+ arg = strsep(&cp, WHITESPACE);
+ if (!arg || *arg == '\0')
fatal("%s line %d: Missing subsystem command.",
filename, linenum);
- options->subsystem_command[options->num_subsystems] = xstrdup(cp);
+ options->subsystem_command[options->num_subsystems] = xstrdup(arg);
options->num_subsystems++;
break;
+ case sMaxStartups:
+ intptr = &options->max_startups;
+ goto parse_int;
+
default:
fprintf(stderr, "%s line %d: Missing handler for opcode %s (%d)\n",
- filename, linenum, cp, opcode);
+ filename, linenum, arg, opcode);
exit(1);
}
- if (strtok(NULL, WHITESPACE) != NULL) {
- fprintf(stderr, "%s line %d: garbage at end of line.\n",
- filename, linenum);
+ if ((arg = strsep(&cp, WHITESPACE)) != NULL && *arg != '\0') {
+ fprintf(stderr,
+ "%s line %d: garbage at end of line; \"%.200s\".\n",
+ filename, linenum, arg);
exit(1);
}
}
*
*/
-/* RCSID("$OpenBSD: servconf.h,v 1.25 2000/06/20 01:39:44 markus Exp $"); */
+/* RCSID("$OpenBSD: servconf.h,v 1.26 2000/06/26 21:59:18 markus Exp $"); */
#ifndef SERVCONF_H
#define SERVCONF_H
unsigned int num_subsystems;
char *subsystem_name[MAX_SUBSYSTEMS];
char *subsystem_command[MAX_SUBSYSTEMS];
+
+ int max_startups;
+
} ServerOptions;
/*
* Initializes the server options to special values that indicate that they
originator, originator_port, target, target_port);
/* XXX check permission */
- if (! no_port_forwarding_flag) {
+ if (no_port_forwarding_flag) {
xfree(target);
xfree(originator);
return -1;
*/
#include "includes.h"
-RCSID("$OpenBSD: session.c,v 1.20 2000/06/18 04:42:54 markus Exp $");
-#if defined(HAVE_USERSEC_H)
-#include <usersec.h>
-#endif
+RCSID("$OpenBSD: session.c,v 1.22 2000/07/05 20:18:07 deraadt Exp $");
#include "xmalloc.h"
#include "ssh.h"
#include <proj.h>
#endif /* WITH_IRIX_PROJECT */
+#if defined(HAVE_USERSEC_H)
+#include <usersec.h>
+#endif
+
#ifdef HAVE_OSF_SIA
# include <sia.h>
# include <siad.h>
extern int log_stderr;
extern int debug_flag;
+extern int startup_pipe;
+
/* Local Xauthority file. */
static char *xauthfile;
* authentication.
*/
alarm(0);
+ close(startup_pipe);
/*
* Inform the channel mechanism that we are the server side and that
int
session_x11_req(Session *s)
{
- if (!no_port_forwarding_flag) {
+ if (no_x11_forwarding_flag) {
debug("X11 forwarding disabled in user configuration file.");
return 0;
}
* authentication.
*/
alarm(0);
+ close(startup_pipe);
server_loop2();
if (xauthfile)
xauthfile_cleanup_proc(NULL);
-.\" $OpenBSD: ssh-agent.1,v 1.12 2000/05/03 18:04:39 markus Exp $
+.\" $OpenBSD: ssh-agent.1,v 1.13 2000/07/06 04:06:56 aaron Exp $
.\"
.\" -*- nroff -*-
.\"
authentication agent.
These sockets should only be readable by the owner.
The sockets should get automatically removed when the agent exits.
+.El
.Sh AUTHOR
Tatu Ylonen <ylo@cs.hut.fi>
.Pp
on all machines
where you wish to log in using DSA authentication.
There is no need to keep the contents of this file secret.
+.El
.Sh AUTHOR
Tatu Ylonen <ylo@cs.hut.fi>
.Pp
*/
#include "includes.h"
-RCSID("$OpenBSD: ssh-keygen.c,v 1.27 2000/06/20 01:39:44 markus Exp $");
+RCSID("$OpenBSD: ssh-keygen.c,v 1.28 2000/07/07 03:55:04 todd Exp $");
#include <openssl/evp.h>
#include <openssl/pem.h>
exit(1);
}
dsa_make_key_blob(k, &blob, &len);
- fprintf(stdout, SSH_COM_MAGIC_BEGIN "\n");
+ fprintf(stdout, "%s\n", SSH_COM_MAGIC_BEGIN);
fprintf(stdout,
"Comment: \"%d-bit DSA, converted from openssh by %s@%s\"\n",
BN_num_bits(k->dsa->p),
pw->pw_name, hostname);
dump_base64(stdout, blob, len);
- fprintf(stdout, SSH_COM_MAGIC_END "\n");
+ fprintf(stdout, "%s\n", SSH_COM_MAGIC_END);
key_free(k);
xfree(blob);
exit(0);
The default is INFO.
Logging with level DEBUG violates the privacy of users
and is not recommended.
+.It Cm MaxStartups
+Specifies the maximum number of concurrent unauthenticated connections to the
+.Nm
+daemon.
+Additional connections will be dropped until authentication succeeds or the
+.Cm LoginGraceTime
+expires for a connection.
+The default is 10.
.It Cm PasswordAuthentication
Specifies whether password authentication is allowed.
The default is
This can be used to specify
machine-specific login-time initializations globally.
This file should be writable only by root, and should be world-readable.
+.El
.Sh AUTHOR
OpenSSH
is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen,
*/
#include "includes.h"
-RCSID("$OpenBSD: sshd.c,v 1.119 2000/06/22 16:32:27 markus Exp $");
+RCSID("$OpenBSD: sshd.c,v 1.121 2000/07/05 21:35:56 provos Exp $");
#include "xmalloc.h"
#include "rsa.h"
break;
}
if (remote_minor < 3) {
- packet_disconnect("Your ssh version is too old and"
+ packet_disconnect("Your ssh version is too old and "
"is no longer supported. Please install a newer version.");
} else if (remote_minor == 3) {
/* note that this disables agent-forwarding */
key_free(sensitive_data.dsa_host_key);
}
+int *startup_pipes = NULL; /* options.max_startup sized array of fd ints */
+int startup_pipe; /* in child */
+
/*
* Main program for the daemon.
*/
{
extern char *optarg;
extern int optind;
- int opt, sock_in = 0, sock_out = 0, newsock, i, fdsetsz, on = 1;
+ int opt, sock_in = 0, sock_out = 0, newsock, j, i, fdsetsz, on = 1;
pid_t pid;
socklen_t fromlen;
int silent = 0;
struct addrinfo *ai;
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
int listen_sock, maxfd;
+ int startup_p[2];
+ int startups = 0;
init_rng();
/* Arrange to restart on SIGHUP. The handler needs listen_sock. */
signal(SIGHUP, sighup_handler);
+
signal(SIGTERM, sigterm_handler);
signal(SIGQUIT, sigterm_handler);
signal(SIGCHLD, main_sigchld_handler);
/* setup fd set for listen */
+ fdset = NULL;
maxfd = 0;
for (i = 0; i < num_listen_socks; i++)
if (listen_socks[i] > maxfd)
maxfd = listen_socks[i];
- fdsetsz = howmany(maxfd, NFDBITS) * sizeof(fd_mask);
- fdset = (fd_set *)xmalloc(fdsetsz);
+ /* pipes connected to unauthenticated childs */
+ startup_pipes = xmalloc(options.max_startups * sizeof(int));
+ for (i = 0; i < options.max_startups; i++)
+ startup_pipes[i] = -1;
/*
* Stay listening for connections until the system crashes or
for (;;) {
if (received_sighup)
sighup_restart();
- /* Wait in select until there is a connection. */
+ if (fdset != NULL)
+ xfree(fdset);
+ fdsetsz = howmany(maxfd, NFDBITS) * sizeof(fd_mask);
+ fdset = (fd_set *)xmalloc(fdsetsz);
memset(fdset, 0, fdsetsz);
+
for (i = 0; i < num_listen_socks; i++)
FD_SET(listen_socks[i], fdset);
+ for (i = 0; i < options.max_startups; i++)
+ if (startup_pipes[i] != -1)
+ FD_SET(startup_pipes[i], fdset);
+
+ /* Wait in select until there is a connection. */
if (select(maxfd + 1, fdset, NULL, NULL, NULL) < 0) {
if (errno != EINTR)
error("select: %.100s", strerror(errno));
continue;
}
+ for (i = 0; i < options.max_startups; i++)
+ if (startup_pipes[i] != -1 &&
+ FD_ISSET(startup_pipes[i], fdset)) {
+ /*
+ * the read end of the pipe is ready
+ * if the child has closed the pipe
+ * after successfull authentication
+ * or if the child has died
+ */
+ close(startup_pipes[i]);
+ startup_pipes[i] = -1;
+ startups--;
+ }
for (i = 0; i < num_listen_socks; i++) {
if (!FD_ISSET(listen_socks[i], fdset))
continue;
- fromlen = sizeof(from);
- newsock = accept(listen_socks[i], (struct sockaddr *)&from,
- &fromlen);
- if (newsock < 0) {
- if (errno != EINTR && errno != EWOULDBLOCK)
- error("accept: %.100s", strerror(errno));
- continue;
- }
- if (fcntl(newsock, F_SETFL, 0) < 0) {
- error("newsock del O_NONBLOCK: %s", strerror(errno));
- continue;
- }
- /*
- * Got connection. Fork a child to handle it, unless
- * we are in debugging mode.
- */
- if (debug_flag) {
- /*
- * In debugging mode. Close the listening
- * socket, and start processing the
- * connection without forking.
- */
- debug("Server will not fork when running in debugging mode.");
- close_listen_socks();
- sock_in = newsock;
- sock_out = newsock;
- pid = getpid();
- break;
- } else {
+ fromlen = sizeof(from);
+ newsock = accept(listen_socks[i], (struct sockaddr *)&from,
+ &fromlen);
+ if (newsock < 0) {
+ if (errno != EINTR && errno != EWOULDBLOCK)
+ error("accept: %.100s", strerror(errno));
+ continue;
+ }
+ if (fcntl(newsock, F_SETFL, 0) < 0) {
+ error("newsock del O_NONBLOCK: %s", strerror(errno));
+ continue;
+ }
+ if (startups >= options.max_startups) {
+ close(newsock);
+ continue;
+ }
+ if (pipe(startup_p) == -1) {
+ close(newsock);
+ continue;
+ }
+
+ for (j = 0; j < options.max_startups; j++)
+ if (startup_pipes[j] == -1) {
+ startup_pipes[j] = startup_p[0];
+ if (maxfd < startup_p[0])
+ maxfd = startup_p[0];
+ startups++;
+ break;
+ }
+
/*
- * Normal production daemon. Fork, and have
- * the child process the connection. The
- * parent continues listening.
+ * Got connection. Fork a child to handle it, unless
+ * we are in debugging mode.
*/
- if ((pid = fork()) == 0) {
+ if (debug_flag) {
/*
- * Child. Close the listening socket, and start using the
- * accepted socket. Reinitialize logging (since our pid has
- * changed). We break out of the loop to handle the connection.
+ * In debugging mode. Close the listening
+ * socket, and start processing the
+ * connection without forking.
*/
+ debug("Server will not fork when running in debugging mode.");
close_listen_socks();
sock_in = newsock;
sock_out = newsock;
- log_init(av0, options.log_level, options.log_facility, log_stderr);
+ pid = getpid();
break;
+ } else {
+ /*
+ * Normal production daemon. Fork, and have
+ * the child process the connection. The
+ * parent continues listening.
+ */
+ if ((pid = fork()) == 0) {
+ /*
+ * Child. Close the listening and max_startup
+ * sockets. Start using the accepted socket.
+ * Reinitialize logging (since our pid has
+ * changed). We break out of the loop to handle
+ * the connection.
+ */
+ startup_pipe = startup_p[1];
+ for (j = 0; j < options.max_startups; j++)
+ if (startup_pipes[j] != -1)
+ close(startup_pipes[j]);
+ close_listen_socks();
+ sock_in = newsock;
+ sock_out = newsock;
+ log_init(av0, options.log_level, options.log_facility, log_stderr);
+ break;
+ }
}
- }
- /* Parent. Stay in the loop. */
- if (pid < 0)
- error("fork: %.100s", strerror(errno));
- else
- debug("Forked child %d.", pid);
+ /* Parent. Stay in the loop. */
+ if (pid < 0)
+ error("fork: %.100s", strerror(errno));
+ else
+ debug("Forked child %d.", pid);
- /* Mark that the key has been used (it was "given" to the child). */
- key_used = 1;
+ close(startup_p[1]);
- arc4random_stir();
+ /* Mark that the key has been used (it was "given" to the child). */
+ key_used = 1;
- /* Close the new socket (the child is now taking care of it). */
- close(newsock);
- } /* for (i = 0; i < num_listen_socks; i++) */
+ arc4random_stir();
+
+ /* Close the new socket (the child is now taking care of it). */
+ close(newsock);
+ }
/* child process check (or debug mode) */
if (num_listen_socks < 0)
break;