version 1.5, 2000/10/09 21:32:34 |
version 1.5.2.3, 2001/03/21 19:46:22 |
|
|
* Author: Tatu Ylonen <ylo@cs.hut.fi> |
* Author: Tatu Ylonen <ylo@cs.hut.fi> |
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
* All rights reserved |
* All rights reserved |
* RSA-based authentication. This code determines whether to admit a login |
|
* based on RSA authentication. This file also contains functions to check |
|
* validity of the host key. |
|
* |
|
* As far as I am concerned, the code I have written for this software |
* As far as I am concerned, the code I have written for this software |
* can be used freely for any purpose. Any derived versions of this |
* can be used freely for any purpose. Any derived versions of this |
* software must be clearly marked as such, and if the derived work is |
* software must be clearly marked as such, and if the derived work is |
|
|
#include "includes.h" |
#include "includes.h" |
RCSID("$OpenBSD$"); |
RCSID("$OpenBSD$"); |
|
|
#include "ssh.h" |
|
#include "packet.h" |
#include "packet.h" |
#include "xmalloc.h" |
#include "xmalloc.h" |
#include "match.h" |
#include "match.h" |
|
#include "log.h" |
|
#include "canohost.h" |
|
#include "channels.h" |
|
#include "auth-options.h" |
|
#include "servconf.h" |
|
|
/* Flags set authorized_keys flags */ |
/* Flags set authorized_keys flags */ |
int no_port_forwarding_flag = 0; |
int no_port_forwarding_flag = 0; |
|
|
/* "environment=" options. */ |
/* "environment=" options. */ |
struct envstring *custom_environment = NULL; |
struct envstring *custom_environment = NULL; |
|
|
|
extern ServerOptions options; |
|
|
void |
void |
auth_clear_options(void) |
auth_clear_options(void) |
{ |
{ |
|
|
xfree(forced_command); |
xfree(forced_command); |
forced_command = NULL; |
forced_command = NULL; |
} |
} |
|
channel_clear_permitted_opens(); |
} |
} |
|
|
/* return 1 if access is granted, 0 if not. side effect: sets key option flags */ |
/* |
|
* return 1 if access is granted, 0 if not. |
|
* side effect: sets key option flags |
|
*/ |
int |
int |
auth_parse_options(struct passwd *pw, char *options, unsigned long linenum) |
auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum) |
{ |
{ |
const char *cp; |
const char *cp; |
if (!options) |
int i; |
return 1; |
|
|
|
/* reset options */ |
/* reset options */ |
auth_clear_options(); |
auth_clear_options(); |
|
|
while (*options && *options != ' ' && *options != '\t') { |
if (!opts) |
|
return 1; |
|
|
|
while (*opts && *opts != ' ' && *opts != '\t') { |
cp = "no-port-forwarding"; |
cp = "no-port-forwarding"; |
if (strncmp(options, cp, strlen(cp)) == 0) { |
if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
packet_send_debug("Port forwarding disabled."); |
packet_send_debug("Port forwarding disabled."); |
no_port_forwarding_flag = 1; |
no_port_forwarding_flag = 1; |
options += strlen(cp); |
opts += strlen(cp); |
goto next_option; |
goto next_option; |
} |
} |
cp = "no-agent-forwarding"; |
cp = "no-agent-forwarding"; |
if (strncmp(options, cp, strlen(cp)) == 0) { |
if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
packet_send_debug("Agent forwarding disabled."); |
packet_send_debug("Agent forwarding disabled."); |
no_agent_forwarding_flag = 1; |
no_agent_forwarding_flag = 1; |
options += strlen(cp); |
opts += strlen(cp); |
goto next_option; |
goto next_option; |
} |
} |
cp = "no-X11-forwarding"; |
cp = "no-X11-forwarding"; |
if (strncmp(options, cp, strlen(cp)) == 0) { |
if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
packet_send_debug("X11 forwarding disabled."); |
packet_send_debug("X11 forwarding disabled."); |
no_x11_forwarding_flag = 1; |
no_x11_forwarding_flag = 1; |
options += strlen(cp); |
opts += strlen(cp); |
goto next_option; |
goto next_option; |
} |
} |
cp = "no-pty"; |
cp = "no-pty"; |
if (strncmp(options, cp, strlen(cp)) == 0) { |
if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
packet_send_debug("Pty allocation disabled."); |
packet_send_debug("Pty allocation disabled."); |
no_pty_flag = 1; |
no_pty_flag = 1; |
options += strlen(cp); |
opts += strlen(cp); |
goto next_option; |
goto next_option; |
} |
} |
cp = "command=\""; |
cp = "command=\""; |
if (strncmp(options, cp, strlen(cp)) == 0) { |
if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
int i; |
opts += strlen(cp); |
options += strlen(cp); |
forced_command = xmalloc(strlen(opts) + 1); |
forced_command = xmalloc(strlen(options) + 1); |
|
i = 0; |
i = 0; |
while (*options) { |
while (*opts) { |
if (*options == '"') |
if (*opts == '"') |
break; |
break; |
if (*options == '\\' && options[1] == '"') { |
if (*opts == '\\' && opts[1] == '"') { |
options += 2; |
opts += 2; |
forced_command[i++] = '"'; |
forced_command[i++] = '"'; |
continue; |
continue; |
} |
} |
forced_command[i++] = *options++; |
forced_command[i++] = *opts++; |
} |
} |
if (!*options) { |
if (!*opts) { |
debug("%.100s, line %lu: missing end quote", |
debug("%.100s, line %lu: missing end quote", |
SSH_USER_PERMITTED_KEYS, linenum); |
file, linenum); |
packet_send_debug("%.100s, line %lu: missing end quote", |
packet_send_debug("%.100s, line %lu: missing end quote", |
SSH_USER_PERMITTED_KEYS, linenum); |
file, linenum); |
continue; |
xfree(forced_command); |
|
forced_command = NULL; |
|
goto bad_option; |
} |
} |
forced_command[i] = 0; |
forced_command[i] = 0; |
packet_send_debug("Forced command: %.900s", forced_command); |
packet_send_debug("Forced command: %.900s", forced_command); |
options++; |
opts++; |
goto next_option; |
goto next_option; |
} |
} |
cp = "environment=\""; |
cp = "environment=\""; |
if (strncmp(options, cp, strlen(cp)) == 0) { |
if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
int i; |
|
char *s; |
char *s; |
struct envstring *new_envstring; |
struct envstring *new_envstring; |
options += strlen(cp); |
|
s = xmalloc(strlen(options) + 1); |
opts += strlen(cp); |
|
s = xmalloc(strlen(opts) + 1); |
i = 0; |
i = 0; |
while (*options) { |
while (*opts) { |
if (*options == '"') |
if (*opts == '"') |
break; |
break; |
if (*options == '\\' && options[1] == '"') { |
if (*opts == '\\' && opts[1] == '"') { |
options += 2; |
opts += 2; |
s[i++] = '"'; |
s[i++] = '"'; |
continue; |
continue; |
} |
} |
s[i++] = *options++; |
s[i++] = *opts++; |
} |
} |
if (!*options) { |
if (!*opts) { |
debug("%.100s, line %lu: missing end quote", |
debug("%.100s, line %lu: missing end quote", |
SSH_USER_PERMITTED_KEYS, linenum); |
file, linenum); |
packet_send_debug("%.100s, line %lu: missing end quote", |
packet_send_debug("%.100s, line %lu: missing end quote", |
SSH_USER_PERMITTED_KEYS, linenum); |
file, linenum); |
continue; |
xfree(s); |
|
goto bad_option; |
} |
} |
s[i] = 0; |
s[i] = 0; |
packet_send_debug("Adding to environment: %.900s", s); |
packet_send_debug("Adding to environment: %.900s", s); |
debug("Adding to environment: %.900s", s); |
debug("Adding to environment: %.900s", s); |
options++; |
opts++; |
new_envstring = xmalloc(sizeof(struct envstring)); |
new_envstring = xmalloc(sizeof(struct envstring)); |
new_envstring->s = s; |
new_envstring->s = s; |
new_envstring->next = custom_environment; |
new_envstring->next = custom_environment; |
|
|
goto next_option; |
goto next_option; |
} |
} |
cp = "from=\""; |
cp = "from=\""; |
if (strncmp(options, cp, strlen(cp)) == 0) { |
if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
int mname, mip; |
int mname, mip; |
char *patterns = xmalloc(strlen(options) + 1); |
const char *remote_ip = get_remote_ipaddr(); |
int i; |
const char *remote_host = get_canonical_hostname( |
options += strlen(cp); |
options.reverse_mapping_check); |
|
char *patterns = xmalloc(strlen(opts) + 1); |
|
|
|
opts += strlen(cp); |
i = 0; |
i = 0; |
while (*options) { |
while (*opts) { |
if (*options == '"') |
if (*opts == '"') |
break; |
break; |
if (*options == '\\' && options[1] == '"') { |
if (*opts == '\\' && opts[1] == '"') { |
options += 2; |
opts += 2; |
patterns[i++] = '"'; |
patterns[i++] = '"'; |
continue; |
continue; |
} |
} |
patterns[i++] = *options++; |
patterns[i++] = *opts++; |
} |
} |
if (!*options) { |
if (!*opts) { |
debug("%.100s, line %lu: missing end quote", |
debug("%.100s, line %lu: missing end quote", |
SSH_USER_PERMITTED_KEYS, linenum); |
file, linenum); |
packet_send_debug("%.100s, line %lu: missing end quote", |
packet_send_debug("%.100s, line %lu: missing end quote", |
SSH_USER_PERMITTED_KEYS, linenum); |
file, linenum); |
continue; |
xfree(patterns); |
|
goto bad_option; |
} |
} |
patterns[i] = 0; |
patterns[i] = 0; |
options++; |
opts++; |
/* |
/* |
* Deny access if we get a negative |
* Deny access if we get a negative |
* match for the hostname or the ip |
* match for the hostname or the ip |
* or if we get not match at all |
* or if we get not match at all |
*/ |
*/ |
mname = match_hostname(get_canonical_hostname(), |
mname = match_hostname(remote_host, patterns, |
patterns, strlen(patterns)); |
strlen(patterns)); |
mip = match_hostname(get_remote_ipaddr(), |
mip = match_hostname(remote_ip, patterns, |
patterns, strlen(patterns)); |
strlen(patterns)); |
xfree(patterns); |
xfree(patterns); |
if (mname == -1 || mip == -1 || |
if (mname == -1 || mip == -1 || |
(mname != 1 && mip != 1)) { |
(mname != 1 && mip != 1)) { |
log("Authentication tried for %.100s with correct key but not from a permitted host (host=%.200s, ip=%.200s).", |
log("Authentication tried for %.100s with " |
pw->pw_name, get_canonical_hostname(), |
"correct key but not from a permitted " |
get_remote_ipaddr()); |
"host (host=%.200s, ip=%.200s).", |
packet_send_debug("Your host '%.200s' is not permitted to use this key for login.", |
pw->pw_name, remote_host, remote_ip); |
get_canonical_hostname()); |
packet_send_debug("Your host '%.200s' is not " |
|
"permitted to use this key for login.", |
|
remote_host); |
/* deny access */ |
/* deny access */ |
return 0; |
return 0; |
} |
} |
/* Host name matches. */ |
/* Host name matches. */ |
goto next_option; |
goto next_option; |
} |
} |
|
cp = "permitopen=\""; |
|
if (strncasecmp(opts, cp, strlen(cp)) == 0) { |
|
u_short port; |
|
char *c, *ep; |
|
char *patterns = xmalloc(strlen(opts) + 1); |
|
|
|
opts += strlen(cp); |
|
i = 0; |
|
while (*opts) { |
|
if (*opts == '"') |
|
break; |
|
if (*opts == '\\' && opts[1] == '"') { |
|
opts += 2; |
|
patterns[i++] = '"'; |
|
continue; |
|
} |
|
patterns[i++] = *opts++; |
|
} |
|
if (!*opts) { |
|
debug("%.100s, line %lu: missing end quote", |
|
file, linenum); |
|
packet_send_debug("%.100s, line %lu: missing end quote", |
|
file, linenum); |
|
xfree(patterns); |
|
goto bad_option; |
|
} |
|
patterns[i] = 0; |
|
opts++; |
|
c = strchr(patterns, ':'); |
|
if (c == NULL) { |
|
debug("%.100s, line %lu: permitopen: missing colon <%.100s>", |
|
file, linenum, patterns); |
|
packet_send_debug("%.100s, line %lu: missing colon", |
|
file, linenum); |
|
xfree(patterns); |
|
goto bad_option; |
|
} |
|
*c = 0; |
|
c++; |
|
port = strtol(c, &ep, 0); |
|
if (c == ep) { |
|
debug("%.100s, line %lu: permitopen: missing port <%.100s>", |
|
file, linenum, patterns); |
|
packet_send_debug("%.100s, line %lu: missing port", |
|
file, linenum); |
|
xfree(patterns); |
|
goto bad_option; |
|
} |
|
if (options.allow_tcp_forwarding) |
|
channel_add_permitted_opens(patterns, port); |
|
xfree(patterns); |
|
goto next_option; |
|
} |
next_option: |
next_option: |
/* |
/* |
* Skip the comma, and move to the next option |
* Skip the comma, and move to the next option |
* (or break out if there are no more). |
* (or break out if there are no more). |
*/ |
*/ |
if (!*options) |
if (!*opts) |
fatal("Bugs in auth-options.c option processing."); |
fatal("Bugs in auth-options.c option processing."); |
if (*options == ' ' || *options == '\t') |
if (*opts == ' ' || *opts == '\t') |
break; /* End of options. */ |
break; /* End of options. */ |
if (*options != ',') |
if (*opts != ',') |
goto bad_option; |
goto bad_option; |
options++; |
opts++; |
/* Process the next option. */ |
/* Process the next option. */ |
} |
} |
/* grant access */ |
/* grant access */ |
|
|
|
|
bad_option: |
bad_option: |
log("Bad options in %.100s file, line %lu: %.50s", |
log("Bad options in %.100s file, line %lu: %.50s", |
SSH_USER_PERMITTED_KEYS, linenum, options); |
file, linenum, opts); |
packet_send_debug("Bad options in %.100s file, line %lu: %.50s", |
packet_send_debug("Bad options in %.100s file, line %lu: %.50s", |
SSH_USER_PERMITTED_KEYS, linenum, options); |
file, linenum, opts); |
/* deny access */ |
/* deny access */ |
return 0; |
return 0; |
} |
} |