[servconf.c servconf.h sshd.8 sshd.c]
     add -o to sshd, too. ok deraadt@
 - (bal) Minor white space fix up in servconf.c
This commit is contained in:
Ben Lindstrom 2001-12-06 18:22:17 +00:00
parent 9eab262f1c
commit ade03f6bad
5 changed files with 523 additions and 489 deletions

View File

@ -68,6 +68,10 @@
- markus@cvs.openbsd.org 2001/12/05 16:54:51 - markus@cvs.openbsd.org 2001/12/05 16:54:51
[compat.c match.c match.h] [compat.c match.c match.h]
make theo and djm happy: bye bye regexp make theo and djm happy: bye bye regexp
- markus@cvs.openbsd.org 2001/12/06 13:30:06
[servconf.c servconf.h sshd.8 sshd.c]
add -o to sshd, too. ok deraadt@
- (bal) Minor white space fix up in servconf.c
20011126 20011126
- (tim) [contrib/cygwin/README, openbsd-compat/bsd-cygwin_util.c, - (tim) [contrib/cygwin/README, openbsd-compat/bsd-cygwin_util.c,
@ -6990,4 +6994,4 @@
- Wrote replacements for strlcpy and mkdtemp - Wrote replacements for strlcpy and mkdtemp
- Released 1.0pre1 - Released 1.0pre1
$Id: ChangeLog,v 1.1686 2001/12/06 18:06:05 mouring Exp $ $Id: ChangeLog,v 1.1687 2001/12/06 18:22:17 mouring Exp $

View File

@ -10,7 +10,7 @@
*/ */
#include "includes.h" #include "includes.h"
RCSID("$OpenBSD: servconf.c,v 1.93 2001/12/05 10:06:12 deraadt Exp $"); RCSID("$OpenBSD: servconf.c,v 1.94 2001/12/06 13:30:05 markus Exp $");
#if defined(KRB4) || defined(KRB5) #if defined(KRB4) || defined(KRB5)
#include <krb.h> #include <krb.h>
@ -261,7 +261,7 @@ typedef enum {
sBanner, sReverseMappingCheck, sHostbasedAuthentication, sBanner, sReverseMappingCheck, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
sDeprecated sDeprecated
} ServerOpCodes; } ServerOpCodes;
/* Textual representation of the tokens. */ /* Textual representation of the tokens. */
@ -392,6 +392,476 @@ add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
options->listen_addrs = aitop; options->listen_addrs = aitop;
} }
int
process_server_config_line(ServerOptions *options, char *line,
const char *filename, int linenum)
{
char *cp, **charptr, *arg, *p;
int *intptr, value;
ServerOpCodes opcode;
int i, n;
cp = line;
arg = strdelim(&cp);
/* Ignore leading whitespace */
if (*arg == '\0')
arg = strdelim(&cp);
if (!arg || !*arg || *arg == '#')
return 0;
intptr = NULL;
charptr = NULL;
opcode = parse_token(arg, filename, linenum);
switch (opcode) {
/* Portable-specific options */
case sPAMAuthenticationViaKbdInt:
intptr = &options->pam_authentication_via_kbd_int;
goto parse_flag;
/* Standard Options */
case sBadOption:
return -1;
case sPort:
/* ignore ports from configfile if cmdline specifies ports */
if (options->ports_from_cmdline)
return 0;
if (options->listen_addrs != NULL)
fatal("%s line %d: ports must be specified before "
"ListenAdress.", filename, linenum);
if (options->num_ports >= MAX_PORTS)
fatal("%s line %d: too many ports.",
filename, linenum);
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing port number.",
filename, linenum);
options->ports[options->num_ports++] = a2port(arg);
if (options->ports[options->num_ports-1] == 0)
fatal("%s line %d: Badly formatted port number.",
filename, linenum);
break;
case sServerKeyBits:
intptr = &options->server_key_bits;
parse_int:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing integer value.",
filename, linenum);
value = atoi(arg);
if (*intptr == -1)
*intptr = value;
break;
case sLoginGraceTime:
intptr = &options->login_grace_time;
parse_time:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing time value.",
filename, linenum);
if ((value = convtime(arg)) == -1)
fatal("%s line %d: invalid time value.",
filename, linenum);
if (*intptr == -1)
*intptr = value;
break;
case sKeyRegenerationTime:
intptr = &options->key_regeneration_time;
goto parse_time;
case sListenAddress:
arg = strdelim(&cp);
if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
fatal("%s line %d: missing inet addr.",
filename, linenum);
if (*arg == '[') {
if ((p = strchr(arg, ']')) == NULL)
fatal("%s line %d: bad ipv6 inet addr usage.",
filename, linenum);
arg++;
memmove(p, p+1, strlen(p+1)+1);
} else if (((p = strchr(arg, ':')) == NULL) ||
(strchr(p+1, ':') != NULL)) {
add_listen_addr(options, arg, 0);
break;
}
if (*p == ':') {
u_short port;
p++;
if (*p == '\0')
fatal("%s line %d: bad inet addr:port usage.",
filename, linenum);
else {
*(p-1) = '\0';
if ((port = a2port(p)) == 0)
fatal("%s line %d: bad port number.",
filename, linenum);
add_listen_addr(options, arg, port);
}
} else if (*p == '\0')
add_listen_addr(options, arg, 0);
else
fatal("%s line %d: bad inet addr usage.",
filename, linenum);
break;
case sHostKeyFile:
intptr = &options->num_host_key_files;
if (*intptr >= MAX_HOSTKEYS)
fatal("%s line %d: too many host keys specified (max %d).",
filename, linenum, MAX_HOSTKEYS);
charptr = &options->host_key_files[*intptr];
parse_filename:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
if (*charptr == NULL) {
*charptr = tilde_expand_filename(arg, getuid());
/* increase optional counter */
if (intptr != NULL)
*intptr = *intptr + 1;
}
break;
case sPidFile:
charptr = &options->pid_file;
goto parse_filename;
case sPermitRootLogin:
intptr = &options->permit_root_login;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing yes/"
"without-password/forced-commands-only/no "
"argument.", filename, linenum);
value = 0; /* silence compiler */
if (strcmp(arg, "without-password") == 0)
value = PERMIT_NO_PASSWD;
else if (strcmp(arg, "forced-commands-only") == 0)
value = PERMIT_FORCED_ONLY;
else if (strcmp(arg, "yes") == 0)
value = PERMIT_YES;
else if (strcmp(arg, "no") == 0)
value = PERMIT_NO;
else
fatal("%s line %d: Bad yes/"
"without-password/forced-commands-only/no "
"argument: %s", filename, linenum, arg);
if (*intptr == -1)
*intptr = value;
break;
case sIgnoreRhosts:
intptr = &options->ignore_rhosts;
parse_flag:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing yes/no argument.",
filename, linenum);
value = 0; /* silence compiler */
if (strcmp(arg, "yes") == 0)
value = 1;
else if (strcmp(arg, "no") == 0)
value = 0;
else
fatal("%s line %d: Bad yes/no argument: %s",
filename, linenum, arg);
if (*intptr == -1)
*intptr = value;
break;
case sIgnoreUserKnownHosts:
intptr = &options->ignore_user_known_hosts;
goto parse_flag;
case sRhostsAuthentication:
intptr = &options->rhosts_authentication;
goto parse_flag;
case sRhostsRSAAuthentication:
intptr = &options->rhosts_rsa_authentication;
goto parse_flag;
case sHostbasedAuthentication:
intptr = &options->hostbased_authentication;
goto parse_flag;
case sHostbasedUsesNameFromPacketOnly:
intptr = &options->hostbased_uses_name_from_packet_only;
goto parse_flag;
case sRSAAuthentication:
intptr = &options->rsa_authentication;
goto parse_flag;
case sPubkeyAuthentication:
intptr = &options->pubkey_authentication;
goto parse_flag;
#if defined(KRB4) || defined(KRB5)
case sKerberosAuthentication:
intptr = &options->kerberos_authentication;
goto parse_flag;
case sKerberosOrLocalPasswd:
intptr = &options->kerberos_or_local_passwd;
goto parse_flag;
case sKerberosTicketCleanup:
intptr = &options->kerberos_ticket_cleanup;
goto parse_flag;
#endif
#if defined(AFS) || defined(KRB5)
case sKerberosTgtPassing:
intptr = &options->kerberos_tgt_passing;
goto parse_flag;
#endif
#ifdef AFS
case sAFSTokenPassing:
intptr = &options->afs_token_passing;
goto parse_flag;
#endif
case sPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
case sKbdInteractiveAuthentication:
intptr = &options->kbd_interactive_authentication;
goto parse_flag;
case sChallengeResponseAuthentication:
intptr = &options->challenge_response_authentication;
goto parse_flag;
case sPrintMotd:
intptr = &options->print_motd;
goto parse_flag;
case sPrintLastLog:
intptr = &options->print_lastlog;
goto parse_flag;
case sX11Forwarding:
intptr = &options->x11_forwarding;
goto parse_flag;
case sX11DisplayOffset:
intptr = &options->x11_display_offset;
goto parse_int;
case sXAuthLocation:
charptr = &options->xauth_location;
goto parse_filename;
case sStrictModes:
intptr = &options->strict_modes;
goto parse_flag;
case sKeepAlives:
intptr = &options->keepalives;
goto parse_flag;
case sEmptyPasswd:
intptr = &options->permit_empty_passwd;
goto parse_flag;
case sUseLogin:
intptr = &options->use_login;
goto parse_flag;
case sGatewayPorts:
intptr = &options->gateway_ports;
goto parse_flag;
case sReverseMappingCheck:
intptr = &options->reverse_mapping_check;
goto parse_flag;
case sLogFacility:
intptr = (int *) &options->log_facility;
arg = strdelim(&cp);
value = log_facility_number(arg);
if (value == (SyslogFacility) - 1)
fatal("%.200s line %d: unsupported log facility '%s'",
filename, linenum, arg ? arg : "<NONE>");
if (*intptr == -1)
*intptr = (SyslogFacility) value;
break;
case sLogLevel:
intptr = (int *) &options->log_level;
arg = strdelim(&cp);
value = log_level_number(arg);
if (value == (LogLevel) - 1)
fatal("%.200s line %d: unsupported log level '%s'",
filename, linenum, arg ? arg : "<NONE>");
if (*intptr == -1)
*intptr = (LogLevel) value;
break;
case sAllowTcpForwarding:
intptr = &options->allow_tcp_forwarding;
goto parse_flag;
case sAllowUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_allow_users >= MAX_ALLOW_USERS)
fatal("%s line %d: too many allow users.",
filename, linenum);
options->allow_users[options->num_allow_users++] = xstrdup(arg);
}
break;
case sDenyUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_deny_users >= MAX_DENY_USERS)
fatal( "%s line %d: too many deny users.",
filename, linenum);
options->deny_users[options->num_deny_users++] = xstrdup(arg);
}
break;
case sAllowGroups:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
fatal("%s line %d: too many allow groups.",
filename, linenum);
options->allow_groups[options->num_allow_groups++] = xstrdup(arg);
}
break;
case sDenyGroups:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_deny_groups >= MAX_DENY_GROUPS)
fatal("%s line %d: too many deny groups.",
filename, linenum);
options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
}
break;
case sCiphers:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
if (!ciphers_valid(arg))
fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->ciphers == NULL)
options->ciphers = xstrdup(arg);
break;
case sMacs:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
if (!mac_valid(arg))
fatal("%s line %d: Bad SSH2 mac spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->macs == NULL)
options->macs = xstrdup(arg);
break;
case sProtocol:
intptr = &options->protocol;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
value = proto_spec(arg);
if (value == SSH_PROTO_UNKNOWN)
fatal("%s line %d: Bad protocol spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*intptr == SSH_PROTO_UNKNOWN)
*intptr = value;
break;
case sSubsystem:
if (options->num_subsystems >= MAX_SUBSYSTEMS) {
fatal("%s line %d: too many subsystems defined.",
filename, linenum);
}
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing subsystem name.",
filename, linenum);
for (i = 0; i < options->num_subsystems; i++)
if (strcmp(arg, options->subsystem_name[i]) == 0)
fatal("%s line %d: Subsystem '%s' already defined.",
filename, linenum, arg);
options->subsystem_name[options->num_subsystems] = xstrdup(arg);
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing subsystem command.",
filename, linenum);
options->subsystem_command[options->num_subsystems] = xstrdup(arg);
options->num_subsystems++;
break;
case sMaxStartups:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing MaxStartups spec.",
filename, linenum);
if ((n = 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);
} else if (n != 1)
fatal("%s line %d: Illegal MaxStartups spec.",
filename, linenum);
else
options->max_startups = options->max_startups_begin;
break;
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;
goto parse_time;
case sClientAliveCountMax:
intptr = &options->client_alive_count_max;
goto parse_int;
case sDeprecated:
log("%s line %d: Deprecated option %s",
filename, linenum, arg);
while (arg)
arg = strdelim(&cp);
break;
default:
fatal("%s line %d: Missing handler for opcode %s (%d)",
filename, linenum, arg, opcode);
}
if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
fatal("%s line %d: garbage at end of line; \"%.200s\".",
filename, linenum, arg);
return 0;
}
/* Reads the server configuration file. */ /* Reads the server configuration file. */
void void
@ -399,11 +869,8 @@ read_server_config(ServerOptions *options, const char *filename)
{ {
FILE *f; FILE *f;
char line[1024]; char line[1024];
char *cp, **charptr, *arg, *p; int linenum;
int linenum, *intptr, value;
int bad_options = 0; int bad_options = 0;
ServerOpCodes opcode;
int i, n;
f = fopen(filename, "r"); f = fopen(filename, "r");
if (!f) { if (!f) {
@ -412,467 +879,10 @@ read_server_config(ServerOptions *options, const char *filename)
} }
linenum = 0; linenum = 0;
while (fgets(line, sizeof(line), f)) { while (fgets(line, sizeof(line), f)) {
/* Update line number counter. */
linenum++; linenum++;
cp = line; if (process_server_config_line(options, line, filename, linenum) != 0)
arg = strdelim(&cp);
/* Ignore leading whitespace */
if (*arg == '\0')
arg = strdelim(&cp);
if (!arg || !*arg || *arg == '#')
continue;
intptr = NULL;
charptr = NULL;
opcode = parse_token(arg, filename, linenum);
switch (opcode) {
case sBadOption:
bad_options++; bad_options++;
continue;
/* Portable-specific options */
case sPAMAuthenticationViaKbdInt:
intptr = &options->pam_authentication_via_kbd_int;
goto parse_flag;
/* Standard Options */
case sPort:
/* ignore ports from configfile if cmdline specifies ports */
if (options->ports_from_cmdline)
continue;
if (options->listen_addrs != NULL)
fatal("%s line %d: ports must be specified before "
"ListenAdress.", filename, linenum);
if (options->num_ports >= MAX_PORTS)
fatal("%s line %d: too many ports.",
filename, linenum);
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing port number.",
filename, linenum);
options->ports[options->num_ports++] = a2port(arg);
if (options->ports[options->num_ports-1] == 0)
fatal("%s line %d: Badly formatted port number.",
filename, linenum);
break;
case sServerKeyBits:
intptr = &options->server_key_bits;
parse_int:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing integer value.",
filename, linenum);
value = atoi(arg);
if (*intptr == -1)
*intptr = value;
break;
case sLoginGraceTime:
intptr = &options->login_grace_time;
parse_time:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing time value.",
filename, linenum);
if ((value = convtime(arg)) == -1)
fatal("%s line %d: invalid time value.",
filename, linenum);
if (*intptr == -1)
*intptr = value;
break;
case sKeyRegenerationTime:
intptr = &options->key_regeneration_time;
goto parse_time;
case sListenAddress:
arg = strdelim(&cp);
if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
fatal("%s line %d: missing inet addr.",
filename, linenum);
if (*arg == '[') {
if ((p = strchr(arg, ']')) == NULL)
fatal("%s line %d: bad ipv6 inet addr usage.",
filename, linenum);
arg++;
memmove(p, p+1, strlen(p+1)+1);
} else if (((p = strchr(arg, ':')) == NULL) ||
(strchr(p+1, ':') != NULL)) {
add_listen_addr(options, arg, 0);
break;
}
if (*p == ':') {
u_short port;
p++;
if (*p == '\0')
fatal("%s line %d: bad inet addr:port usage.",
filename, linenum);
else {
*(p-1) = '\0';
if ((port = a2port(p)) == 0)
fatal("%s line %d: bad port number.",
filename, linenum);
add_listen_addr(options, arg, port);
}
} else if (*p == '\0')
add_listen_addr(options, arg, 0);
else
fatal("%s line %d: bad inet addr usage.",
filename, linenum);
break;
case sHostKeyFile:
intptr = &options->num_host_key_files;
if (*intptr >= MAX_HOSTKEYS)
fatal("%s line %d: too many host keys specified (max %d).",
filename, linenum, MAX_HOSTKEYS);
charptr = &options->host_key_files[*intptr];
parse_filename:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
if (*charptr == NULL) {
*charptr = tilde_expand_filename(arg, getuid());
/* increase optional counter */
if (intptr != NULL)
*intptr = *intptr + 1;
}
break;
case sPidFile:
charptr = &options->pid_file;
goto parse_filename;
case sPermitRootLogin:
intptr = &options->permit_root_login;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing yes/"
"without-password/forced-commands-only/no "
"argument.", filename, linenum);
value = 0; /* silence compiler */
if (strcmp(arg, "without-password") == 0)
value = PERMIT_NO_PASSWD;
else if (strcmp(arg, "forced-commands-only") == 0)
value = PERMIT_FORCED_ONLY;
else if (strcmp(arg, "yes") == 0)
value = PERMIT_YES;
else if (strcmp(arg, "no") == 0)
value = PERMIT_NO;
else
fatal("%s line %d: Bad yes/"
"without-password/forced-commands-only/no "
"argument: %s", filename, linenum, arg);
if (*intptr == -1)
*intptr = value;
break;
case sIgnoreRhosts:
intptr = &options->ignore_rhosts;
parse_flag:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing yes/no argument.",
filename, linenum);
value = 0; /* silence compiler */
if (strcmp(arg, "yes") == 0)
value = 1;
else if (strcmp(arg, "no") == 0)
value = 0;
else
fatal("%s line %d: Bad yes/no argument: %s",
filename, linenum, arg);
if (*intptr == -1)
*intptr = value;
break;
case sIgnoreUserKnownHosts:
intptr = &options->ignore_user_known_hosts;
goto parse_flag;
case sRhostsAuthentication:
intptr = &options->rhosts_authentication;
goto parse_flag;
case sRhostsRSAAuthentication:
intptr = &options->rhosts_rsa_authentication;
goto parse_flag;
case sHostbasedAuthentication:
intptr = &options->hostbased_authentication;
goto parse_flag;
case sHostbasedUsesNameFromPacketOnly:
intptr = &options->hostbased_uses_name_from_packet_only;
goto parse_flag;
case sRSAAuthentication:
intptr = &options->rsa_authentication;
goto parse_flag;
case sPubkeyAuthentication:
intptr = &options->pubkey_authentication;
goto parse_flag;
#if defined(KRB4) || defined(KRB5)
case sKerberosAuthentication:
intptr = &options->kerberos_authentication;
goto parse_flag;
case sKerberosOrLocalPasswd:
intptr = &options->kerberos_or_local_passwd;
goto parse_flag;
case sKerberosTicketCleanup:
intptr = &options->kerberos_ticket_cleanup;
goto parse_flag;
#endif
#if defined(AFS) || defined(KRB5)
case sKerberosTgtPassing:
intptr = &options->kerberos_tgt_passing;
goto parse_flag;
#endif
#ifdef AFS
case sAFSTokenPassing:
intptr = &options->afs_token_passing;
goto parse_flag;
#endif
case sPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
case sKbdInteractiveAuthentication:
intptr = &options->kbd_interactive_authentication;
goto parse_flag;
case sChallengeResponseAuthentication:
intptr = &options->challenge_response_authentication;
goto parse_flag;
case sPrintMotd:
intptr = &options->print_motd;
goto parse_flag;
case sPrintLastLog:
intptr = &options->print_lastlog;
goto parse_flag;
case sX11Forwarding:
intptr = &options->x11_forwarding;
goto parse_flag;
case sX11DisplayOffset:
intptr = &options->x11_display_offset;
goto parse_int;
case sXAuthLocation:
charptr = &options->xauth_location;
goto parse_filename;
case sStrictModes:
intptr = &options->strict_modes;
goto parse_flag;
case sKeepAlives:
intptr = &options->keepalives;
goto parse_flag;
case sEmptyPasswd:
intptr = &options->permit_empty_passwd;
goto parse_flag;
case sUseLogin:
intptr = &options->use_login;
goto parse_flag;
case sGatewayPorts:
intptr = &options->gateway_ports;
goto parse_flag;
case sReverseMappingCheck:
intptr = &options->reverse_mapping_check;
goto parse_flag;
case sLogFacility:
intptr = (int *) &options->log_facility;
arg = strdelim(&cp);
value = log_facility_number(arg);
if (value == (SyslogFacility) - 1)
fatal("%.200s line %d: unsupported log facility '%s'",
filename, linenum, arg ? arg : "<NONE>");
if (*intptr == -1)
*intptr = (SyslogFacility) value;
break;
case sLogLevel:
intptr = (int *) &options->log_level;
arg = strdelim(&cp);
value = log_level_number(arg);
if (value == (LogLevel) - 1)
fatal("%.200s line %d: unsupported log level '%s'",
filename, linenum, arg ? arg : "<NONE>");
if (*intptr == -1)
*intptr = (LogLevel) value;
break;
case sAllowTcpForwarding:
intptr = &options->allow_tcp_forwarding;
goto parse_flag;
case sAllowUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_allow_users >= MAX_ALLOW_USERS)
fatal("%s line %d: too many allow users.",
filename, linenum);
options->allow_users[options->num_allow_users++] = xstrdup(arg);
}
break;
case sDenyUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_deny_users >= MAX_DENY_USERS)
fatal( "%s line %d: too many deny users.",
filename, linenum);
options->deny_users[options->num_deny_users++] = xstrdup(arg);
}
break;
case sAllowGroups:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
fatal("%s line %d: too many allow groups.",
filename, linenum);
options->allow_groups[options->num_allow_groups++] = xstrdup(arg);
}
break;
case sDenyGroups:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_deny_groups >= MAX_DENY_GROUPS)
fatal("%s line %d: too many deny groups.",
filename, linenum);
options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
}
break;
case sCiphers:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
if (!ciphers_valid(arg))
fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->ciphers == NULL)
options->ciphers = xstrdup(arg);
break;
case sMacs:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
if (!mac_valid(arg))
fatal("%s line %d: Bad SSH2 mac spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->macs == NULL)
options->macs = xstrdup(arg);
break;
case sProtocol:
intptr = &options->protocol;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
value = proto_spec(arg);
if (value == SSH_PROTO_UNKNOWN)
fatal("%s line %d: Bad protocol spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*intptr == SSH_PROTO_UNKNOWN)
*intptr = value;
break;
case sSubsystem:
if (options->num_subsystems >= MAX_SUBSYSTEMS) {
fatal("%s line %d: too many subsystems defined.",
filename, linenum);
}
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing subsystem name.",
filename, linenum);
for (i = 0; i < options->num_subsystems; i++)
if (strcmp(arg, options->subsystem_name[i]) == 0)
fatal("%s line %d: Subsystem '%s' already defined.",
filename, linenum, arg);
options->subsystem_name[options->num_subsystems] = xstrdup(arg);
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing subsystem command.",
filename, linenum);
options->subsystem_command[options->num_subsystems] = xstrdup(arg);
options->num_subsystems++;
break;
case sMaxStartups:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing MaxStartups spec.",
filename, linenum);
if ((n = 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);
} else if (n != 1)
fatal("%s line %d: Illegal MaxStartups spec.",
filename, linenum);
else
options->max_startups = options->max_startups_begin;
break;
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;
goto parse_time;
case sClientAliveCountMax:
intptr = &options->client_alive_count_max;
goto parse_int;
case sDeprecated:
log("%s line %d: Deprecated option %s",
filename, linenum, arg);
while (arg)
arg = strdelim(&cp);
break;
default:
fatal("%s line %d: Missing handler for opcode %s (%d)",
filename, linenum, arg, opcode);
}
if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
fatal("%s line %d: garbage at end of line; \"%.200s\".",
filename, linenum, arg);
} }
fclose(f); fclose(f);
if (bad_options > 0) if (bad_options > 0)

View File

@ -11,7 +11,7 @@
* called by a name other than "ssh" or "Secure Shell". * called by a name other than "ssh" or "Secure Shell".
*/ */
/* RCSID("$OpenBSD: servconf.h,v 1.49 2001/08/17 18:59:47 stevesk Exp $"); */ /* RCSID("$OpenBSD: servconf.h,v 1.50 2001/12/06 13:30:05 markus Exp $"); */
#ifndef SERVCONF_H #ifndef SERVCONF_H
#define SERVCONF_H #define SERVCONF_H
@ -135,5 +135,7 @@ typedef struct {
void initialize_server_options(ServerOptions *); void initialize_server_options(ServerOptions *);
void read_server_config(ServerOptions *, const char *); void read_server_config(ServerOptions *, const char *);
void fill_default_server_options(ServerOptions *); void fill_default_server_options(ServerOptions *);
int process_server_config_line(ServerOptions *, char *, const char *, int);
#endif /* SERVCONF_H */ #endif /* SERVCONF_H */

7
sshd.8
View File

@ -34,7 +34,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: sshd.8,v 1.155 2001/12/01 21:41:48 markus Exp $ .\" $OpenBSD: sshd.8,v 1.156 2001/12/06 13:30:06 markus Exp $
.Dd September 25, 1999 .Dd September 25, 1999
.Dt SSHD 8 .Dt SSHD 8
.Os .Os
@ -49,6 +49,7 @@
.Op Fl g Ar login_grace_time .Op Fl g Ar login_grace_time
.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 o Ar option
.Op Fl p Ar port .Op Fl p Ar port
.Op Fl u Ar len .Op Fl u Ar len
.Sh DESCRIPTION .Sh DESCRIPTION
@ -237,6 +238,10 @@ it becomes impossible to recover the key for decrypting intercepted
communications even if the machine is cracked into or physically communications even if the machine is cracked into or physically
seized. seized.
A value of zero indicates that the key will never be regenerated. A value of zero indicates that the key will never be regenerated.
.It Fl o Ar option
Can be used to give options in the format used in the configuration file.
This is useful for specifying options for which there is no separate
command-line flag.
.It Fl p Ar port .It Fl p Ar port
Specifies the port on which the server listens for connections Specifies the port on which the server listens for connections
(default 22). (default 22).

55
sshd.c
View File

@ -40,7 +40,7 @@
*/ */
#include "includes.h" #include "includes.h"
RCSID("$OpenBSD: sshd.c,v 1.214 2001/12/05 10:06:13 deraadt Exp $"); RCSID("$OpenBSD: sshd.c,v 1.215 2001/12/06 13:30:06 markus Exp $");
#include <openssl/dh.h> #include <openssl/dh.h>
#include <openssl/bn.h> #include <openssl/bn.h>
@ -543,6 +543,31 @@ drop_connection(int startups)
return (r < p) ? 1 : 0; return (r < p) ? 1 : 0;
} }
static void
usage(void)
{
fprintf(stderr, "sshd version %s\n", SSH_VERSION);
fprintf(stderr, "Usage: %s [options]\n", __progname);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -f file Configuration file (default %s)\n", _PATH_SERVER_CONFIG_FILE);
fprintf(stderr, " -d Debugging mode (multiple -d means more debugging)\n");
fprintf(stderr, " -i Started from inetd\n");
fprintf(stderr, " -D Do not fork into daemon mode\n");
fprintf(stderr, " -t Only test configuration file and keys\n");
fprintf(stderr, " -q Quiet (no logging)\n");
fprintf(stderr, " -p port Listen on the specified port (default: 22)\n");
fprintf(stderr, " -k seconds Regenerate server key every this many seconds (default: 3600)\n");
fprintf(stderr, " -g seconds Grace period for authentication (default: 600)\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",
_PATH_HOST_KEY_FILE);
fprintf(stderr, " -u len Maximum hostname length for utmp recording\n");
fprintf(stderr, " -4 Use IPv4 only\n");
fprintf(stderr, " -6 Use IPv6 only\n");
fprintf(stderr, " -o option Process the option as if it was read from a configuration file.\n");
exit(1);
}
/* /*
* Main program for the daemon. * Main program for the daemon.
*/ */
@ -579,7 +604,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:u:dDeiqtQ46")) != -1) { while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:o:dDeiqtQ46")) != -1) {
switch (opt) { switch (opt) {
case '4': case '4':
IPv4or6 = AF_INET; IPv4or6 = AF_INET;
@ -661,27 +686,15 @@ main(int ac, char **av)
case 'u': case 'u':
utmp_len = atoi(optarg); utmp_len = atoi(optarg);
break; break;
case 'o':
if (process_server_config_line(&options, optarg,
"command-line", 0) != 0)
exit(1);
break;
case '?': case '?':
default: default:
fprintf(stderr, "sshd version %s\n", SSH_VERSION); usage();
fprintf(stderr, "Usage: %s [options]\n", __progname); break;
fprintf(stderr, "Options:\n");
fprintf(stderr, " -f file Configuration file (default %s)\n", _PATH_SERVER_CONFIG_FILE);
fprintf(stderr, " -d Debugging mode (multiple -d means more debugging)\n");
fprintf(stderr, " -i Started from inetd\n");
fprintf(stderr, " -D Do not fork into daemon mode\n");
fprintf(stderr, " -t Only test configuration file and keys\n");
fprintf(stderr, " -q Quiet (no logging)\n");
fprintf(stderr, " -p port Listen on the specified port (default: 22)\n");
fprintf(stderr, " -k seconds Regenerate server key every this many seconds (default: 3600)\n");
fprintf(stderr, " -g seconds Grace period for authentication (default: 600)\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",
_PATH_HOST_KEY_FILE);
fprintf(stderr, " -u len Maximum hostname length for utmp recording\n");
fprintf(stderr, " -4 Use IPv4 only\n");
fprintf(stderr, " -6 Use IPv6 only\n");
exit(1);
} }
} }
SSLeay_add_all_algorithms(); SSLeay_add_all_algorithms();