Resolve conflicts and update for OpenSSH 2.2.0

Reviewed by:	gshapiro, peter, green
This commit is contained in:
kris 2000-09-10 09:35:38 +00:00
parent d345e9b7aa
commit 71b51dc832
37 changed files with 2392 additions and 1657 deletions

View File

@ -1,8 +1,25 @@
/*
* Dug Song <dugsong@UMICH.EDU>
* Kerberos v4 authentication and ticket-passing routines.
*
* $FreeBSD$
* Copyright (c) 1999 Dug Song. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
@ -11,6 +28,9 @@
#include "ssh.h"
#include "servconf.h"
RCSID("$OpenBSD: auth-krb4.c,v 1.18 2000/09/07 20:27:49 deraadt Exp $");
RCSID("$FreeBSD$");
#ifdef KRB4
char *ticket = NULL;
@ -82,11 +102,12 @@ auth_krb4_password(struct passwd * pw, const char *password)
if (r == RD_AP_UNDEC) {
/*
* Probably didn't have a srvtab on
* localhost. Allow login.
* localhost. Disallow login.
*/
log("Kerberos V4 TGT for %s unverifiable, "
"no srvtab installed? krb_rd_req: %s",
pw->pw_name, krb_err_txt[r]);
goto kerberos_auth_failure;
} else if (r != KSUCCESS) {
log("Kerberos V4 %s ticket unverifiable: %s",
KRB4_SERVICE_NAME, krb_err_txt[r]);
@ -94,12 +115,13 @@ auth_krb4_password(struct passwd * pw, const char *password)
}
} 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("Kerberos V4 TGT for %s unverifiable: %s; %s.%s "
"not registered, or srvtab is wrong?", pw->pw_name,
krb_err_txt[r], KRB4_SERVICE_NAME, phost);
goto kerberos_auth_failure;
} else {
/*
* TGT is bad, forget it. Possibly spoofed!
@ -152,7 +174,7 @@ krb4_init(uid_t uid)
if (lstat("/ticket", &st) != -1)
tkt_root = "/ticket/";
#endif /* AFS */
snprintf(ticket, MAXPATHLEN, "%s%d_%d", tkt_root, uid, getpid());
snprintf(ticket, MAXPATHLEN, "%s%u_%d", tkt_root, uid, getpid());
(void) krb_set_tkt_string(ticket);
}
/* Register ticket cleanup in case of fatal error. */

View File

@ -2,15 +2,65 @@
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Created: Sat Mar 18 05:11:38 1995 ylo
* Password authentication. This file contains the functions to check whether
* the password is valid for the user.
*
* $FreeBSD$
*
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
*
* Copyright (c) 1999 Dug Song. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$Id: auth-passwd.c,v 1.15 2000/04/14 10:30:29 markus Exp $");
RCSID("$OpenBSD: auth-passwd.c,v 1.17 2000/09/07 20:27:49 deraadt Exp $");
RCSID("$FreeBSD$");
#include "packet.h"
#include "ssh.h"
@ -21,7 +71,7 @@ RCSID("$Id: auth-passwd.c,v 1.15 2000/04/14 10:30:29 markus Exp $");
* Tries to authenticate the user using password. Returns true if
* authentication succeeds.
*/
int
int
auth_password(struct passwd * pw, const char *password)
{
extern ServerOptions options;

View File

@ -1,22 +1,20 @@
/*
*
* auth-rh-rsa.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Sun May 7 03:08:06 1995 ylo
*
* Rhosts or /etc/hosts.equiv authentication combined with RSA host
* authentication.
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
RCSID("$Id: auth-rh-rsa.c,v 1.13 2000/04/14 10:30:29 markus Exp $");
RCSID("$OpenBSD: auth-rh-rsa.c,v 1.16 2000/09/07 21:13:36 markus Exp $");
RCSID("$FreeBSD$");
#include "packet.h"
#include "ssh.h"

View File

@ -1,23 +1,21 @@
/*
*
* auth-rsa.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Mon Mar 27 01:46:52 1995 ylo
*
* 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.
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
RCSID("$Id: auth-rsa.c,v 1.23 2000/04/29 18:11:51 markus Exp $");
RCSID("$OpenBSD: auth-rsa.c,v 1.29 2000/09/07 21:13:36 markus Exp $");
RCSID("$FreeBSD$");
#include "rsa.h"
#include "packet.h"
@ -27,18 +25,11 @@ RCSID("$Id: auth-rsa.c,v 1.23 2000/04/29 18:11:51 markus Exp $");
#include "uidswap.h"
#include "match.h"
#include "servconf.h"
#include "auth-options.h"
#include <openssl/rsa.h>
#include <openssl/md5.h>
/* Flags that may be set in authorized_keys options. */
extern int no_port_forwarding_flag;
extern int no_agent_forwarding_flag;
extern int no_x11_forwarding_flag;
extern int no_pty_flag;
extern char *forced_command;
extern struct envstring *custom_environment;
/*
* Session identifier that is used to bind key exchange and authentication
* responses to a particular session.
@ -187,8 +178,8 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
}
if (fail) {
fclose(f);
log(buf);
packet_send_debug(buf);
log("%s",buf);
packet_send_debug("%s",buf);
restore_uid();
return 0;
}
@ -269,188 +260,10 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
* authenticated. Note that we have not yet processed the
* options; this will be reset if the options cause the
* authentication to be rejected.
*/
authenticated = 1;
/* RSA part of authentication was accepted. Now process the options. */
if (options) {
while (*options && *options != ' ' && *options != '\t') {
cp = "no-port-forwarding";
if (strncmp(options, cp, strlen(cp)) == 0) {
packet_send_debug("Port forwarding disabled.");
no_port_forwarding_flag = 1;
options += strlen(cp);
goto next_option;
}
cp = "no-agent-forwarding";
if (strncmp(options, cp, strlen(cp)) == 0) {
packet_send_debug("Agent forwarding disabled.");
no_agent_forwarding_flag = 1;
options += strlen(cp);
goto next_option;
}
cp = "no-X11-forwarding";
if (strncmp(options, cp, strlen(cp)) == 0) {
packet_send_debug("X11 forwarding disabled.");
no_x11_forwarding_flag = 1;
options += strlen(cp);
goto next_option;
}
cp = "no-pty";
if (strncmp(options, cp, strlen(cp)) == 0) {
packet_send_debug("Pty allocation disabled.");
no_pty_flag = 1;
options += strlen(cp);
goto next_option;
}
cp = "command=\"";
if (strncmp(options, cp, strlen(cp)) == 0) {
int i;
options += strlen(cp);
forced_command = xmalloc(strlen(options) + 1);
i = 0;
while (*options) {
if (*options == '"')
break;
if (*options == '\\' && options[1] == '"') {
options += 2;
forced_command[i++] = '"';
continue;
}
forced_command[i++] = *options++;
}
if (!*options) {
debug("%.100s, line %lu: missing end quote",
SSH_USER_PERMITTED_KEYS, linenum);
packet_send_debug("%.100s, line %lu: missing end quote",
SSH_USER_PERMITTED_KEYS, linenum);
continue;
}
forced_command[i] = 0;
packet_send_debug("Forced command: %.900s", forced_command);
options++;
goto next_option;
}
cp = "environment=\"";
if (strncmp(options, cp, strlen(cp)) == 0) {
int i;
char *s;
struct envstring *new_envstring;
options += strlen(cp);
s = xmalloc(strlen(options) + 1);
i = 0;
while (*options) {
if (*options == '"')
break;
if (*options == '\\' && options[1] == '"') {
options += 2;
s[i++] = '"';
continue;
}
s[i++] = *options++;
}
if (!*options) {
debug("%.100s, line %lu: missing end quote",
SSH_USER_PERMITTED_KEYS, linenum);
packet_send_debug("%.100s, line %lu: missing end quote",
SSH_USER_PERMITTED_KEYS, linenum);
continue;
}
s[i] = 0;
packet_send_debug("Adding to environment: %.900s", s);
debug("Adding to environment: %.900s", s);
options++;
new_envstring = xmalloc(sizeof(struct envstring));
new_envstring->s = s;
new_envstring->next = custom_environment;
custom_environment = new_envstring;
goto next_option;
}
cp = "from=\"";
if (strncmp(options, cp, strlen(cp)) == 0) {
char *patterns = xmalloc(strlen(options) + 1);
int i;
options += strlen(cp);
i = 0;
while (*options) {
if (*options == '"')
break;
if (*options == '\\' && options[1] == '"') {
options += 2;
patterns[i++] = '"';
continue;
}
patterns[i++] = *options++;
}
if (!*options) {
debug("%.100s, line %lu: missing end quote",
SSH_USER_PERMITTED_KEYS, linenum);
packet_send_debug("%.100s, line %lu: missing end quote",
SSH_USER_PERMITTED_KEYS, linenum);
continue;
}
patterns[i] = 0;
options++;
if (!match_hostname(get_canonical_hostname(), patterns,
strlen(patterns)) &&
!match_hostname(get_remote_ipaddr(), patterns,
strlen(patterns))) {
log("RSA authentication tried for %.100s with correct key but not from a permitted host (host=%.200s, ip=%.200s).",
pw->pw_name, get_canonical_hostname(),
get_remote_ipaddr());
packet_send_debug("Your host '%.200s' is not permitted to use this key for login.",
get_canonical_hostname());
xfree(patterns);
/* key invalid for this host, reset flags */
authenticated = 0;
no_agent_forwarding_flag = 0;
no_port_forwarding_flag = 0;
no_pty_flag = 0;
no_x11_forwarding_flag = 0;
while (custom_environment) {
struct envstring *ce = custom_environment;
custom_environment = ce->next;
xfree(ce->s);
xfree(ce);
}
if (forced_command) {
xfree(forced_command);
forced_command = NULL;
}
break;
}
xfree(patterns);
/* Host name matches. */
goto next_option;
}
bad_option:
log("Bad options in %.100s file, line %lu: %.50s",
SSH_USER_PERMITTED_KEYS, linenum, options);
packet_send_debug("Bad options in %.100s file, line %lu: %.50s",
SSH_USER_PERMITTED_KEYS, linenum, options);
authenticated = 0;
break;
next_option:
/*
* Skip the comma, and move to the next option
* (or break out if there are no more).
*/
if (!*options)
fatal("Bugs in auth-rsa.c option processing.");
if (*options == ' ' || *options == '\t')
break; /* End of options. */
if (*options != ',')
goto bad_option;
options++;
/* Process the next option. */
continue;
}
}
/*
* Break out of the loop if authentication was successful;
* otherwise continue searching.
*/
authenticated = auth_parse_options(pw, options, linenum);
if (authenticated)
break;
}

View File

@ -1,7 +1,30 @@
/* $FreeBSD$ */
/*
* Copyright (c) 1999,2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$Id: auth-skey.c,v 1.6 2000/04/14 10:30:29 markus Exp $");
RCSID("$OpenBSD: auth-skey.c,v 1.8 2000/09/07 20:27:49 deraadt Exp $");
RCSID("$FreeBSD$");
#include <sys/sysctl.h>
#include "ssh.h"
@ -112,7 +135,7 @@ skey_fake_keyinfo(char *username)
mib[0] = CTL_KERN;
mib[1] = KERN_BOOTTIME;
size = sizeof(boottime);
bzero(&boottime, sizeof(boottime));
bzero(&boottime, size);
if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 &&
boottime.tv_sec != 0) {
secret = (char *)&boottime;

View File

@ -1,13 +1,40 @@
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* $FreeBSD$
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: auth.c,v 1.7 2000/05/17 21:37:24 deraadt Exp $");
RCSID("$OpenBSD: auth.c,v 1.10 2000/09/07 21:13:36 markus Exp $");
RCSID("$FreeBSD$");
#include "xmalloc.h"
#include "rsa.h"
@ -26,12 +53,9 @@ RCSID("$OpenBSD: auth.c,v 1.7 2000/05/17 21:37:24 deraadt Exp $");
#include "ssh2.h"
#include "auth.h"
#include "session.h"
#include "dispatch.h"
/* import */
extern ServerOptions options;
extern char *forced_command;
/*
* Check if the user is allowed to log in via ssh. If user is listed in
@ -115,16 +139,6 @@ allowed_user(struct passwd * pw)
return 0;
}
}
#ifndef __FreeBSD__ /* FreeBSD handle it later */
/* Fail if the account's expiration time has passed. */
if (pw->pw_expire != 0) {
struct timeval tv;
(void)gettimeofday(&tv, NULL);
if (tv.tv_sec >= pw->pw_expire)
return 0;
}
#endif /* !__FreeBSD__ */
/* We found no reason not to let this user try to log on... */
return 1;
}

View File

@ -2,11 +2,16 @@
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
RCSID("$OpenBSD: auth1.c,v 1.2 2000/04/29 18:11:52 markus Exp $");
RCSID("$OpenBSD: auth1.c,v 1.4 2000/09/07 20:27:49 deraadt Exp $");
RCSID("$FreeBSD$");
#include "xmalloc.h"
#include "rsa.h"
@ -148,15 +153,15 @@ do_authloop(struct passwd * pw)
unsigned int ulen;
int type = 0;
void (*authlog) (const char *fmt,...) = verbose;
#ifdef LOGIN_CAP
#ifdef HAVE_LOGIN_CAP
login_cap_t *lc;
#endif /* LOGIN_CAP */
#if defined(LOGIN_CAP) || defined(LOGIN_ACCESS)
#endif /* HAVE_LOGIN_CAP */
#if defined(HAVE_LOGIN_CAP) || defined(LOGIN_ACCESS)
const char *from_host, *from_ip;
from_host = get_canonical_hostname();
from_ip = get_remote_ipaddr();
#endif /* LOGIN_CAP || LOGIN_ACCESS */
#endif /* HAVE_LOGIN_CAP || LOGIN_ACCESS */
#ifdef HAVE_LIBPAM
int pam_retval;
#endif /* HAVE_LIBPAM */
@ -452,7 +457,7 @@ do_authloop(struct passwd * pw)
}
}
#ifdef LOGIN_CAP
#ifdef HAVE_LOGIN_CAP
lc = login_getpwclass(pw);
if (lc == NULL)
lc = login_getclassbyname(NULL, pw);
@ -467,7 +472,7 @@ do_authloop(struct passwd * pw)
packet_disconnect("Logins not available right now.");
}
login_close(lc);
#endif /* LOGIN_CAP */
#endif /* HAVE_LOGIN_CAP */
#ifdef LOGIN_ACCESS
if (!login_access(pw->pw_name, from_host)) {
log("Denied connection for %.200s from %.200s [%.200s].",
@ -548,6 +553,7 @@ do_authentication()
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
pwcopy.pw_uid = pw->pw_uid;
pwcopy.pw_gid = pw->pw_gid;
pwcopy.pw_class = xstrdup(pw->pw_class);
pwcopy.pw_dir = xstrdup(pw->pw_dir);
pwcopy.pw_shell = xstrdup(pw->pw_shell);
pwcopy.pw_class = xstrdup(pw->pw_class);

View File

@ -9,11 +9,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Markus Friedl.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@ -25,11 +20,11 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#include "includes.h"
RCSID("$OpenBSD: auth2.c,v 1.8 2000/05/08 17:42:24 markus Exp $");
RCSID("$OpenBSD: auth2.c,v 1.14 2000/09/07 20:27:49 deraadt Exp $");
RCSID("$FreeBSD$");
#include <openssl/dsa.h>
#include <openssl/rsa.h>
@ -56,6 +51,7 @@ RCSID("$OpenBSD: auth2.c,v 1.8 2000/05/08 17:42:24 markus Exp $");
#include "dsa.h"
#include "uidswap.h"
#include "auth-options.h"
/* import */
extern ServerOptions options;
@ -71,7 +67,7 @@ void protocol_error(int type, int plen);
/* auth */
int ssh2_auth_none(struct passwd *pw);
int ssh2_auth_password(struct passwd *pw);
int ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen);
int ssh2_auth_pubkey(struct passwd *pw, char *service);
/* helper */
struct passwd* auth_set_user(char *u, char *s);
@ -152,17 +148,14 @@ input_userauth_request(int type, int plen)
{
static void (*authlog) (const char *fmt,...) = verbose;
static int attempt = 0;
unsigned int len, rlen;
unsigned int len;
int authenticated = 0;
char *raw, *user, *service, *method, *authmsg = NULL;
char *user, *service, *method, *authmsg = NULL;
struct passwd *pw;
if (++attempt == AUTH_FAIL_MAX)
packet_disconnect("too many failed userauth_requests");
raw = packet_get_raw(&rlen);
if (plen != rlen)
fatal("plen != rlen");
user = packet_get_string(&len);
service = packet_get_string(&len);
method = packet_get_string(&len);
@ -176,7 +169,7 @@ input_userauth_request(int type, int plen)
} else if (strcmp(method, "password") == 0) {
authenticated = ssh2_auth_password(pw);
} else if (strcmp(method, "publickey") == 0) {
authenticated = ssh2_auth_pubkey(pw, raw, rlen);
authenticated = ssh2_auth_pubkey(pw, service);
}
}
if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
@ -254,7 +247,7 @@ ssh2_auth_password(struct passwd *pw)
return authenticated;
}
int
ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen)
ssh2_auth_pubkey(struct passwd *pw, char *service)
{
Buffer b;
Key *key;
@ -267,10 +260,6 @@ ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen)
debug("pubkey auth disabled");
return 0;
}
if (datafellows & SSH_BUG_PUBKEYAUTH) {
log("bug compatibility with ssh-2.0.13 pubkey not implemented");
return 0;
}
have_sig = packet_get_char();
pkalg = packet_get_string(&alen);
if (strcmp(pkalg, KEX_DSS) != 0) {
@ -285,11 +274,22 @@ ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen)
sig = packet_get_string(&slen);
packet_done();
buffer_init(&b);
buffer_append(&b, session_id2, session_id2_len);
if (datafellows & SSH_COMPAT_SESSIONID_ENCODING) {
buffer_put_string(&b, session_id2, session_id2_len);
} else {
buffer_append(&b, session_id2, session_id2_len);
}
/* reconstruct packet */
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
if (slen + 4 > rlen)
fatal("bad rlen/slen");
buffer_append(&b, raw, rlen - slen - 4);
buffer_put_cstring(&b, pw->pw_name);
buffer_put_cstring(&b,
datafellows & SSH_BUG_PUBKEYAUTH ?
"ssh-userauth" :
service);
buffer_put_cstring(&b, "publickey");
buffer_put_char(&b, have_sig);
buffer_put_cstring(&b, KEX_DSS);
buffer_put_string(&b, pkblob, blen);
#ifdef DEBUG_DSS
buffer_dump(&b);
#endif
@ -357,6 +357,7 @@ auth_set_user(char *u, char *s)
copy->pw_passwd = xstrdup(pw->pw_passwd);
copy->pw_uid = pw->pw_uid;
copy->pw_gid = pw->pw_gid;
copy->pw_class = xstrdup(pw->pw_class);
copy->pw_dir = xstrdup(pw->pw_dir);
copy->pw_shell = xstrdup(pw->pw_shell);
copy->pw_class = xstrdup(pw->pw_class);
@ -438,8 +439,8 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
}
}
if (fail) {
log(buf);
fclose(f);
log("%s",buf);
restore_uid();
return 0;
}
@ -448,17 +449,36 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
found = key_new(KEY_DSA);
while (fgets(line, sizeof(line), f)) {
char *cp;
char *cp, *options = NULL;
linenum++;
/* Skip leading whitespace, empty and comment lines. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
if (!*cp || *cp == '\n' || *cp == '#')
continue;
bits = key_read(found, &cp);
if (bits == 0)
continue;
if (key_equal(found, key)) {
if (bits == 0) {
/* no key? check if there are options for this key */
int quoted = 0;
options = cp;
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
if (*cp == '\\' && cp[1] == '"')
cp++; /* Skip both */
else if (*cp == '"')
quoted = !quoted;
}
/* Skip remaining whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
bits = key_read(found, &cp);
if (bits == 0) {
/* still no key? advance to next line*/
continue;
}
}
if (key_equal(found, key) &&
auth_parse_options(pw, options, linenum) == 1) {
found_key = 1;
debug("matching key found: file %s, line %ld",
file, linenum);

View File

@ -1,31 +1,60 @@
/*
*
* authfd.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Wed Mar 29 01:30:28 1995 ylo
*
* Functions for connecting the local authentication agent.
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* SSH2 implementation,
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$Id: authfd.c,v 1.19 2000/04/29 18:11:52 markus Exp $");
RCSID("$OpenBSD: authfd.c,v 1.27 2000/09/07 20:27:49 deraadt Exp $");
RCSID("$FreeBSD$");
#include "ssh.h"
#include "rsa.h"
#include "authfd.h"
#include "buffer.h"
#include "bufaux.h"
#include "xmalloc.h"
#include "getput.h"
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/evp.h>
#include "key.h"
#include "authfd.h"
#include "kex.h"
#include "dsa.h"
/* helper */
int decode_reply(int type);
/* Returns the number of the authentication fd, or -1 if there is none. */
@ -60,6 +89,59 @@ ssh_get_authentication_socket()
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
* obtained). The argument must have been returned by
@ -98,7 +180,6 @@ ssh_get_authentication_connection()
auth = xmalloc(sizeof(*auth));
auth->fd = sock;
buffer_init(&auth->packet);
buffer_init(&auth->identities);
auth->howmany = 0;
@ -111,121 +192,108 @@ ssh_get_authentication_connection()
*/
void
ssh_close_authentication_connection(AuthenticationConnection *ac)
ssh_close_authentication_connection(AuthenticationConnection *auth)
{
buffer_free(&ac->packet);
buffer_free(&ac->identities);
close(ac->fd);
xfree(ac);
buffer_free(&auth->identities);
close(auth->fd);
xfree(auth);
}
/*
* Returns the first authentication identity held by the agent.
* Returns true if an identity is available, 0 otherwise.
* The caller must initialize the integers before the call, and free the
* comment after a successful call (before calling ssh_get_next_identity).
*/
int
ssh_get_first_identity(AuthenticationConnection *auth,
BIGNUM *e, BIGNUM *n, char **comment)
Key *
ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version)
{
unsigned char msg[8192];
int len, l;
int type, code1 = 0, code2 = 0;
Buffer request;
switch(version){
case 1:
code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER;
break;
case 2:
code1 = SSH2_AGENTC_REQUEST_IDENTITIES;
code2 = SSH2_AGENT_IDENTITIES_ANSWER;
break;
default:
return NULL;
}
/*
* Send a message to the agent requesting for a list of the
* identities it can represent.
*/
msg[0] = 0;
msg[1] = 0;
msg[2] = 0;
msg[3] = 1;
msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
if (atomicio(write, auth->fd, msg, 5) != 5) {
error("write auth->fd: %.100s", strerror(errno));
return 0;
}
/* Read the length of the response. XXX implement timeouts here. */
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;
}
buffer_init(&request);
buffer_put_char(&request, code1);
/*
* 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;
if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
buffer_free(&request);
return NULL;
}
buffer_free(&request);
/* Get message type, and verify that we got a proper answer. */
buffer_get(&auth->identities, (char *) msg, 1);
if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)
fatal("Bad authentication reply message type: %d", msg[0]);
type = buffer_get_char(&auth->identities);
if (type == SSH_AGENT_FAILURE) {
return NULL;
} else if (type != code2) {
fatal("Bad authentication reply message type: %d", type);
}
/* Get the number of entries in the response and check it for sanity. */
auth->howmany = buffer_get_int(&auth->identities);
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 ssh_get_next_identity(auth, e, n, comment);
return ssh_get_next_identity(auth, comment, version);
}
/*
* Returns the next authentication identity for the agent. Other functions
* can be called between this and ssh_get_first_identity or two calls of this
* function. This returns 0 if there are no more identities. The caller
* must free comment after a successful return.
*/
int
ssh_get_next_identity(AuthenticationConnection *auth,
BIGNUM *e, BIGNUM *n, char **comment)
Key *
ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version)
{
unsigned int bits;
unsigned char *blob;
unsigned int blen;
Key *key = NULL;
/* Return failure if no more entries. */
if (auth->howmany <= 0)
return 0;
return NULL;
/*
* Get the next entry from the packet. These will abort with a fatal
* error if the packet is too short or contains corrupt data.
*/
bits = buffer_get_int(&auth->identities);
buffer_get_bignum(&auth->identities, e);
buffer_get_bignum(&auth->identities, n);
*comment = buffer_get_string(&auth->identities, NULL);
if (bits != BN_num_bits(n))
log("Warning: identity keysize mismatch: actual %d, announced %u",
BN_num_bits(n), bits);
switch(version){
case 1:
key = key_new(KEY_RSA);
bits = buffer_get_int(&auth->identities);
buffer_get_bignum(&auth->identities, key->rsa->e);
buffer_get_bignum(&auth->identities, key->rsa->n);
*comment = buffer_get_string(&auth->identities, NULL);
if (bits != BN_num_bits(key->rsa->n))
log("Warning: identity keysize mismatch: actual %d, announced %u",
BN_num_bits(key->rsa->n), bits);
break;
case 2:
blob = buffer_get_string(&auth->identities, &blen);
*comment = buffer_get_string(&auth->identities, NULL);
key = dsa_key_from_blob(blob, blen);
xfree(blob);
break;
default:
return NULL;
break;
}
/* Decrement the number of remaining entries. */
auth->howmany--;
return 1;
return key;
}
/*
@ -238,101 +306,124 @@ ssh_get_next_identity(AuthenticationConnection *auth,
int
ssh_decrypt_challenge(AuthenticationConnection *auth,
BIGNUM* e, BIGNUM *n, BIGNUM *challenge,
unsigned char session_id[16],
unsigned int response_type,
unsigned char response[16])
Key* key, BIGNUM *challenge,
unsigned char session_id[16],
unsigned int response_type,
unsigned char response[16])
{
Buffer buffer;
unsigned char buf[8192];
int len, l, i;
int success = 0;
int i;
int type;
/* Response type 0 is no longer supported. */
if (response_type == 0)
fatal("Compatibility with ssh protocol version 1.0 no longer supported.");
/* Format a message to the agent. */
buf[0] = SSH_AGENTC_RSA_CHALLENGE;
if (key->type != KEY_RSA)
return 0;
if (response_type == 0) {
log("Compatibility with ssh protocol version 1.0 no longer supported.");
return 0;
}
buffer_init(&buffer);
buffer_append(&buffer, (char *) buf, 1);
buffer_put_int(&buffer, BN_num_bits(n));
buffer_put_bignum(&buffer, e);
buffer_put_bignum(&buffer, n);
buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE);
buffer_put_int(&buffer, BN_num_bits(key->rsa->n));
buffer_put_bignum(&buffer, key->rsa->e);
buffer_put_bignum(&buffer, key->rsa->n);
buffer_put_bignum(&buffer, challenge);
buffer_append(&buffer, (char *) session_id, 16);
buffer_put_int(&buffer, response_type);
/* 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.");
error_cleanup:
if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
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;
}
type = buffer_get_char(&buffer);
/* 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 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) {
if (type == SSH_AGENT_FAILURE) {
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);
return success;
}
/* Correct answer. */
return 1;
/* ask agent to sign data, returns -1 on error, 0 on success */
int
ssh_agent_sign(AuthenticationConnection *auth,
Key *key,
unsigned char **sigp, int *lenp,
unsigned char *data, int datalen)
{
Buffer msg;
unsigned char *blob;
unsigned int blen;
int type;
int ret = -1;
if (dsa_make_key_blob(key, &blob, &blen) == 0)
return -1;
buffer_init(&msg);
buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST);
buffer_put_string(&msg, blob, blen);
buffer_put_string(&msg, data, datalen);
buffer_put_int(&msg, 0); /* flags, unused */
xfree(blob);
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
return -1;
}
type = buffer_get_char(&msg);
if (type == SSH_AGENT_FAILURE) {
log("Agent admitted failure to sign using the key.");
} else if (type != SSH2_AGENT_SIGN_RESPONSE) {
fatal("Bad authentication response: %d", type);
} else {
ret = 0;
*sigp = buffer_get_string(&msg, lenp);
}
buffer_free(&msg);
return ret;
}
/* Encode key for a message to the agent. */
void
ssh_encode_identity_rsa(Buffer *b, RSA *key, const char *comment)
{
buffer_clear(b);
buffer_put_char(b, SSH_AGENTC_ADD_RSA_IDENTITY);
buffer_put_int(b, BN_num_bits(key->n));
buffer_put_bignum(b, key->n);
buffer_put_bignum(b, key->e);
buffer_put_bignum(b, key->d);
/* To keep within the protocol: p < q for ssh. in SSL p > q */
buffer_put_bignum(b, key->iqmp); /* ssh key->u */
buffer_put_bignum(b, key->q); /* ssh key->p, SSL key->q */
buffer_put_bignum(b, key->p); /* ssh key->q, SSL key->p */
buffer_put_string(b, comment, strlen(comment));
}
void
ssh_encode_identity_dsa(Buffer *b, DSA *key, const char *comment)
{
buffer_clear(b);
buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY);
buffer_put_cstring(b, KEX_DSS);
buffer_put_bignum2(b, key->p);
buffer_put_bignum2(b, key->q);
buffer_put_bignum2(b, key->g);
buffer_put_bignum2(b, key->pub_key);
buffer_put_bignum2(b, key->priv_key);
buffer_put_string(b, comment, strlen(comment));
}
/*
@ -341,86 +432,32 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
*/
int
ssh_add_identity(AuthenticationConnection *auth,
RSA * key, const char *comment)
ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
{
Buffer buffer;
unsigned char buf[8192];
int len, l, type;
Buffer msg;
int type;
/* Format a message to the agent. */
buffer_init(&buffer);
buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);
buffer_put_int(&buffer, BN_num_bits(key->n));
buffer_put_bignum(&buffer, key->n);
buffer_put_bignum(&buffer, key->e);
buffer_put_bignum(&buffer, key->d);
/* To keep within the protocol: p < q for ssh. in SSL p > q */
buffer_put_bignum(&buffer, key->iqmp); /* ssh key->u */
buffer_put_bignum(&buffer, key->q); /* ssh key->p, SSL key->q */
buffer_put_bignum(&buffer, key->p); /* ssh key->q, SSL key->p */
buffer_put_string(&buffer, comment, strlen(comment));
buffer_init(&msg);
/* 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.");
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;
switch (key->type) {
case KEY_RSA:
ssh_encode_identity_rsa(&msg, key->rsa, comment);
break;
case KEY_DSA:
ssh_encode_identity_dsa(&msg, key->dsa, comment);
break;
default:
fatal("Bad response to add identity from authentication agent: %d",
type);
buffer_free(&msg);
return 0;
break;
}
/* NOTREACHED */
return 0;
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
return 0;
}
type = buffer_get_char(&msg);
buffer_free(&msg);
return decode_reply(type);
}
/*
@ -429,81 +466,36 @@ ssh_add_identity(AuthenticationConnection *auth,
*/
int
ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
ssh_remove_identity(AuthenticationConnection *auth, Key *key)
{
Buffer buffer;
unsigned char buf[8192];
int len, l, type;
Buffer msg;
int type;
unsigned char *blob;
unsigned int blen;
/* Format a message to the agent. */
buffer_init(&buffer);
buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
buffer_put_int(&buffer, BN_num_bits(key->n));
buffer_put_bignum(&buffer, key->e);
buffer_put_bignum(&buffer, key->n);
buffer_init(&msg);
/* 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.");
error_cleanup:
buffer_free(&buffer);
if (key->type == KEY_RSA) {
buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY);
buffer_put_int(&msg, BN_num_bits(key->rsa->n));
buffer_put_bignum(&msg, key->rsa->e);
buffer_put_bignum(&msg, key->rsa->n);
} else if (key->type == KEY_DSA) {
dsa_make_key_blob(key, &blob, &blen);
buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
buffer_put_string(&msg, blob, blen);
xfree(blob);
} else {
buffer_free(&msg);
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);
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
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;
type = buffer_get_char(&msg);
buffer_free(&msg);
return decode_reply(type);
}
/*
@ -512,68 +504,37 @@ ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
*/
int
ssh_remove_all_identities(AuthenticationConnection *auth)
ssh_remove_all_identities(AuthenticationConnection *auth, int version)
{
Buffer buffer;
unsigned char buf[8192];
int len, l, type;
Buffer msg;
int type;
int code = (version==1) ?
SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES :
SSH2_AGENTC_REMOVE_ALL_IDENTITIES;
/* Get the length of the message, and format it in the buffer. */
PUT_32BIT(buf, 1);
buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
buffer_init(&msg);
buffer_put_char(&msg, code);
/* Send the length and then the packet to the agent. */
if (atomicio(write, auth->fd, buf, 5) != 5) {
error("Error writing to authentication socket.");
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
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;
}
type = buffer_get_char(&msg);
buffer_free(&msg);
return decode_reply(type);
}
/* 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 into 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);
int
decode_reply(int type)
{
switch (type) {
case SSH_AGENT_FAILURE:
buffer_free(&buffer);
log("SSH_AGENT_FAILURE");
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;

View File

@ -1,22 +1,43 @@
/*
*
* authfile.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Mon Mar 27 03:52:05 1995 ylo
*
* This file contains functions for reading and writing identity files, and
* for reading the passphrase from the user.
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$Id: authfile.c,v 1.16 2000/04/26 21:28:32 markus Exp $");
RCSID("$OpenBSD: authfile.c,v 1.19 2000/09/07 20:27:49 deraadt Exp $");
RCSID("$FreeBSD$");
#include <openssl/bn.h>
#include <openssl/dsa.h>
@ -263,6 +284,7 @@ load_public_key_rsa(const char *filename, RSA * pub, char **comment_return)
return 1;
}
/* load public key from private-key file */
int
load_public_key(const char *filename, Key * key, char **comment_return)
{
@ -492,3 +514,57 @@ load_private_key(const char *filename, const char *passphrase, Key *key,
close(fd);
return ret;
}
int
do_load_public_key(const char *filename, Key *k, char **commentp)
{
FILE *f;
unsigned int bits;
char line[1024];
char *cp;
f = fopen(filename, "r");
if (f != NULL) {
while (fgets(line, sizeof(line), f)) {
line[sizeof(line)-1] = '\0';
cp = line;
switch(*cp){
case '#':
case '\n':
case '\0':
continue;
}
/* Skip leading whitespace. */
for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
;
if (*cp) {
bits = key_read(k, &cp);
if (bits != 0) {
if (commentp)
*commentp=xstrdup(filename);
fclose(f);
return 1;
}
}
}
fclose(f);
}
return 0;
}
/* load public key from pubkey file */
int
try_load_public_key(const char *filename, Key *k, char **commentp)
{
char pub[MAXPATHLEN];
if (do_load_public_key(filename, k, commentp) == 1)
return 1;
if (strlcpy(pub, filename, sizeof pub) >= MAXPATHLEN)
return 0;
if (strlcat(pub, ".pub", sizeof pub) >= MAXPATHLEN)
return 0;
if (do_load_public_key(pub, k, commentp) == 1)
return 1;
return 0;
}

View File

@ -1,24 +1,44 @@
/*
*
* bufaux.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Wed Mar 29 02:24:47 1995 ylo
*
* Auxiliary functions for storing and retrieving various data types to/from
* Buffers.
*
* SSH2 packet format added by Markus Friedl
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* $FreeBSD$
*
* SSH2 packet format added by Markus Friedl
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$Id: bufaux.c,v 1.11 2000/04/14 10:30:30 markus Exp $");
RCSID("$OpenBSD: bufaux.c,v 1.13 2000/09/07 20:27:50 deraadt Exp $");
RCSID("$FreeBSD$");
#include "ssh.h"
#include <openssl/bn.h>

View File

@ -1,21 +1,19 @@
/*
*
* canohost.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Sun Jul 2 17:52:22 1995 ylo
*
* Functions for returning the canonical host name of the remote site.
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
RCSID("$Id: canohost.c,v 1.12 2000/04/14 10:30:30 markus Exp $");
RCSID("$OpenBSD: canohost.c,v 1.15 2000/09/07 21:13:37 markus Exp $");
RCSID("$FreeBSD$");
#include "packet.h"
#include "xmalloc.h"

View File

@ -1,19 +1,42 @@
/*
*
* cipher.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Wed Apr 19 17:41:39 1995 ylo
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* $FreeBSD$
*
* Copyright (c) 1999 Niels Provos. All rights reserved.
* Copyright (c) 1999,2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$Id: cipher.c,v 1.27 2000/05/22 18:42:00 markus Exp $");
RCSID("$OpenBSD: cipher.c,v 1.30 2000/09/07 20:27:50 deraadt Exp $");
RCSID("$FreeBSD$");
#include "ssh.h"
#include "cipher.h"
@ -175,14 +198,15 @@ cipher_name(int cipher)
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);

View File

@ -1,18 +1,17 @@
/*
*
* cipher.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Wed Apr 19 16:50:42 1995 ylo
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
/* RCSID("$Id: cipher.h,v 1.17 2000/05/08 17:12:15 markus Exp $"); */
/* RCSID("$OpenBSD: cipher.h,v 1.19 2000/09/07 20:27:50 deraadt Exp $"); */
/* $FreeBSD$ */
#ifndef CIPHER_H
#define CIPHER_H

View File

@ -1,21 +1,43 @@
/*
*
* hostfile.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Thu Jun 29 07:10:56 1995 ylo
*
* Functions for manipulating the known hosts files.
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
*
* Copyright (c) 1999,2000 Markus Friedl. All rights reserved.
* Copyright (c) 1999 Niels Provos. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: hostfile.c,v 1.18 2000/04/29 18:11:52 markus Exp $");
RCSID("$OpenBSD: hostfile.c,v 1.20 2000/09/07 20:27:51 deraadt Exp $");
RCSID("$FreeBSD$");
#include "packet.h"
#include "match.h"
@ -130,7 +152,7 @@ check_host_in_hostfile(const char *filename, const char *host, Key *key, Key *fo
;
/* Check if the host name matches. */
if (!match_hostname(host, cp, (unsigned int) (cp2 - cp)))
if (match_hostname(host, cp, (unsigned int) (cp2 - cp)) != 1)
continue;
/* Got a match. Skip host name. */

View File

@ -1,24 +1,22 @@
/*
*
* includes.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Thu Mar 23 16:29:37 1995 ylo
*
* This file includes most of the needed system headers.
*
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* $FreeBSD$
*/
#ifndef INCLUDES_H
#define INCLUDES_H
#define RCSID(msg) \
static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
#define RCSID(msg) __RCSID(msg)
#include <sys/types.h>
#include <sys/socket.h>

View File

@ -1,4 +1,14 @@
/*
* read_bignum():
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
*
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -9,11 +19,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Markus Friedl.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@ -25,12 +30,6 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* read_bignum():
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
*/
#include "includes.h"
@ -43,6 +42,9 @@
#include "dsa.h"
#include "uuencode.h"
RCSID("$OpenBSD: key.c,v 1.11 2000/09/07 20:27:51 deraadt Exp $");
RCSID("$FreeBSD$");
#define SSH_DSS "ssh-dss"
Key *
@ -123,8 +125,6 @@ key_equal(Key *a, Key *b)
return 0;
}
#define FPRINT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
/*
* Generate key fingerprint in ascii format.
* Based on ideas and code from Bjoern Groenvall <bg@sics.se>
@ -132,7 +132,7 @@ key_equal(Key *a, Key *b)
char *
key_fingerprint(Key *k)
{
static char retval[80];
static char retval[(EVP_MAX_MD_SIZE+1)*3];
unsigned char *blob = NULL;
int len = 0;
int nlen, elen;
@ -153,15 +153,22 @@ key_fingerprint(Key *k)
fatal("key_fingerprint: bad key type %d", k->type);
break;
}
retval[0] = '\0';
if (blob != NULL) {
unsigned char d[16];
EVP_MD_CTX md;
EVP_DigestInit(&md, EVP_md5());
EVP_DigestUpdate(&md, blob, len);
EVP_DigestFinal(&md, d, NULL);
snprintf(retval, sizeof(retval), FPRINT,
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
int i;
unsigned char digest[EVP_MAX_MD_SIZE];
EVP_MD *md = EVP_md5();
EVP_MD_CTX ctx;
EVP_DigestInit(&ctx, md);
EVP_DigestUpdate(&ctx, blob, len);
EVP_DigestFinal(&ctx, digest, NULL);
for(i = 0; i < md->md_size; i++) {
char hex[4];
snprintf(hex, sizeof(hex), "%02x:", digest[i]);
strlcat(retval, hex, sizeof(retval));
}
retval[strlen(retval) - 1] = '\0';
memset(blob, 0, len);
xfree(blob);
}
@ -330,3 +337,15 @@ key_type(Key *k)
}
return "unknown";
}
unsigned int
key_size(Key *k){
switch (k->type) {
case KEY_RSA:
return BN_num_bits(k->rsa->n);
break;
case KEY_DSA:
return BN_num_bits(k->dsa->p);
break;
}
return 0;
}

View File

@ -1,25 +1,46 @@
/*
*
* login.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Fri Mar 24 14:51:08 1995 ylo
*
* This file performs some of the things login(1) normally does. We cannot
* easily use something like login -p -h host -f user, because there are
* several different logins around, and it is hard to determined what kind of
* login the current system has. Also, we want to be able to execute commands
* on a tty.
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* Copyright (c) 1999 Theo de Raadt. All rights reserved.
* Copyright (c) 1999 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$Id: login.c,v 1.13 2000/04/19 07:05:49 deraadt Exp $");
RCSID("$OpenBSD: login.c,v 1.15 2000/09/07 20:27:52 deraadt Exp $");
RCSID("$FreeBSD$");
#ifdef __FreeBSD__
#include <libutil.h>

View File

@ -1,22 +1,20 @@
/*
*
* mpaux.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Sun Jul 16 04:29:30 1995 ylo
*
* This file contains various auxiliary functions related to multiple
* precision integers.
*
* $FreeBSD$
*/
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
RCSID("$Id: mpaux.c,v 1.12 2000/04/14 10:30:32 markus Exp $");
RCSID("$OpenBSD: mpaux.c,v 1.14 2000/09/07 20:27:52 deraadt Exp $");
RCSID("$FreeBSD$");
#include <openssl/bn.h>
#include "getput.h"

View File

@ -1,20 +1,18 @@
/*
*
* packet.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Sat Mar 18 02:02:14 1995 ylo
*
* Interface for the packet protocol functions.
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
/* RCSID("$Id: packet.h,v 1.15 2000/04/14 10:30:32 markus Exp $"); */
/* RCSID("$OpenBSD: packet.h,v 1.17 2000/09/07 20:27:52 deraadt Exp $"); */
/* $FreeBSD$ */
#ifndef PACKET_H
#define PACKET_H

View File

@ -1,21 +1,19 @@
/*
*
* pty.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Fri Mar 17 04:37:25 1995 ylo
*
* Allocating a pseudo-terminal, and making it the controlling tty.
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
RCSID("$Id: pty.c,v 1.13 2000/04/14 10:30:32 markus Exp $");
RCSID("$OpenBSD: pty.c,v 1.16 2000/09/07 21:13:37 markus Exp $");
RCSID("$FreeBSD$");
#ifdef __FreeBSD__
#include <libutil.h>

View File

@ -1,21 +1,19 @@
/*
*
* readconf.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Sat Apr 22 00:03:10 1995 ylo
*
* Functions for reading the configuration files.
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
RCSID("$Id: readconf.c,v 1.33 2000/05/29 20:20:46 markus Exp $");
RCSID("$OpenBSD: readconf.c,v 1.47 2000/09/07 21:13:37 markus Exp $");
RCSID("$FreeBSD$");
#include "ssh.h"
#include "cipher.h"
@ -93,7 +91,7 @@ typedef enum {
oBadOption,
oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
oSkeyAuthentication,
oSkeyAuthentication, oXAuthLocation,
#ifdef KRB4
oKrb4Authentication,
#endif /* KRB4 */
@ -120,6 +118,7 @@ static struct {
} keywords[] = {
{ "forwardagent", oForwardAgent },
{ "forwardx11", oForwardX11 },
{ "xauthlocation", oXAuthLocation },
{ "gatewayports", oGatewayPorts },
{ "useprivilegedport", oUsePrivilegedPort },
{ "rhostsauthentication", oRhostsAuthentication },
@ -171,10 +170,6 @@ static struct {
{ NULL, 0 }
};
/* Characters considered whitespace in strtok calls. */
#define WHITESPACE " \t\r\n"
/*
* Adds a local TCP/IP port forward to options. Never returns if there is an
* error.
@ -244,18 +239,20 @@ process_config_line(Options *options, const char *host,
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;
/* Get the keyword. (Each line is supposed to begin with a keyword). */
keyword = strdelim(&s);
/* Ignore leading whitespace. */
if (*keyword == '\0')
keyword = strdelim(&s);
if (!*keyword || *keyword == '\n' || *keyword == '#')
return 0;
/* Get the keyword. (Each line is supposed to begin with a keyword). */
cp = strtok(cp, WHITESPACE);
opcode = parse_token(cp, filename, linenum);
opcode = parse_token(keyword, filename, linenum);
switch (opcode) {
case oBadOption:
@ -265,13 +262,13 @@ process_config_line(Options *options, const char *host,
case oForwardAgent:
intptr = &options->forward_agent;
parse_flag:
cp = strtok(NULL, WHITESPACE);
if (!cp)
arg = strdelim(&s);
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);
@ -361,16 +358,16 @@ process_config_line(Options *options, const char *host,
case oStrictHostKeyChecking:
intptr = &options->strict_host_key_checking;
cp = strtok(NULL, WHITESPACE);
if (!cp)
arg = strdelim(&s);
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);
@ -396,8 +393,8 @@ process_config_line(Options *options, const char *host,
case oIdentityFile:
case oIdentityFile2:
cp = strtok(NULL, WHITESPACE);
if (!cp)
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (*activep) {
intptr = (opcode == oIdentityFile) ?
@ -409,19 +406,23 @@ process_config_line(Options *options, const char *host,
charptr = (opcode == oIdentityFile) ?
&options->identity_files[*intptr] :
&options->identity_files2[*intptr];
*charptr = xstrdup(cp);
*charptr = xstrdup(arg);
*intptr = *intptr + 1;
}
break;
case oXAuthLocation:
charptr=&options->xauth_location;
goto parse_string;
case oUser:
charptr = &options->user;
parse_string:
cp = strtok(NULL, WHITESPACE);
if (!cp)
arg = strdelim(&s);
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:
@ -447,10 +448,10 @@ process_config_line(Options *options, const char *host,
case oProxyCommand:
charptr = &options->proxy_command;
string = xstrdup("");
while ((cp = strtok(NULL, WHITESPACE)) != NULL) {
string = xrealloc(string, strlen(string) + strlen(cp) + 2);
while ((arg = strdelim(&s)) != 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;
@ -461,15 +462,15 @@ process_config_line(Options *options, const char *host,
case oPort:
intptr = &options->port;
parse_int:
cp = strtok(NULL, WHITESPACE);
if (!cp)
arg = strdelim(&s);
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;
@ -481,65 +482,65 @@ process_config_line(Options *options, const char *host,
case oCipher:
intptr = &options->cipher;
cp = strtok(NULL, WHITESPACE);
if (!cp)
arg = strdelim(&s);
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 = strdelim(&s);
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 = strdelim(&s);
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 = strdelim(&s);
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 = strdelim(&s);
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 = strdelim(&s);
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)
@ -547,18 +548,18 @@ process_config_line(Options *options, const char *host,
break;
case oLocalForward:
cp = strtok(NULL, WHITESPACE);
if (!cp)
arg = strdelim(&s);
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 = strdelim(&s);
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)
@ -567,26 +568,26 @@ process_config_line(Options *options, const char *host,
case oHost:
*activep = 0;
while ((cp = strtok(NULL, WHITESPACE)) != NULL)
if (match_pattern(host, cp)) {
debug("Applying options for %.100s", cp);
while ((arg = strdelim(&s)) != 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 strdelim is done. */
return 0;
case oEscapeChar:
intptr = &options->escape_char;
cp = strtok(NULL, WHITESPACE);
if (!cp)
arg = strdelim(&s);
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.",
@ -603,9 +604,11 @@ process_config_line(Options *options, const char *host,
}
/* 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 = strdelim(&s)) != NULL && *arg != '\0')
{
fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
filename, linenum, arg);
}
return 0;
}
@ -662,6 +665,7 @@ initialize_options(Options * options)
memset(options, 'X', sizeof(*options));
options->forward_agent = -1;
options->forward_x11 = -1;
options->xauth_location = NULL;
options->gateway_ports = -1;
options->use_privileged_port = -1;
options->rhosts_authentication = -1;
@ -722,6 +726,10 @@ fill_default_options(Options * options)
options->forward_agent = 0;
if (options->forward_x11 == -1)
options->forward_x11 = 0;
#ifdef XAUTH_PATH
if (options->xauth_location == NULL)
options->xauth_location = XAUTH_PATH;
#endif /* XAUTH_PATH */
if (options->gateway_ports == -1)
options->gateway_ports = 0;
if (options->use_privileged_port == -1)

View File

@ -1,20 +1,18 @@
/*
*
* readconf.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Sat Apr 22 00:25:29 1995 ylo
*
* Functions for reading the configuration file.
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
/* RCSID("$Id: readconf.h,v 1.18 2000/05/08 17:12:15 markus Exp $"); */
/* RCSID("$OpenBSD: readconf.h,v 1.21 2000/09/07 20:27:53 deraadt Exp $"); */
/* $FreeBSD$ */
#ifndef READCONF_H
#define READCONF_H
@ -31,6 +29,7 @@ typedef struct {
typedef struct {
int forward_agent; /* Forward authentication agent. */
int forward_x11; /* Forward X11 display. */
char *xauth_location; /* Location for xauth program */
int gateway_ports; /* Allow remote connects to forwarded ports. */
int use_privileged_port; /* Don't use privileged port if false. */
int rhosts_authentication; /* Try rhosts authentication. */

View File

@ -1,15 +1,40 @@
/*
*
* rsa.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Fri Mar 3 22:07:06 1995 ylo
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
*
* Description of the RSA algorithm can be found e.g. from the following sources:
* Copyright (c) 1999 Niels Provos. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* Description of the RSA algorithm can be found e.g. from the following
* sources:
*
* Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994.
*
@ -25,18 +50,18 @@
* Hans Riesel: Prime Numbers and Computer Methods for Factorization.
* Birkhauser, 1994.
*
* The RSA Frequently Asked Questions document by RSA Data Security, Inc., 1995.
* The RSA Frequently Asked Questions document by RSA Data Security,
* Inc., 1995.
*
* RSA in 3 lines of perl by Adam Back <aba@atlax.ex.ac.uk>, 1995, as included
* below:
* RSA in 3 lines of perl by Adam Back <aba@atlax.ex.ac.uk>, 1995, as
* included below:
*
* [gone - had to be deleted - what a pity]
*
* $FreeBSD$
*/
*/
#include "includes.h"
RCSID("$Id: rsa.c,v 1.14 2000/04/14 10:30:32 markus Exp $");
RCSID("$OpenBSD: rsa.c,v 1.16 2000/09/07 20:27:53 deraadt Exp $");
RCSID("$FreeBSD$");
#include "rsa.h"
#include "ssh.h"

View File

@ -1,20 +1,18 @@
/*
*
* rsa.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Fri Mar 3 22:01:06 1995 ylo
*
* RSA key generation, encryption and decryption.
*
* $FreeBSD$
*/
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
/* RCSID("$Id: rsa.h,v 1.6 2000/04/14 10:30:32 markus Exp $"); */
/* RCSID("$OpenBSD: rsa.h,v 1.8 2000/09/07 20:27:53 deraadt Exp $"); */
/* $FreeBSD$ */
#ifndef RSA_H
#define RSA_H

View File

@ -1,19 +1,17 @@
/*
*
* servconf.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Mon Aug 21 15:48:58 1995 ylo
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
RCSID("$Id: servconf.c,v 1.41 2000/05/22 18:42:01 markus Exp $");
RCSID("$OpenBSD: servconf.c,v 1.51 2000/09/07 20:27:53 deraadt Exp $");
RCSID("$FreeBSD$");
#include "ssh.h"
#include "servconf.h"
@ -45,6 +43,7 @@ initialize_server_options(ServerOptions *options)
options->check_mail = -1;
options->x11_forwarding = -1;
options->x11_display_offset = -1;
options->xauth_location = NULL;
options->strict_modes = -1;
options->keepalives = -1;
options->log_facility = (SyslogFacility) - 1;
@ -81,6 +80,10 @@ initialize_server_options(ServerOptions *options)
options->gateway_ports = -1;
options->connections_per_period = 0;
options->connections_period = 0;
options->num_subsystems = 0;
options->max_startups_begin = -1;
options->max_startups_rate = -1;
options->max_startups = -1;
}
void
@ -116,6 +119,10 @@ fill_default_server_options(ServerOptions *options)
options->x11_forwarding = 1;
if (options->x11_display_offset == -1)
options->x11_display_offset = 10;
#ifdef XAUTH_PATH
if (options->xauth_location == NULL)
options->xauth_location = XAUTH_PATH;
#endif /* XAUTH_PATH */
if (options->strict_modes == -1)
options->strict_modes = 1;
if (options->keepalives == -1)
@ -166,10 +173,14 @@ fill_default_server_options(ServerOptions *options)
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;
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;
}
#define WHITESPACE " \t\r\n"
/* Keyword tokens. */
typedef enum {
sBadOption, /* == unknown option */
@ -193,7 +204,8 @@ typedef enum {
sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile,
sGatewayPorts, sDSAAuthentication, sConnectionsPerPeriod
sGatewayPorts, sDSAAuthentication, sConnectionsPerPeriod, sXAuthLocation,
sSubsystem, sMaxStartups
} ServerOpCodes;
/* Textual representation of the tokens. */
@ -239,6 +251,7 @@ static struct {
{ "ignoreuserknownhosts", sIgnoreUserKnownHosts },
{ "x11forwarding", sX11Forwarding },
{ "x11displayoffset", sX11DisplayOffset },
{ "xauthlocation", sXAuthLocation },
{ "strictmodes", sStrictModes },
{ "permitemptypasswords", sEmptyPasswd },
{ "uselogin", sUseLogin },
@ -252,6 +265,8 @@ static struct {
{ "protocol", sProtocol },
{ "gatewayports", sGatewayPorts },
{ "connectionsperperiod", sConnectionsPerPeriod },
{ "subsystem", sSubsystem },
{ "maxstartups", sMaxStartups },
{ NULL, 0 }
};
@ -313,10 +328,11 @@ read_server_config(ServerOptions *options, const char *filename)
{
FILE *f;
char line[1024];
char *cp, **charptr;
char *cp, **charptr, *arg;
int linenum, *intptr, value;
int bad_options = 0;
ServerOpCodes opcode;
int i;
f = fopen(filename, "r");
if (!f) {
@ -326,11 +342,14 @@ read_server_config(ServerOptions *options, const char *filename)
linenum = 0;
while (fgets(line, sizeof(line), f)) {
linenum++;
cp = line + strspn(line, WHITESPACE);
if (!*cp || *cp == '#')
cp = line;
arg = strdelim(&cp);
/* Ignore leading whitespace */
if (*arg == '\0')
arg = strdelim(&cp);
if (!*arg || *arg == '#')
continue;
cp = strtok(cp, WHITESPACE);
opcode = parse_token(cp, filename, linenum);
opcode = parse_token(arg, filename, linenum);
switch (opcode) {
case sBadOption:
bad_options++;
@ -345,23 +364,24 @@ read_server_config(ServerOptions *options, const char *filename)
if (options->num_ports >= MAX_PORTS)
fatal("%s line %d: too many ports.\n",
filename, linenum);
cp = strtok(NULL, WHITESPACE);
if (!cp)
arg = strdelim(&cp);
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 = strdelim(&cp);
if (!arg || *arg == '\0') {
fprintf(stderr, "%s line %d: missing integer value.\n",
filename, linenum);
exit(1);
}
if (sscanf(cp, " %d ", &value) != 1) {
value = atoi(arg);
if (value == 0) {
fprintf(stderr, "%s line %d: invalid integer value.\n",
filename, linenum);
exit(1);
@ -379,62 +399,55 @@ read_server_config(ServerOptions *options, const char *filename)
goto parse_int;
case sListenAddress:
cp = strtok(NULL, WHITESPACE);
if (!cp)
arg = strdelim(&cp);
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:
case sHostDSAKeyFile:
charptr = (opcode == sHostKeyFile ) ?
&options->host_key_file : &options->host_dsa_key_file;
cp = strtok(NULL, WHITESPACE);
if (!cp) {
parse_filename:
arg = strdelim(&cp);
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:
charptr = &options->pid_file;
cp = strtok(NULL, WHITESPACE);
if (!cp) {
fprintf(stderr, "%s line %d: missing file name.\n",
filename, linenum);
exit(1);
}
if (*charptr == NULL)
*charptr = tilde_expand_filename(cp, getuid());
break;
goto parse_filename;
case sRandomSeedFile:
fprintf(stderr, "%s line %d: \"randomseed\" option is obsolete.\n",
filename, linenum);
cp = strtok(NULL, WHITESPACE);
arg = strdelim(&cp);
break;
case sPermitRootLogin:
intptr = &options->permit_root_login;
cp = strtok(NULL, WHITESPACE);
if (!cp) {
arg = strdelim(&cp);
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)
@ -444,19 +457,19 @@ read_server_config(ServerOptions *options, const char *filename)
case sIgnoreRhosts:
intptr = &options->ignore_rhosts;
parse_flag:
cp = strtok(NULL, WHITESPACE);
if (!cp) {
arg = strdelim(&cp);
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)
@ -543,6 +556,10 @@ read_server_config(ServerOptions *options, const char *filename)
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;
@ -565,92 +582,92 @@ read_server_config(ServerOptions *options, const char *filename)
case sLogFacility:
intptr = (int *) &options->log_facility;
cp = strtok(NULL, WHITESPACE);
value = log_facility_number(cp);
arg = strdelim(&cp);
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 = strdelim(&cp);
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 = strdelim(&cp)) && *arg != '\0') {
if (options->num_allow_users >= MAX_ALLOW_USERS)
fatal("%.200s 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 = strdelim(&cp)) && *arg != '\0') {
if (options->num_deny_users >= MAX_DENY_USERS)
fatal("%.200s 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 = strdelim(&cp)) && *arg != '\0') {
if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
fatal("%.200s 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 = strdelim(&cp)) && *arg != '\0') {
if (options->num_deny_groups >= MAX_DENY_GROUPS)
fatal("%.200s 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 = strdelim(&cp);
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 = strdelim(&cp);
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;
case sConnectionsPerPeriod:
cp = strtok(NULL, WHITESPACE);
arg = strdelim(&cp);
if (cp == NULL)
fatal("%.200s line %d: missing (>= 0) number argument.\n",
filename, linenum);
if (sscanf(cp, " %u/%u ", &options->connections_per_period,
if (sscanf(arg, "%u/%u", &options->connections_per_period,
&options->connections_period) != 2)
fatal("%.200s line %d: invalid numerical argument(s).\n",
filename, linenum);
@ -660,13 +677,57 @@ read_server_config(ServerOptions *options, const char *filename)
filename, linenum);
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 (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;
goto parse_int;
default:
fatal("%.200s line %d: Missing handler for opcode %s (%d)\n",
filename, linenum, cp, opcode);
filename, linenum,arg, opcode);
}
if (strtok(NULL, WHITESPACE) != NULL) {
fatal("%.200s line %d: garbage at end of line.\n",
filename, linenum);
if ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
fprintf(stderr,
"%s line %d: garbage at end of line; \"%.200s\".\n",
filename, linenum, arg);
exit(1);
}
}
fclose(f);

View File

@ -1,20 +1,18 @@
/*
*
* servconf.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Mon Aug 21 15:35:03 1995 ylo
*
* Definitions for server configuration data and for the functions reading it.
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
/* RCSID("$Id: servconf.h,v 1.22 2000/05/06 17:45:37 markus Exp $"); */
/* RCSID("$OpenBSD: servconf.h,v 1.28 2000/09/07 20:27:53 deraadt Exp $"); */
/* $FreeBSD$ */
#ifndef SERVCONF_H
#define SERVCONF_H
@ -25,6 +23,7 @@
#define MAX_DENY_USERS 256 /* Max # users on deny list. */
#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */
#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */
typedef struct {
unsigned int num_ports;
@ -48,6 +47,7 @@ typedef struct {
int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */
int x11_display_offset; /* What DISPLAY number to start
* searching at */
char *xauth_location; /* Location of xauth program */
int strict_modes; /* If true, require string home dir modes. */
int keepalives; /* If true, set SO_KEEPALIVE. */
char *ciphers; /* Ciphers in order of preference. */
@ -105,6 +105,15 @@ typedef struct {
* connections_period.
*/
unsigned int connections_period;
unsigned int num_subsystems;
char *subsystem_name[MAX_SUBSYSTEMS];
char *subsystem_command[MAX_SUBSYSTEMS];
int max_startups_begin;
int max_startups_rate;
int max_startups;
} ServerOptions;
/*
* Initializes the server options to special values that indicate that they

View File

@ -1,16 +1,40 @@
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*/
/*
*
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* SSH2 support by Markus Friedl.
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* $FreeBSD$
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: session.c,v 1.15 2000/05/30 17:23:37 markus Exp $");
RCSID("$OpenBSD: session.c,v 1.37 2000/09/07 20:27:53 deraadt Exp $");
RCSID("$FreeBSD$");
#include "xmalloc.h"
#include "ssh.h"
@ -28,14 +52,15 @@ RCSID("$OpenBSD: session.c,v 1.15 2000/05/30 17:23:37 markus Exp $");
#include "bufaux.h"
#include "ssh2.h"
#include "auth.h"
#include "auth-options.h"
#ifdef __FreeBSD__
#define _PATH_CHPASS "/usr/bin/passwd"
#endif /* __FreeBSD__ */
#ifdef LOGIN_CAP
#ifdef HAVE_LOGIN_CAP
#include <login_cap.h>
#endif /* LOGIN_CAP */
#endif
#ifdef KRB5
extern krb5_context ssh_context;
@ -74,6 +99,7 @@ void session_pty_cleanup(Session *s);
void session_proctitle(Session *s);
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);
char *do_login(Session *s, const char *command);
void
do_child(const char *command, struct passwd * pw, const char *term,
@ -85,25 +111,23 @@ extern ServerOptions options;
extern char *__progname;
extern int log_stderr;
extern int debug_flag;
extern unsigned int utmp_len;
extern int startup_pipe;
/* Local Xauthority file. */
static char *xauthfile;
/* original command from peer. */
char *original_command = NULL;
/* data */
#define MAX_SESSIONS 10
Session sessions[MAX_SESSIONS];
/* Flags set in auth-rsa from authorized_keys flags. These are set in auth-rsa.c. */
int no_port_forwarding_flag = 0;
int no_agent_forwarding_flag = 0;
int no_x11_forwarding_flag = 0;
int no_pty_flag = 0;
/* RSA authentication "command=" option. */
char *forced_command = NULL;
/* RSA authentication "environment=" options. */
struct envstring *custom_environment = NULL;
#ifdef HAVE_LOGIN_CAP
static login_cap_t *lc;
#endif
/*
* Remove local Xauthority file.
@ -157,7 +181,7 @@ void
do_authenticated(struct passwd * pw)
{
Session *s;
int type;
int type, fd;
int compression_level = 0, enable_compression_after_reply = 0;
int have_pty = 0;
char *command;
@ -170,6 +194,10 @@ do_authenticated(struct passwd * pw)
* authentication.
*/
alarm(0);
if (startup_pipe != -1) {
close(startup_pipe);
startup_pipe = -1;
}
/*
* Inform the channel mechanism that we are the server side and that
@ -184,6 +212,13 @@ do_authenticated(struct passwd * pw)
s = session_new();
s->pw = pw;
#ifdef HAVE_LOGIN_CAP
if ((lc = login_getclass(pw->pw_class)) == NULL) {
error("unable to get login class");
return;
}
#endif
/*
* We stay in this loop until the client requests to execute a shell
* or a command.
@ -262,7 +297,10 @@ do_authenticated(struct passwd * pw)
packet_send_debug("X11 forwarding disabled in server configuration file.");
break;
}
#ifdef XAUTH_PATH
if (!options.xauth_location) {
packet_send_debug("No xauth program; cannot forward with spoofing.");
break;
}
if (no_x11_forwarding_flag) {
packet_send_debug("X11 forwarding not permitted for this authentication.");
break;
@ -298,15 +336,13 @@ do_authenticated(struct passwd * pw)
break;
}
strlcat(xauthfile, "/cookies", MAXPATHLEN);
open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);
fd = open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);
if (fd >= 0)
close(fd);
restore_uid();
fatal_add_cleanup(xauthfile_cleanup_proc, NULL);
success = 1;
break;
#else /* XAUTH_PATH */
packet_send_debug("No xauth program; cannot forward with spoofing.");
break;
#endif /* XAUTH_PATH */
case SSH_CMSG_AGENT_REQUEST_FORWARDING:
if (no_agent_forwarding_flag || compat13) {
@ -347,6 +383,7 @@ do_authenticated(struct passwd * pw)
packet_integrity_check(plen, 0, type);
}
if (forced_command != NULL) {
original_command = command;
command = forced_command;
debug("Forced command '%.500s'", forced_command);
}
@ -506,50 +543,17 @@ do_exec_no_pty(Session *s, const char *command, struct passwd * pw)
void
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 quiet_login;
pid_t pid;
socklen_t fromlen;
struct sockaddr_storage from;
struct stat st;
time_t last_login_time;
#ifdef LOGIN_CAP
login_cap_t *lc;
char *fname;
#endif /* LOGIN_CAP */
#ifdef __FreeBSD__
#define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */
struct timeval tv;
time_t warntime = DEFAULT_WARN;
#endif /* __FreeBSD__ */
if (s == NULL)
fatal("do_exec_pty: no session");
ptyfd = s->ptyfd;
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));
}
/* Fork the child. */
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);
/* Close the master side of the pseudo tty. */
@ -573,152 +577,9 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw)
/* Close the extra descriptor for the pseudo tty. */
close(ttyfd);
/* XXXX ? move to do_child() ??*/
/*
* Get IP address of client. This is needed because we want
* 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. */
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 LOGIN_CAP
lc = login_getpwclass(pw);
if (lc == NULL)
lc = login_getclassbyname(NULL, pw);
quiet_login = login_getcapbool(lc, "hushlogin", quiet_login);
#endif /* LOGIN_CAP */
#ifdef __FreeBSD__
if (pw->pw_change || pw->pw_expire)
(void)gettimeofday(&tv, NULL);
#ifdef LOGIN_CAP
warntime = login_getcaptime(lc, "warnpassword",
DEFAULT_WARN, DEFAULT_WARN);
#endif /* LOGIN_CAP */
/*
* If the password change time is set and has passed, give the
* user a password expiry notice and chance to change it.
*/
if (pw->pw_change != 0) {
if (tv.tv_sec >= pw->pw_change) {
(void)printf(
"Sorry -- your password has expired.\n");
log("%s Password expired - forcing change",
pw->pw_name);
command = _PATH_CHPASS;
} else if (pw->pw_change - tv.tv_sec < warntime &&
!quiet_login)
(void)printf(
"Warning: your password expires on %s",
ctime(&pw->pw_change));
}
#ifdef LOGIN_CAP
warntime = login_getcaptime(lc, "warnexpire",
DEFAULT_WARN, DEFAULT_WARN);
#endif /* LOGIN_CAP */
if (pw->pw_expire) {
if (tv.tv_sec >= pw->pw_expire) {
(void)printf(
"Sorry -- your account has expired.\n");
log(
"LOGIN %.200s REFUSED (EXPIRED) FROM %.200s ON TTY %.200s",
pw->pw_name, hostname, s->tty);
exit(254);
} else if (pw->pw_expire - tv.tv_sec < warntime &&
!quiet_login)
(void)printf(
"Warning: your account expires on %s",
ctime(&pw->pw_expire));
}
#endif /* __FreeBSD__ */
#ifdef LOGIN_CAP
if (!auth_ttyok(lc, s->tty)) {
(void)printf("Permission denied.\n");
log(
"LOGIN %.200s REFUSED (TTY) FROM %.200s ON TTY %.200s",
pw->pw_name, hostname, s->tty);
exit(254);
}
#endif /* LOGIN_CAP */
/*
* 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);
}
#ifdef LOGIN_CAP
if (command == NULL && !quiet_login && !options.use_login) {
fname = login_getcapstr(lc, "copyright", NULL, NULL);
if (fname != NULL && (f = fopen(fname, "r")) != NULL) {
while (fgets(line, sizeof(line), f) != NULL)
fputs(line, stdout);
fclose(f);
} else
(void)printf("%s\n\t%s %s\n",
"Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994",
"The Regents of the University of California. ",
"All rights reserved.");
}
#endif /* LOGIN_CAP */
/*
* 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) {
#ifdef LOGIN_CAP
fname = login_getcapstr(lc, "welcome", NULL, NULL);
if (fname == NULL || (f = fopen(fname, "r")) == NULL)
f = fopen("/etc/motd", "r");
#else /* !LOGIN_CAP */
f = fopen("/etc/motd", "r");
#endif /* LOGIN_CAP */
/* Print /etc/motd if it exists. */
if (f) {
while (fgets(line, sizeof(line), f))
fputs(line, stdout);
fclose(f);
}
}
#ifdef LOGIN_CAP
login_close(lc);
#endif /* LOGIN_CAP */
/* record login, etc. similar to login(1) */
if (!options.use_login)
command = do_login(s, command);
/* Do common processing for the child, such as execing the command. */
do_child(command, pw, s->term, s->display, s->auth_proto,
@ -757,6 +618,197 @@ 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 */
char *
do_login(Session *s, const char *command)
{
FILE *f;
char *time_string, *newcommand;
char buf[256];
char hostname[MAXHOSTNAMELEN];
int quiet_login;
socklen_t fromlen;
struct sockaddr_storage from;
struct stat st;
time_t last_login_time;
struct passwd * pw = s->pw;
pid_t pid = getpid();
#ifdef HAVE_LOGIN_CAP
login_cap_t *lc;
char *fname;
#endif /* HAVE_LOGIN_CAP */
#ifdef __FreeBSD__
#define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */
struct timeval tv;
time_t warntime = DEFAULT_WARN;
#endif /* __FreeBSD__ */
newcommand = (char *)command;
/*
* 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();
}
}
/* Get the time and hostname when the user last logged in. */
hostname[0] = '\0';
last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
hostname, sizeof(hostname));
/* 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);
#ifdef HAVE_LOGIN_CAP
lc = login_getpwclass(pw);
if (lc == NULL)
lc = login_getclassbyname(NULL, pw);
quiet_login = login_getcapbool(lc, "hushlogin", quiet_login) || stat(buf, &st) >= 0;
#else
quiet_login = stat(line, &st) >= 0;
#endif /* HAVE_LOGIN_CAP */
#ifdef __FreeBSD__
if (pw->pw_change || pw->pw_expire)
(void)gettimeofday(&tv, NULL);
#ifdef HAVE_LOGIN_CAP
warntime = login_getcaptime(lc, "warnpassword",
DEFAULT_WARN, DEFAULT_WARN);
#endif /* HAVE_LOGIN_CAP */
/*
* If the password change time is set and has passed, give the
* user a password expiry notice and chance to change it.
*/
if (pw->pw_change != 0) {
if (tv.tv_sec >= pw->pw_change) {
(void)printf(
"Sorry -- your password has expired.\n");
log("%s Password expired - forcing change",
pw->pw_name);
newcommand = _PATH_CHPASS;
} else if (pw->pw_change - tv.tv_sec < warntime &&
!quiet_login)
(void)printf(
"Warning: your password expires on %s",
ctime(&pw->pw_change));
}
#ifdef HAVE_LOGIN_CAP
warntime = login_getcaptime(lc, "warnexpire",
DEFAULT_WARN, DEFAULT_WARN);
#endif /* HAVE_LOGIN_CAP */
if (pw->pw_expire) {
if (tv.tv_sec >= pw->pw_expire) {
(void)printf(
"Sorry -- your account has expired.\n");
log(
"LOGIN %.200s REFUSED (EXPIRED) FROM %.200s ON TTY %.200s",
pw->pw_name, get_remote_name_or_ip(), s->tty);
exit(254);
} else if (pw->pw_expire - tv.tv_sec < warntime &&
!quiet_login)
(void)printf(
"Warning: your account expires on %s",
ctime(&pw->pw_expire));
}
#endif /* __FreeBSD__ */
#ifdef HAVE_LOGIN_CAP
if (!auth_ttyok(lc, s->tty)) {
(void)printf("Permission denied.\n");
log(
"LOGIN %.200s REFUSED (TTY) FROM %.200s ON TTY %.200s",
pw->pw_name, get_remote_name_or_ip(), s->tty);
exit(254);
}
#endif /* HAVE_LOGIN_CAP */
/*
* 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 (newcommand == 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, hostname);
}
#ifdef HAVE_LOGIN_CAP
if (newcommand == NULL && !quiet_login && !options.use_login) {
fname = login_getcapstr(lc, "copyright", NULL, NULL);
if (fname != NULL && (f = fopen(fname, "r")) != NULL) {
while (fgets(buf, sizeof(buf), f) != NULL)
fputs(buf, stdout);
fclose(f);
} else
(void)printf("%s\n\t%s %s\n",
"Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994",
"The Regents of the University of California. ",
"All rights reserved.");
}
#endif /* HAVE_LOGIN_CAP */
/*
* 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 (newcommand == NULL && options.print_motd && !quiet_login &&
!options.use_login) {
#ifdef HAVE_LOGIN_CAP
f = fopen(login_getcapstr(lc, "welcome", "/etc/motd",
"/etc/motd"), "r");
#else /* !HAVE_LOGIN_CAP */
f = fopen("/etc/motd", "r");
#endif /* HAVE_LOGIN_CAP */
if (f) {
while (fgets(buf, sizeof(buf), f))
fputs(buf, stdout);
fclose(f);
}
}
#ifdef HAVE_LOGIN_CAP
login_close(lc);
#endif /* HAVE_LOGIN_CAP */
return newcommand;
}
/*
* Sets the value of the given variable in the environment. If the variable
* already exists, its value is overriden.
@ -847,16 +899,16 @@ do_child(const char *command, struct passwd * pw, const char *term,
const char *display, const char *auth_proto,
const char *auth_data, const char *ttyname)
{
char *shell;
const char *cp = NULL;
const char *shell, *hostname = NULL, *cp = NULL;
char buf[256];
FILE *f;
char cmd[1024];
FILE *f = NULL;
unsigned int envsize, i;
char **env = NULL;
extern char **environ;
struct stat st;
char *argv[10];
#ifdef LOGIN_CAP
#ifdef HAVE_LOGIN_CAP
login_cap_t *lc;
#endif
@ -864,36 +916,32 @@ do_child(const char *command, struct passwd * pw, const char *term,
if (options.use_login && command != NULL)
options.use_login = 0;
#ifdef LOGIN_CAP
lc = login_getpwclass(pw);
if (lc == NULL)
lc = login_getclassbyname(NULL, pw);
if (pw->pw_uid != 0)
auth_checknologin(lc);
#else /* !LOGIN_CAP */
f = fopen("/etc/nologin", "r");
if (f) {
/* /etc/nologin exists. Print its contents and exit. */
while (fgets(buf, sizeof(buf), f))
fputs(buf, stderr);
fclose(f);
if (!options.use_login) {
#ifdef HAVE_LOGIN_CAP
lc = login_getpwclass(pw);
if (lc == NULL)
lc = login_getclassbyname(NULL, pw);
if (pw->pw_uid != 0)
auth_checknologin(lc);
f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN,
_PATH_NOLOGIN), "r");
#else
if (pw->pw_uid)
f = fopen(_PATH_NOLOGIN, "r");
#endif
if (f) {
/* /etc/nologin exists. Print its contents and exit. */
while (fgets(buf, sizeof(buf), f))
fputs(buf, stderr);
fclose(f);
exit(254);
}
}
#endif /* LOGIN_CAP */
#ifdef LOGIN_CAP
if (options.use_login)
#endif /* LOGIN_CAP */
/* Set login name in the kernel. */
if (setlogin(pw->pw_name) < 0)
error("setlogin failed: %s", strerror(errno));
/* Set uid, gid, and groups. */
/* Set login name, uid, gid, and groups. */
/* Login(1) does this as well, and it needs uid 0 for the "-h"
switch, so we let login(1) to this for us. */
if (!options.use_login) {
#ifdef LOGIN_CAP
#ifdef HAVE_LOGIN_CAP
char **tmpenv;
/* Initialize temp environment */
@ -928,8 +976,18 @@ do_child(const char *command, struct passwd * pw, const char *term,
envsize = (envsize < 100) ? 100 : envsize + 16;
env = xrealloc(env, envsize * sizeof(char *));
#else /* !LOGIN_CAP */
#endif /* !HAVE_LOGIN_CAP */
if (getuid() == 0 || geteuid() == 0) {
#ifdef HAVE_LOGIN_CAP
if (setusercontext(lc, pw, pw->pw_uid,
(LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) {
perror("unable to set user context");
exit(1);
}
#else
if (setlogin(pw->pw_name) < 0)
error("setlogin failed: %s", strerror(errno));
if (setgid(pw->pw_gid) < 0) {
perror("setgid");
exit(1);
@ -943,19 +1001,19 @@ do_child(const char *command, struct passwd * pw, const char *term,
/* Permanently switch to the desired uid. */
permanently_set_uid(pw->pw_uid);
#endif /* HAVE_LOGIN_CAP */
}
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
fatal("Failed to set uids to %d.", (int) pw->pw_uid);
#endif /* LOGIN_CAP */
fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
}
/*
* Get the shell from the password data. An empty shell field is
* legal, and means /bin/sh.
*/
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
#ifdef LOGIN_CAP
shell = login_getcapstr(lc, "shell", shell, shell);
#endif /* LOGIN_CAP */
#ifdef HAVE_LOGIN_CAP
shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
#endif
#ifdef AFS
/* Try to get AFS tokens for the local cell. */
@ -981,20 +1039,20 @@ do_child(const char *command, struct passwd * pw, const char *term,
child_set_env(&env, &envsize, "USER", pw->pw_name);
child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
child_set_env(&env, &envsize, "HOME", pw->pw_dir);
#ifndef LOGIN_CAP
#ifdef HAVE_LOGIN_CAP
(void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH);
child_set_env(&env, &envsize, "PATH", getenv("PATH"));
#else
child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
#endif
snprintf(buf, sizeof buf, "%.200s/%.50s",
_PATH_MAILDIR, pw->pw_name);
child_set_env(&env, &envsize, "MAIL", buf);
#endif /* !LOGIN_CAP */
/* Normal systems set SHELL by default. */
child_set_env(&env, &envsize, "SHELL", shell);
}
#ifdef LOGIN_CAP
if (options.use_login)
#endif /* LOGIN_CAP */
if (getenv("TZ"))
child_set_env(&env, &envsize, "TZ", getenv("TZ"));
@ -1023,6 +1081,9 @@ do_child(const char *command, struct passwd * pw, const char *term,
child_set_env(&env, &envsize, "TERM", term);
if (display)
child_set_env(&env, &envsize, "DISPLAY", display);
if (original_command)
child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",
original_command);
#ifdef KRB4
{
@ -1076,6 +1137,9 @@ do_child(const char *command, struct passwd * pw, const char *term,
for (i = 0; env[i]; i++)
fprintf(stderr, " %.200s\n", env[i]);
}
/* we have to stash the hostname before we close our socket. */
if (options.use_login)
hostname = get_remote_name_or_ip();
/*
* Close the connection descriptors; note that this is the child, and
* the server will still have the socket open, and it is important
@ -1121,14 +1185,14 @@ do_child(const char *command, struct passwd * pw, const char *term,
#ifdef __FreeBSD__
int quiet_login = 0;
#endif /* __FreeBSD__ */
#ifdef LOGIN_CAP
#ifdef HAVE_LOGIN_CAP
if (login_getcapbool(lc, "requirehome", 0)) {
(void)printf("Home directory not available\n");
log("LOGIN %.200s REFUSED (HOMEDIR) ON TTY %.200s",
pw->pw_name, ttyname);
exit(254);
}
#endif /* LOGIN_CAP */
#endif /* HAVE_LOGIN_CAP */
#ifdef __FreeBSD__
if (chdir("/") < 0) {
(void)printf("Cannot find root directory\n");
@ -1136,9 +1200,9 @@ do_child(const char *command, struct passwd * pw, const char *term,
pw->pw_name, ttyname);
exit(254);
}
#ifdef LOGIN_CAP
#ifdef HAVE_LOGIN_CAP
quiet_login = login_getcapbool(lc, "hushlogin", 0);
#endif /* LOGIN_CAP */
#endif /* HAVE_LOGIN_CAP */
if (!quiet_login || *pw->pw_dir)
(void)printf(
"No home directory.\nLogging in with home = \"/\".\n");
@ -1149,9 +1213,9 @@ do_child(const char *command, struct passwd * pw, const char *term,
pw->pw_dir, strerror(errno));
#endif /* __FreeBSD__ */
}
#ifdef LOGIN_CAP
#ifdef HAVE_LOGIN_CAP
login_close(lc);
#endif /* LOGIN_CAP */
#endif /* HAVE_LOGIN_CAP */
/*
* Must take new environment into use so that .ssh/rc, /etc/sshrc and
@ -1186,38 +1250,38 @@ do_child(const char *command, struct passwd * pw, const char *term,
pclose(f);
} else
fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC);
}
#ifdef XAUTH_PATH
else {
} else if (options.xauth_location != NULL) {
/* Add authority data to .Xauthority if appropriate. */
if (auth_proto != NULL && auth_data != NULL) {
char *screen = strchr(display, ':');
if (debug_flag) {
fprintf(stderr,
"Running %.100s add %.100s %.100s %.100s\n",
XAUTH_PATH, display, auth_proto, auth_data);
options.xauth_location, display,
auth_proto, auth_data);
if (screen != NULL)
fprintf(stderr,
"Adding %.*s/unix%s %s %s\n",
screen-display, display,
(int)(screen-display), display,
screen, auth_proto, auth_data);
}
f = popen(XAUTH_PATH " -q -", "w");
snprintf(cmd, sizeof cmd, "%s -q -",
options.xauth_location);
f = popen(cmd, "w");
if (f) {
fprintf(f, "add %s %s %s\n", display,
auth_proto, auth_data);
if (screen != NULL)
fprintf(f, "add %.*s/unix%s %s %s\n",
screen-display, display,
(int)(screen-display), display,
screen, auth_proto, auth_data);
pclose(f);
} else
fprintf(stderr, "Could not run %s -q -\n",
XAUTH_PATH);
} else {
fprintf(stderr, "Could not run %s\n",
cmd);
}
}
}
#endif /* XAUTH_PATH */
/* Get the last component of the shell name. */
cp = strrchr(shell, '/');
if (cp)
@ -1273,8 +1337,8 @@ do_child(const char *command, struct passwd * pw, const char *term,
} else {
/* Launch login(1). */
execl("/usr/bin/login", "login", "-h", get_remote_ipaddr(),
"-p", "-f", "--", pw->pw_name, NULL);
execl("/usr/bin/login", "login", "-h", hostname,
"-p", "-f", "--", pw->pw_name, NULL);
/* Login couldn't be executed, die. */
@ -1412,6 +1476,8 @@ session_pty_req(Session *s)
unsigned int len;
char *term_modes; /* encoded terminal modes */
if (no_pty_flag)
return 0;
if (s->ttyfd != -1)
return 0;
s->term = packet_get_string(&len);
@ -1459,10 +1525,22 @@ session_subsystem_req(Session *s)
unsigned int len;
int success = 0;
char *subsys = packet_get_string(&len);
int i;
packet_done();
log("subsystem request for %s", subsys);
for (i = 0; i < options.num_subsystems; i++) {
if(strcmp(subsys, options.subsystem_name[i]) == 0) {
debug("subsystem: exec() %s", options.subsystem_command[i]);
do_exec_no_pty(s, options.subsystem_command[i], s->pw);
success = 1;
}
}
if (!success)
log("subsystem request for %s failed, subsystem not found", subsys);
xfree(subsys);
return success;
}
@ -1470,6 +1548,11 @@ session_subsystem_req(Session *s)
int
session_x11_req(Session *s)
{
int fd;
if (no_x11_forwarding_flag) {
debug("X11 forwarding disabled in user configuration file.");
return 0;
}
if (!options.x11_forwarding) {
debug("X11 forwarding disabled in server configuration file.");
return 0;
@ -1510,12 +1593,49 @@ session_x11_req(Session *s)
return 0;
}
strlcat(xauthfile, "/cookies", MAXPATHLEN);
open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);
fd = open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600);
if (fd >= 0)
close(fd);
restore_uid();
fatal_add_cleanup(xauthfile_cleanup_proc, s);
return 1;
}
int
session_shell_req(Session *s)
{
/* if forced_command == NULL, the shell is execed */
char *shell = forced_command;
packet_done();
s->extended = 1;
if (s->ttyfd == -1)
do_exec_no_pty(s, shell, s->pw);
else
do_exec_pty(s, shell, s->pw);
return 1;
}
int
session_exec_req(Session *s)
{
unsigned int len;
char *command = packet_get_string(&len);
packet_done();
if (forced_command) {
original_command = command;
command = forced_command;
debug("Forced command '%.500s'", forced_command);
}
s->extended = 1;
if (s->ttyfd == -1)
do_exec_no_pty(s, command, s->pw);
else
do_exec_pty(s, command, s->pw);
if (forced_command == NULL)
xfree(command);
return 1;
}
void
session_input_channel_req(int id, void *arg)
{
@ -1545,23 +1665,9 @@ session_input_channel_req(int id, void *arg)
*/
if (c->type == SSH_CHANNEL_LARVAL) {
if (strcmp(rtype, "shell") == 0) {
packet_done();
s->extended = 1;
if (s->ttyfd == -1)
do_exec_no_pty(s, NULL, s->pw);
else
do_exec_pty(s, NULL, s->pw);
success = 1;
success = session_shell_req(s);
} else if (strcmp(rtype, "exec") == 0) {
char *command = packet_get_string(&len);
packet_done();
s->extended = 1;
if (s->ttyfd == -1)
do_exec_no_pty(s, command, s->pw);
else
do_exec_pty(s, command, s->pw);
xfree(command);
success = 1;
success = session_exec_req(s);
} else if (strcmp(rtype, "pty-req") == 0) {
success = session_pty_req(s);
} else if (strcmp(rtype, "x11-req") == 0) {
@ -1765,11 +1871,24 @@ session_proctitle(Session *s)
void
do_authenticated2(void)
{
struct passwd *pw;
/*
* Cancel the alarm we set to limit the time taken for
* authentication.
*/
alarm(0);
if (startup_pipe != -1) {
close(startup_pipe);
startup_pipe = -1;
}
#ifdef HAVE_LOGIN_CAP
pw = auth_get_user();
if ((lc = login_getclass(pw->pw_class)) == NULL) {
error("unable to get login class");
return;
}
#endif
server_loop2();
if (xauthfile)
xauthfile_cleanup_proc(NULL);

View File

@ -1,20 +1,45 @@
/* $FreeBSD$ */
/* $OpenBSD: ssh-agent.c,v 1.31 2000/04/29 18:11:52 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Created: Wed Mar 29 03:46:59 1995 ylo
* The authentication agent program.
*
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* SSH2 implementation,
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: ssh-agent.c,v 1.31 2000/04/29 18:11:52 markus Exp $");
RCSID("$OpenBSD: ssh-agent.c,v 1.35 2000/09/07 20:27:54 deraadt Exp $");
RCSID("$FreeBSD$");
#include "ssh.h"
#include "rsa.h"
#include "authfd.h"
#include "buffer.h"
#include "bufaux.h"
#include "xmalloc.h"
@ -22,7 +47,14 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.31 2000/04/29 18:11:52 markus Exp $");
#include "getput.h"
#include "mpaux.h"
#include <openssl/evp.h>
#include <openssl/md5.h>
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include "key.h"
#include "authfd.h"
#include "dsa.h"
#include "kex.h"
typedef struct {
int fd;
@ -37,12 +69,17 @@ unsigned int sockets_alloc = 0;
SocketEntry *sockets = NULL;
typedef struct {
RSA *key;
Key *key;
char *comment;
} Identity;
unsigned int num_identities = 0;
Identity *identities = NULL;
typedef struct {
int nentries;
Identity *identities;
} Idtab;
/* private key table, one per protocol version */
Idtab idtable[3];
int max_fd = 0;
@ -56,175 +93,244 @@ char socket_dir[1024];
extern char *__progname;
void
process_request_identity(SocketEntry *e)
idtab_init(void)
{
int i;
for (i = 0; i <=2; i++){
idtable[i].identities = NULL;
idtable[i].nentries = 0;
}
}
/* return private key table for requested protocol version */
Idtab *
idtab_lookup(int version)
{
if (version < 1 || version > 2)
fatal("internal error, bad protocol version %d", version);
return &idtable[version];
}
/* return matching private key for given public key */
Key *
lookup_private_key(Key *key, int *idx, int version)
{
int i;
Idtab *tab = idtab_lookup(version);
for (i = 0; i < tab->nentries; i++) {
if (key_equal(key, tab->identities[i].key)) {
if (idx != NULL)
*idx = i;
return tab->identities[i].key;
}
}
return NULL;
}
/* send list of supported public keys to 'client' */
void
process_request_identities(SocketEntry *e, int version)
{
Idtab *tab = idtab_lookup(version);
Buffer msg;
int i;
buffer_init(&msg);
buffer_put_char(&msg, SSH_AGENT_RSA_IDENTITIES_ANSWER);
buffer_put_int(&msg, num_identities);
for (i = 0; i < num_identities; i++) {
buffer_put_int(&msg, BN_num_bits(identities[i].key->n));
buffer_put_bignum(&msg, identities[i].key->e);
buffer_put_bignum(&msg, identities[i].key->n);
buffer_put_string(&msg, identities[i].comment,
strlen(identities[i].comment));
buffer_put_char(&msg, (version == 1) ?
SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
buffer_put_int(&msg, tab->nentries);
for (i = 0; i < tab->nentries; i++) {
Identity *id = &tab->identities[i];
if (id->key->type == KEY_RSA) {
buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
buffer_put_bignum(&msg, id->key->rsa->e);
buffer_put_bignum(&msg, id->key->rsa->n);
} else {
unsigned char *blob;
unsigned int blen;
dsa_make_key_blob(id->key, &blob, &blen);
buffer_put_string(&msg, blob, blen);
xfree(blob);
}
buffer_put_cstring(&msg, id->comment);
}
buffer_put_int(&e->output, buffer_len(&msg));
buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
buffer_free(&msg);
}
/* ssh1 only */
void
process_authentication_challenge(SocketEntry *e)
process_authentication_challenge1(SocketEntry *e)
{
int i, pub_bits, len;
BIGNUM *pub_e, *pub_n, *challenge;
Key *key, *private;
BIGNUM *challenge;
int i, len;
Buffer msg;
MD5_CTX md;
unsigned char buf[32], mdbuf[16], session_id[16];
unsigned int response_type;
buffer_init(&msg);
pub_e = BN_new();
pub_n = BN_new();
key = key_new(KEY_RSA);
challenge = BN_new();
pub_bits = buffer_get_int(&e->input);
buffer_get_bignum(&e->input, pub_e);
buffer_get_bignum(&e->input, pub_n);
buffer_get_int(&e->input); /* ignored */
buffer_get_bignum(&e->input, key->rsa->e);
buffer_get_bignum(&e->input, key->rsa->n);
buffer_get_bignum(&e->input, challenge);
if (buffer_len(&e->input) == 0) {
/* Compatibility code for old servers. */
memset(session_id, 0, 16);
response_type = 0;
} else {
/* New code. */
buffer_get(&e->input, (char *) session_id, 16);
response_type = buffer_get_int(&e->input);
}
for (i = 0; i < num_identities; i++)
if (pub_bits == BN_num_bits(identities[i].key->n) &&
BN_cmp(pub_e, identities[i].key->e) == 0 &&
BN_cmp(pub_n, identities[i].key->n) == 0) {
/* Decrypt the challenge using the private key. */
rsa_private_decrypt(challenge, challenge, identities[i].key);
/* Compute the desired response. */
switch (response_type) {
case 0:/* As of protocol 1.0 */
/* This response type is no longer supported. */
log("Compatibility with ssh protocol 1.0 no longer supported.");
buffer_put_char(&msg, SSH_AGENT_FAILURE);
goto send;
/* Only protocol 1.1 is supported */
if (buffer_len(&e->input) == 0)
goto failure;
buffer_get(&e->input, (char *) session_id, 16);
response_type = buffer_get_int(&e->input);
if (response_type != 1)
goto failure;
case 1:/* As of protocol 1.1 */
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
private = lookup_private_key(key, NULL, 1);
if (private != NULL) {
/* Decrypt the challenge using the private key. */
rsa_private_decrypt(challenge, challenge, private->rsa);
if (len <= 0 || len > 32) {
fatal("process_authentication_challenge: "
"bad challenge length %d", len);
}
memset(buf, 0, 32);
BN_bn2bin(challenge, buf + 32 - len);
MD5_Init(&md);
MD5_Update(&md, buf, 32);
MD5_Update(&md, session_id, 16);
MD5_Final(mdbuf, &md);
break;
default:
fatal("process_authentication_challenge: bad response_type %d",
response_type);
break;
}
/* Send the response. */
buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
for (i = 0; i < 16; i++)
buffer_put_char(&msg, mdbuf[i]);
goto send;
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
if (len <= 0 || len > 32) {
log("process_authentication_challenge: bad challenge length %d", len);
goto failure;
}
/* Unknown identity. Send failure. */
memset(buf, 0, 32);
BN_bn2bin(challenge, buf + 32 - len);
MD5_Init(&md);
MD5_Update(&md, buf, 32);
MD5_Update(&md, session_id, 16);
MD5_Final(mdbuf, &md);
/* Send the response. */
buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
for (i = 0; i < 16; i++)
buffer_put_char(&msg, mdbuf[i]);
goto send;
}
failure:
/* Unknown identity or protocol error. Send failure. */
buffer_put_char(&msg, SSH_AGENT_FAILURE);
send:
buffer_put_int(&e->output, buffer_len(&msg));
buffer_append(&e->output, buffer_ptr(&msg),
buffer_len(&msg));
buffer_free(&msg);
BN_clear_free(pub_e);
BN_clear_free(pub_n);
buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
key_free(key);
BN_clear_free(challenge);
buffer_free(&msg);
}
/* ssh2 only */
void
process_remove_identity(SocketEntry *e)
process_sign_request2(SocketEntry *e)
{
extern int datafellows;
Key *key, *private;
unsigned char *blob, *data, *signature = NULL;
unsigned int blen, dlen, slen = 0;
Buffer msg;
int ok = -1;
datafellows = 0;
blob = buffer_get_string(&e->input, &blen);
data = buffer_get_string(&e->input, &dlen);
buffer_get_int(&e->input); /* flags, unused */
key = dsa_key_from_blob(blob, blen);
if (key != NULL) {
private = lookup_private_key(key, NULL, 2);
if (private != NULL)
ok = dsa_sign(private, &signature, &slen, data, dlen);
}
key_free(key);
buffer_init(&msg);
if (ok == 0) {
buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE);
buffer_put_string(&msg, signature, slen);
} else {
buffer_put_char(&msg, SSH_AGENT_FAILURE);
}
buffer_put_int(&e->output, buffer_len(&msg));
buffer_append(&e->output, buffer_ptr(&msg),
buffer_len(&msg));
buffer_free(&msg);
xfree(data);
xfree(blob);
if (signature != NULL)
xfree(signature);
}
/* shared */
void
process_remove_identity(SocketEntry *e, int version)
{
Key *key = NULL, *private;
unsigned char *blob;
unsigned int blen;
unsigned int bits;
unsigned int i;
BIGNUM *dummy, *n;
int success = 0;
dummy = BN_new();
n = BN_new();
switch(version){
case 1:
key = key_new(KEY_RSA);
bits = buffer_get_int(&e->input);
buffer_get_bignum(&e->input, key->rsa->e);
buffer_get_bignum(&e->input, key->rsa->n);
/* Get the key from the packet. */
bits = buffer_get_int(&e->input);
buffer_get_bignum(&e->input, dummy);
buffer_get_bignum(&e->input, n);
if (bits != BN_num_bits(n))
log("Warning: identity keysize mismatch: actual %d, announced %d",
BN_num_bits(n), bits);
/* Check if we have the key. */
for (i = 0; i < num_identities; i++)
if (BN_cmp(identities[i].key->n, n) == 0) {
if (bits != key_size(key))
log("Warning: identity keysize mismatch: actual %d, announced %d",
key_size(key), bits);
break;
case 2:
blob = buffer_get_string(&e->input, &blen);
key = dsa_key_from_blob(blob, blen);
xfree(blob);
break;
}
if (key != NULL) {
int idx;
private = lookup_private_key(key, &idx, version);
if (private != NULL) {
/*
* We have this key. Free the old key. Since we
* don\'t want to leave empty slots in the middle of
* the array, we actually free the key there and copy
* data from the last entry.
*/
RSA_free(identities[i].key);
xfree(identities[i].comment);
if (i < num_identities - 1)
identities[i] = identities[num_identities - 1];
num_identities--;
BN_clear_free(dummy);
BN_clear_free(n);
/* Send success. */
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
return;
Idtab *tab = idtab_lookup(version);
key_free(tab->identities[idx].key);
xfree(tab->identities[idx].comment);
if (idx != tab->nentries)
tab->identities[idx] = tab->identities[tab->nentries];
tab->nentries--;
success = 1;
}
/* We did not have the key. */
BN_clear(dummy);
BN_clear(n);
/* Send failure. */
key_free(key);
}
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output, SSH_AGENT_FAILURE);
buffer_put_char(&e->output,
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
}
/*
* Removes all identities from the agent.
*/
void
process_remove_all_identities(SocketEntry *e)
process_remove_all_identities(SocketEntry *e, int version)
{
unsigned int i;
Idtab *tab = idtab_lookup(version);
/* Loop over all identities and clear the keys. */
for (i = 0; i < num_identities; i++) {
RSA_free(identities[i].key);
xfree(identities[i].comment);
for (i = 0; i < tab->nentries; i++) {
key_free(tab->identities[i].key);
xfree(tab->identities[i].comment);
}
/* Mark that there are no identities. */
num_identities = 0;
tab->nentries = 0;
/* Send success. */
buffer_put_int(&e->output, 1);
@ -232,79 +338,108 @@ process_remove_all_identities(SocketEntry *e)
return;
}
/*
* Adds an identity to the agent.
*/
void
process_add_identity(SocketEntry *e)
process_add_identity(SocketEntry *e, int version)
{
RSA *k;
int i;
Key *k = NULL;
RSA *rsa;
BIGNUM *aux;
BN_CTX *ctx;
char *type;
char *comment;
int success = 0;
Idtab *tab = idtab_lookup(version);
if (num_identities == 0)
identities = xmalloc(sizeof(Identity));
else
identities = xrealloc(identities, (num_identities + 1) * sizeof(Identity));
switch (version) {
case 1:
k = key_new(KEY_RSA);
rsa = k->rsa;
identities[num_identities].key = RSA_new();
k = identities[num_identities].key;
buffer_get_int(&e->input); /* bits */
k->n = BN_new();
buffer_get_bignum(&e->input, k->n);
k->e = BN_new();
buffer_get_bignum(&e->input, k->e);
k->d = BN_new();
buffer_get_bignum(&e->input, k->d);
k->iqmp = BN_new();
buffer_get_bignum(&e->input, k->iqmp);
/* SSH and SSL have p and q swapped */
k->q = BN_new();
buffer_get_bignum(&e->input, k->q); /* p */
k->p = BN_new();
buffer_get_bignum(&e->input, k->p); /* q */
/* allocate mem for private key */
/* XXX rsa->n and rsa->e are already allocated */
rsa->d = BN_new();
rsa->iqmp = BN_new();
rsa->q = BN_new();
rsa->p = BN_new();
rsa->dmq1 = BN_new();
rsa->dmp1 = BN_new();
/* Generate additional parameters */
aux = BN_new();
ctx = BN_CTX_new();
buffer_get_int(&e->input); /* ignored */
BN_sub(aux, k->q, BN_value_one());
k->dmq1 = BN_new();
BN_mod(k->dmq1, k->d, aux, ctx);
buffer_get_bignum(&e->input, rsa->n);
buffer_get_bignum(&e->input, rsa->e);
buffer_get_bignum(&e->input, rsa->d);
buffer_get_bignum(&e->input, rsa->iqmp);
BN_sub(aux, k->p, BN_value_one());
k->dmp1 = BN_new();
BN_mod(k->dmp1, k->d, aux, ctx);
/* SSH and SSL have p and q swapped */
buffer_get_bignum(&e->input, rsa->q); /* p */
buffer_get_bignum(&e->input, rsa->p); /* q */
BN_clear_free(aux);
BN_CTX_free(ctx);
/* Generate additional parameters */
aux = BN_new();
ctx = BN_CTX_new();
identities[num_identities].comment = buffer_get_string(&e->input, NULL);
BN_sub(aux, rsa->q, BN_value_one());
BN_mod(rsa->dmq1, rsa->d, aux, ctx);
/* Check if we already have the key. */
for (i = 0; i < num_identities; i++)
if (BN_cmp(identities[i].key->n, k->n) == 0) {
/*
* We already have this key. Clear and free the new
* data and return success.
*/
RSA_free(k);
xfree(identities[num_identities].comment);
BN_sub(aux, rsa->p, BN_value_one());
BN_mod(rsa->dmp1, rsa->d, aux, ctx);
/* Send success. */
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
return;
BN_clear_free(aux);
BN_CTX_free(ctx);
break;
case 2:
type = buffer_get_string(&e->input, NULL);
if (strcmp(type, KEX_DSS)) {
buffer_clear(&e->input);
xfree(type);
goto send;
}
/* Increment the number of identities. */
num_identities++;
xfree(type);
/* Send a success message. */
k = key_new(KEY_DSA);
/* allocate mem for private key */
k->dsa->priv_key = BN_new();
buffer_get_bignum2(&e->input, k->dsa->p);
buffer_get_bignum2(&e->input, k->dsa->q);
buffer_get_bignum2(&e->input, k->dsa->g);
buffer_get_bignum2(&e->input, k->dsa->pub_key);
buffer_get_bignum2(&e->input, k->dsa->priv_key);
break;
}
comment = buffer_get_string(&e->input, NULL);
if (k == NULL) {
xfree(comment);
goto send;
}
success = 1;
if (lookup_private_key(k, NULL, version) == NULL) {
if (tab->nentries == 0)
tab->identities = xmalloc(sizeof(Identity));
else
tab->identities = xrealloc(tab->identities,
(tab->nentries + 1) * sizeof(Identity));
tab->identities[tab->nentries].key = k;
tab->identities[tab->nentries].comment = comment;
/* Increment the number of identities. */
tab->nentries++;
} else {
key_free(k);
xfree(comment);
}
send:
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
buffer_put_char(&e->output,
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
}
/* dispatch incoming messages */
void
process_message(SocketEntry *e)
{
@ -327,20 +462,37 @@ process_message(SocketEntry *e)
type = buffer_get_char(&e->input);
switch (type) {
case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
process_request_identity(e);
break;
/* ssh1 */
case SSH_AGENTC_RSA_CHALLENGE:
process_authentication_challenge(e);
process_authentication_challenge1(e);
break;
case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
process_request_identities(e, 1);
break;
case SSH_AGENTC_ADD_RSA_IDENTITY:
process_add_identity(e);
process_add_identity(e, 1);
break;
case SSH_AGENTC_REMOVE_RSA_IDENTITY:
process_remove_identity(e);
process_remove_identity(e, 1);
break;
case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
process_remove_all_identities(e);
process_remove_all_identities(e, 1);
break;
/* ssh2 */
case SSH2_AGENTC_SIGN_REQUEST:
process_sign_request2(e);
break;
case SSH2_AGENTC_REQUEST_IDENTITIES:
process_request_identities(e, 2);
break;
case SSH2_AGENTC_ADD_IDENTITY:
process_add_identity(e, 2);
break;
case SSH2_AGENTC_REMOVE_IDENTITY:
process_remove_identity(e, 2);
break;
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
process_remove_all_identities(e, 2);
break;
default:
/* Unknown message. Respond with failure. */
@ -537,7 +689,7 @@ main(int ac, char **av)
if (ac > 0 && (c_flag || k_flag || s_flag))
usage();
if (ac == 0 && !c_flag && !s_flag) {
if (ac == 0 && !c_flag && !k_flag && !s_flag) {
shell = getenv("SHELL");
if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
c_flag = 1;
@ -641,6 +793,7 @@ main(int ac, char **av)
signal(SIGALRM, check_parent_exists);
alarm(10);
}
idtab_init();
signal(SIGINT, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGHUP, cleanup_exit);

View File

@ -1,15 +1,39 @@
.\" -*- nroff -*-
.\"
.\" ssh.1.in
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\"
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
.\" All rights reserved
.\"
.\" Created: Sat Apr 22 21:55:14 1995 ylo
.\" 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
.\" software must be clearly marked as such, and if the derived work is
.\" incompatible with the protocol description in the RFC file, it must be
.\" called by a name other than "ssh" or "Secure Shell".
.\"
.\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved.
.\" Copyright (c) 1999 Aaron Campbell. All rights reserved.
.\" Copyright (c) 1999 Theo de Raadt. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $Id: ssh.1,v 1.54 2000/05/29 20:20:46 markus Exp $
.\" $FreeBSD$
.\"
.Dd September 25, 1999
@ -942,6 +966,13 @@ The argument must be
.Dq yes
or
.Dq no .
.It Cm XAuthLocation
Specifies the location of the
.Xr xauth 1
program.
The default is
.Pa /usr/X11R6/bin/xauth .
.El
.Sh ENVIRONMENT
.Nm
will normally set the following environment variables:
@ -1186,6 +1217,7 @@ above.
.It Pa libcrypto.so.X.1
A version of this library which includes support for the RSA algorithm
is required for proper operation.
.El
.Sh AUTHOR
OpenSSH
is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen,
@ -1214,10 +1246,6 @@ supports one-time password authentication with
.Xr skey 1 .
.El
.Pp
The libraries described in
.Xr ssl 8
are required for proper operation.
.Pp
OpenSSH has been created by Aaron Campbell, Bob Beck, Markus Friedl,
Niels Provos, Theo de Raadt, and Dug Song.
.Pp

View File

@ -2,18 +2,45 @@
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Created: Sat Mar 18 16:36:11 1995 ylo
* Ssh client program. This program can be used to log into a remote machine.
* The software supports strong authentication, encryption, and forwarding
* of X11, TCP/IP, and authentication connections.
*
* Modified to work with SSL by Niels Provos <provos@citi.umich.edu> in Canada.
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* $FreeBSD$
* Copyright (c) 1999 Niels Provos. All rights reserved.
*
* Modified to work with SSL by Niels Provos <provos@citi.umich.edu>
* in Canada (German citizen).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$Id: ssh.c,v 1.54 2000/05/30 17:32:06 markus Exp $");
RCSID("$OpenBSD: ssh.c,v 1.65 2000/09/07 20:40:30 markus Exp $");
RCSID("$FreeBSD$");
#include <openssl/evp.h>
#include <openssl/dsa.h>
@ -23,7 +50,6 @@ RCSID("$Id: ssh.c,v 1.54 2000/05/30 17:32:06 markus Exp $");
#include "ssh.h"
#include "packet.h"
#include "buffer.h"
#include "authfd.h"
#include "readconf.h"
#include "uidswap.h"
@ -31,6 +57,7 @@ RCSID("$Id: ssh.c,v 1.54 2000/05/30 17:32:06 markus Exp $");
#include "compat.h"
#include "channels.h"
#include "key.h"
#include "authfd.h"
#include "authfile.h"
extern char *__progname;
@ -117,7 +144,6 @@ usage()
#endif /* AFS */
fprintf(stderr, " -X Enable X11 connection forwarding.\n");
fprintf(stderr, " -x Disable X11 connection forwarding.\n");
fprintf(stderr, " -X Enable X11 connection forwarding.\n");
fprintf(stderr, " -i file Identity for RSA authentication (default: ~/.ssh/identity).\n");
fprintf(stderr, " -t Tty; allocate a tty even if command is given.\n");
fprintf(stderr, " -T Do not allocate a tty.\n");
@ -249,8 +275,8 @@ main(int ac, char **av)
cp = strrchr(av0, '/') + 1;
else
cp = av0;
if (strcmp(cp, "rsh") != 0 && strcmp(cp, "ssh") != 0 &&
strcmp(cp, "rlogin") != 0 && strcmp(cp, "slogin") != 0)
if (strcmp(cp, "rsh") && strcmp(cp, "ssh") && strcmp(cp, "rlogin") &&
strcmp(cp, "slogin") && strcmp(cp, "remsh"))
host = cp;
for (optind = 1; optind < ac; optind++) {
@ -458,7 +484,7 @@ main(int ac, char **av)
}
/* Cannot fork to background if no command. */
if (fork_after_authentication_flag && buffer_len(&command) == 0)
if (fork_after_authentication_flag && buffer_len(&command) == 0 && !no_shell_flag)
fatal("Cannot fork into background without a command to execute.");
/* Allocate a tty by default if no command specified. */
@ -487,6 +513,7 @@ main(int ac, char **av)
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
pwcopy.pw_uid = pw->pw_uid;
pwcopy.pw_gid = pw->pw_gid;
pwcopy.pw_class = xstrdup(pw->pw_class);
pwcopy.pw_dir = xstrdup(pw->pw_dir);
pwcopy.pw_shell = xstrdup(pw->pw_shell);
pwcopy.pw_class = xstrdup(pw->pw_class);
@ -622,7 +649,7 @@ main(int ac, char **av)
*/
snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_DIR);
if (stat(buf, &st) < 0)
if (mkdir(buf, 0755) < 0)
if (mkdir(buf, 0700) < 0)
error("Could not create directory '%.200s'.", buf);
/* Check if the connection failed, and try "rsh" if appropriate. */
@ -679,17 +706,17 @@ x11_get_proto(char *proto, int proto_len, char *data, int data_len)
FILE *f;
int got_data = 0, i;
#ifdef XAUTH_PATH
/* Try to get Xauthority information for the display. */
snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null",
XAUTH_PATH, getenv("DISPLAY"));
f = popen(line, "r");
if (f && fgets(line, sizeof(line), f) &&
sscanf(line, "%*s %s %s", proto, data) == 2)
got_data = 1;
if (f)
pclose(f);
#endif /* XAUTH_PATH */
if (options.xauth_location) {
/* Try to get Xauthority information for the display. */
snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null",
options.xauth_location, getenv("DISPLAY"));
f = popen(line, "r");
if (f && fgets(line, sizeof(line), f) &&
sscanf(line, "%*s %s %s", proto, data) == 2)
got_data = 1;
if (f)
pclose(f);
}
/*
* If we didn't get authentication data, just make up some
* data. The forwarding code will check the validity of the
@ -871,7 +898,7 @@ ssh_session(void)
}
/* Enter the interactive session. */
return client_loop(have_tty, tty_flag ? options.escape_char : -1);
return client_loop(have_tty, tty_flag ? options.escape_char : -1, 0);
}
void
@ -954,31 +981,40 @@ int
ssh_session2(void)
{
int window, packetmax, id;
int in = dup(STDIN_FILENO);
int out = dup(STDOUT_FILENO);
int err = dup(STDERR_FILENO);
int in, out, err;
if (stdin_null_flag) {
in = open("/dev/null", O_RDONLY);
} else {
in = dup(STDIN_FILENO);
}
out = dup(STDOUT_FILENO);
err = dup(STDERR_FILENO);
if (in < 0 || out < 0 || err < 0)
fatal("dump in/out/err failed");
fatal("dup() in/out/err failed");
/* should be pre-session */
init_local_fwd();
window = 32*1024;
if (tty_flag) {
packetmax = window/8;
} else {
window *= 2;
packetmax = window/2;
}
/* If requested, let ssh continue in the background. */
if (fork_after_authentication_flag)
if (daemon(1, 1) < 0)
fatal("daemon() failed: %.200s", strerror(errno));
window = CHAN_SES_WINDOW_DEFAULT;
packetmax = CHAN_SES_PACKET_DEFAULT;
if (!tty_flag) {
window *= 2;
packetmax *=2;
}
id = channel_new(
"session", SSH_CHANNEL_OPENING, in, out, err,
window, packetmax, CHAN_EXTENDED_WRITE, xstrdup("client-session"));
window, packetmax, CHAN_EXTENDED_WRITE,
xstrdup("client-session"));
channel_open(id);
channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0);
return client_loop(tty_flag, tty_flag ? options.escape_char : -1);
return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id);
}

View File

@ -1,20 +1,19 @@
/*
*
* ssh.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Fri Mar 17 17:09:37 1995 ylo
*
* Generic header file for ssh.
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
/* RCSID("$Id: ssh.h,v 1.46 2000/05/17 08:20:15 markus Exp $"); */
/* RCSID("$OpenBSD: ssh.h,v 1.50 2000/09/07 20:27:54 deraadt Exp $"); */
/* $FreeBSD$ */
#ifndef SSH_H
#define SSH_H
@ -463,6 +462,9 @@ char *tilde_expand_filename(const char *filename, uid_t my_uid);
/* remove newline at end of string */
char *chop(char *s);
/* return next token in configuration line */
char *strdelim(char **s);
/* set filedescriptor to non-blocking */
void set_nonblock(int fd);
@ -477,7 +479,7 @@ void server_loop(pid_t pid, int fdin, int fdout, int fderr);
void server_loop2(void);
/* Client side main loop for the interactive session. */
int client_loop(int have_pty, int escape_char);
int client_loop(int have_pty, int escape_char, int id);
/* Linked list of custom environment strings (see auth-rsa.c). */
struct envstring {

View File

@ -2,15 +2,19 @@
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Created: Sat Mar 18 22:15:47 1995 ylo
* Code to connect to a remote host, and to perform the client side of the
* login (authentication) dialog.
*
* $FreeBSD$
*
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
RCSID("$OpenBSD: sshconnect.c,v 1.74 2000/05/17 16:57:02 markus Exp $");
RCSID("$OpenBSD: sshconnect.c,v 1.78 2000/09/07 20:27:54 deraadt Exp $");
RCSID("$FreeBSD$");
#include <openssl/bn.h>
#include <openssl/dsa.h>
@ -191,8 +195,8 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
int gaierr;
struct linger linger;
debug("ssh_connect: getuid %d geteuid %d anon %d",
(int) getuid(), (int) geteuid(), anonymous);
debug("ssh_connect: getuid %u geteuid %u anon %d",
(u_int) getuid(), (u_int) geteuid(), anonymous);
/* Get default port if port has not been set. */
if (port == 0) {
@ -312,23 +316,28 @@ ssh_exchange_identification()
int connection_out = packet_get_connection_out();
/* Read other side\'s version identification. */
for (i = 0; i < sizeof(buf) - 1; i++) {
int len = read(connection_in, &buf[i], 1);
if (len < 0)
fatal("ssh_exchange_identification: read: %.100s", strerror(errno));
if (len != 1)
fatal("ssh_exchange_identification: Connection closed by remote host");
if (buf[i] == '\r') {
buf[i] = '\n';
buf[i + 1] = 0;
continue; /**XXX wait for \n */
for (;;) {
for (i = 0; i < sizeof(buf) - 1; i++) {
int len = atomicio(read, connection_in, &buf[i], 1);
if (len < 0)
fatal("ssh_exchange_identification: read: %.100s", strerror(errno));
if (len != 1)
fatal("ssh_exchange_identification: Connection closed by remote host");
if (buf[i] == '\r') {
buf[i] = '\n';
buf[i + 1] = 0;
continue; /**XXX wait for \n */
}
if (buf[i] == '\n') {
buf[i + 1] = 0;
break;
}
}
if (buf[i] == '\n') {
buf[i + 1] = 0;
buf[sizeof(buf) - 1] = 0;
if (strncmp(buf, "SSH-", 4) == 0)
break;
}
debug("ssh_exchange_identification: %s", buf);
}
buf[sizeof(buf) - 1] = 0;
server_version_string = xstrdup(buf);
/*
@ -899,7 +908,7 @@ ssh_login(int host_key_valid, RSA *own_host_key, const char *orighost,
/* Get local user name. Use it as server user if no user name was given. */
pw = getpwuid(original_real_uid);
if (!pw)
fatal("User id %d not found from user database.", original_real_uid);
fatal("User id %u not found from user database.", original_real_uid);
local_user = xstrdup(pw->pw_name);
server_user = options.user ? options.user : local_user;

View File

@ -2,15 +2,19 @@
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Created: Sat Mar 18 22:15:47 1995 ylo
* Code to connect to a remote host, and to perform the client side of the
* login (authentication) dialog.
*
* $FreeBSD$
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
RCSID("$OpenBSD: sshconnect1.c,v 1.3 2000/05/08 17:12:16 markus Exp $");
RCSID("$OpenBSD: sshconnect1.c,v 1.6 2000/09/07 20:27:54 deraadt Exp $");
RCSID("$FreeBSD$");
#include <openssl/bn.h>
#include <openssl/dsa.h>
@ -22,12 +26,12 @@ RCSID("$OpenBSD: sshconnect1.c,v 1.3 2000/05/08 17:12:16 markus Exp $");
#include "ssh.h"
#include "buffer.h"
#include "packet.h"
#include "authfd.h"
#include "cipher.h"
#include "mpaux.h"
#include "uidswap.h"
#include "readconf.h"
#include "key.h"
#include "authfd.h"
#include "sshconnect.h"
#include "authfile.h"
@ -45,27 +49,27 @@ extern char *__progname;
int
try_agent_authentication()
{
int status, type;
int type;
char *comment;
AuthenticationConnection *auth;
unsigned char response[16];
unsigned int i;
BIGNUM *e, *n, *challenge;
int plen, clen;
Key *key;
BIGNUM *challenge;
/* Get connection to the agent. */
auth = ssh_get_authentication_connection();
if (!auth)
return 0;
e = BN_new();
n = BN_new();
challenge = BN_new();
key = key_new(KEY_RSA);
/* Loop through identities served by the agent. */
for (status = ssh_get_first_identity(auth, e, n, &comment);
status;
status = ssh_get_next_identity(auth, e, n, &comment)) {
int plen, clen;
for (key = ssh_get_first_identity(auth, &comment, 1);
key != NULL;
key = ssh_get_next_identity(auth, &comment, 1)) {
/* Try this identity. */
debug("Trying RSA authentication via agent with '%.100s'", comment);
@ -73,7 +77,7 @@ try_agent_authentication()
/* Tell the server that we are willing to authenticate using this key. */
packet_start(SSH_CMSG_AUTH_RSA);
packet_put_bignum(n);
packet_put_bignum(key->rsa->n);
packet_send();
packet_write_wait();
@ -84,6 +88,7 @@ try_agent_authentication()
does not support RSA authentication. */
if (type == SSH_SMSG_FAILURE) {
debug("Server refused our key.");
key_free(key);
continue;
}
/* Otherwise it should have sent a challenge. */
@ -98,13 +103,16 @@ try_agent_authentication()
debug("Received RSA challenge from server.");
/* Ask the agent to decrypt the challenge. */
if (!ssh_decrypt_challenge(auth, e, n, challenge,
session_id, 1, response)) {
/* The agent failed to authenticate this identifier although it
advertised it supports this. Just return a wrong value. */
if (!ssh_decrypt_challenge(auth, key, challenge, session_id, 1, response)) {
/*
* The agent failed to authenticate this identifier
* although it advertised it supports this. Just
* return a wrong value.
*/
log("Authentication agent failed to decrypt challenge.");
memset(response, 0, sizeof(response));
}
key_free(key);
debug("Sending response to RSA challenge.");
/* Send the decrypted challenge back to the server. */
@ -119,10 +127,8 @@ try_agent_authentication()
/* The server returns success if it accepted the authentication. */
if (type == SSH_SMSG_SUCCESS) {
debug("RSA authentication accepted by server.");
BN_clear_free(e);
BN_clear_free(n);
BN_clear_free(challenge);
debug("RSA authentication accepted by server.");
return 1;
}
/* Otherwise it should return failure. */
@ -130,11 +136,7 @@ try_agent_authentication()
packet_disconnect("Protocol error waiting RSA auth response: %d",
type);
}
BN_clear_free(e);
BN_clear_free(n);
BN_clear_free(challenge);
debug("RSA authentication using agent refused.");
return 0;
}

View File

@ -1,15 +1,39 @@
.\" -*- nroff -*-
.\"
.\" sshd.8.in
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\"
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
.\" All rights reserved
.\"
.\" Created: Sat Apr 22 21:55:14 1995 ylo
.\" 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
.\" software must be clearly marked as such, and if the derived work is
.\" incompatible with the protocol description in the RFC file, it must be
.\" called by a name other than "ssh" or "Secure Shell".
.\"
.\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved.
.\" Copyright (c) 1999 Aaron Campbell. All rights reserved.
.\" Copyright (c) 1999 Theo de Raadt. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $Id: sshd.8,v 1.51 2000/05/08 17:42:31 hugh Exp $
.\" $FreeBSD$
.\"
.Dd September 25, 1999
@ -27,6 +51,7 @@
.Op Fl h Ar host_key_file
.Op Fl k Ar key_gen_time
.Op Fl p Ar port
.Op Fl u Ar len
.Op Fl V Ar client_protocol_id
.Sh DESCRIPTION
.Nm
@ -105,7 +130,7 @@ into the machine).
.Pp
.Ss SSH protocol version 2
.Pp
Version 2 works similar:
Version 2 works similarly:
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.
Forward security is provided through a Diffie-Hellman key agreement.
@ -212,6 +237,22 @@ Quiet mode.
Nothing is sent to the system log.
Normally the beginning,
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
Do not print an error message if RSA support is missing.
.It Fl V Ar client_protocol_id
@ -258,7 +299,7 @@ and
.Ql ?
can be used as
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.
.Pp
.It Cm AllowUsers
@ -271,7 +312,7 @@ and
.Ql ?
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.
.Pp
.It Cm Ciphers
@ -320,7 +361,7 @@ and
.Ql ?
can be used as
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.
.Pp
.It Cm DenyUsers
@ -331,7 +372,7 @@ Login is disallowed for user names that match one of the patterns.
and
.Ql ?
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.
.It Cm DSAAuthentication
Specifies whether DSA authentication is allowed.
@ -347,7 +388,7 @@ or
.Dq no .
The default is
.Dq no .
.It Cm HostDsaKey
.It Cm HostDSAKey
Specifies the file containing the private DSA host key (default
.Pa /etc/ssh/ssh_host_dsa_key )
used by SSH protocol 2.0.
@ -409,7 +450,8 @@ Specifies whether Kerberos authentication is allowed.
This can be in the form of a Kerberos ticket, or if
.Cm PasswordAuthentication
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
.Dq yes .
.It Cm KerberosOrLocalPasswd
@ -461,11 +503,36 @@ QUIET, FATAL, ERROR, INFO, VERBOSE and DEBUG.
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.
.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
Specifies whether password authentication is allowed.
The default is
.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
When password authentication is allowed, it specifies whether the
server allows login to accounts with empty password strings.
@ -574,6 +641,16 @@ This is normally desirable because novices sometimes accidentally leave their
directory or files world-writable.
The default is
.Dq yes .
.It Cm Subsystem
Configures an external subsystem (e.g. file transfer daemon).
Arguments should be a subsystem name and a command to execute upon subsystem request.
The command
.Xr sftp-server 8
implements the
.Dq sftp
file transfer subsystem.
By default no subsystems are defined.
Note that this option applies to protocol version 2 only.
.It Cm SyslogFacility
Gives the facility code that is used when logging messages from
.Nm sshd .
@ -583,7 +660,10 @@ The default is AUTH.
.It Cm UseLogin
Specifies whether
.Xr login 1
is used.
is used for interactive login sessions.
Note that
.Xr login 1
is never used for remote command execution.
The default is
.Dq no .
.It Cm X11DisplayOffset
@ -600,6 +680,12 @@ The default is
.Dq no .
Note that disabling X11 forwarding does not improve security in any
way, as users can always install their own forwarders.
.It Cm XAuthLocation
Specifies the location of the
.Xr xauth 1
program.
The default is
.Pa /usr/X11R6/bin/xauth .
.El
.Sh LOGIN PROCESS
When a user successfully logs in,
@ -677,7 +763,7 @@ You don't want to type them in; instead, copy the
.Pa identity.pub
file and edit it.
.Pp
The options (if present) consists of comma-separated option
The options (if present) consist of comma-separated option
specifications.
No spaces are permitted, except within double quotes.
The following option specifications are supported:
@ -751,7 +837,7 @@ and
files contain host public keys for all known hosts.
The global file should
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.
.Pp
Each line in these files contains the following fields: hostnames,
@ -828,7 +914,7 @@ Contains the process ID of the
listening for connections (if there are several daemons running
concurrently for different ports, this contains the pid of the one
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
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
@ -856,7 +942,7 @@ These files are consulted when using rhosts with RSA host
authentication to check the public key of the host.
The key must be listed in one of these files to be accepted.
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.
.Pa /etc/ssh/ssh_known_hosts
should be world-readable, and
@ -983,6 +1069,7 @@ Like
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,
@ -1011,16 +1098,13 @@ supports one-time password authentication with
.Xr skey 1 .
.El
.Pp
The libraries described in
.Xr ssl 8
are required for proper operation.
.Pp
OpenSSH has been created by Aaron Campbell, Bob Beck, Markus Friedl,
Niels Provos, Theo de Raadt, and Dug Song.
.Pp
The support for SSH protocol 2 was written by Markus Friedl.
.Sh SEE ALSO
.Xr scp 1 ,
.Xr sftp-server 8 ,
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-agent 1 ,

View File

@ -2,21 +2,46 @@
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Created: Fri Mar 17 17:09:28 1995 ylo
* This program is the ssh daemon. It listens for connections from clients, and
* performs authentication, executes use commands or shell, and forwards
* This program is the ssh daemon. It listens for connections from clients,
* and performs authentication, executes use commands or shell, and forwards
* information to/from the application to the user client over an encrypted
* connection. This can also handle forwarding of X11, TCP/IP, and authentication
* agent connections.
* connection. This can also handle forwarding of X11, TCP/IP, and
* authentication agent connections.
*
* SSH2 implementation,
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* 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
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* $FreeBSD$
* SSH2 implementation:
*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: sshd.c,v 1.118 2000/05/25 20:45:20 markus Exp $");
RCSID("$OpenBSD: sshd.c,v 1.126 2000/09/07 20:27:55 deraadt Exp $");
RCSID("$FreeBSD$");
#include "xmalloc.h"
#include "rsa.h"
@ -168,6 +193,9 @@ timevaldiff(struct timeval *tv1, struct timeval *tv2) {
return diff;
}
/* record remote hostname or ip */
unsigned int utmp_len = MAXHOSTNAMELEN;
/* Prototypes for various functions defined later in this file. */
void do_ssh1_kex();
void do_ssh2_kex();
@ -327,7 +355,7 @@ sshd_exchange_identification(int sock_in, int sock_out)
/* Read other side\'s version identification. */
for (i = 0; i < sizeof(buf) - 1; i++) {
if (read(sock_in, &buf[i], 1) != 1) {
if (atomicio(read, sock_in, &buf[i], 1) != 1) {
log("Did not receive ident string from %s.", get_remote_ipaddr());
fatal_cleanup();
}
@ -380,7 +408,7 @@ sshd_exchange_identification(int sock_in, int sock_out)
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 */
@ -430,6 +458,38 @@ destroy_sensitive_data(void)
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_pipe; /* in child */
/*
* Main program for the daemon.
*/
@ -438,7 +498,7 @@ main(int ac, char **av)
{
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 ratelim_exceeded = 0;
@ -452,6 +512,8 @@ main(int ac, char **av)
struct addrinfo *ai;
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
int listen_sock, maxfd;
int startup_p[2];
int startups = 0;
/* Save argv[0]. */
saved_argv = av;
@ -464,7 +526,7 @@ main(int ac, char **av)
initialize_server_options(&options);
/* 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) {
case '4':
IPv4or6 = AF_INET;
@ -511,6 +573,9 @@ main(int ac, char **av)
/* only makes sense with inetd_flag, i.e. no listen() */
inetd_flag = 1;
break;
case 'u':
utmp_len = atoi(optarg);
break;
case '?':
default:
fprintf(stderr, "sshd version %s\n", SSH_VERSION);
@ -526,6 +591,7 @@ main(int ac, char **av)
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",
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);
@ -665,6 +731,7 @@ main(int ac, char **av)
s2 = dup(s1);
sock_in = dup(0);
sock_out = dup(1);
startup_pipe = -1;
/*
* We intentionally do not close the descriptors 0, 1, and 2
* as our code for setting the descriptors won\'t work if
@ -773,6 +840,7 @@ main(int ac, char **av)
/* Arrange to restart on SIGHUP. The handler needs listen_sock. */
signal(SIGHUP, sighup_handler);
signal(SIGTERM, sigterm_handler);
signal(SIGQUIT, sigterm_handler);
@ -780,12 +848,15 @@ main(int ac, char **av)
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;
ratelim_init();
@ -796,116 +867,165 @@ main(int ac, char **av)
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;
}
if (options.connections_per_period != 0) {
struct timeval diff, connections_end;
struct ratelim_connection *rc;
(void)gettimeofday(&connections_end, NULL);
rc = &ratelim_connections[i];
diff = timevaldiff(&rc->connections_begin,
&connections_end);
if (diff.tv_sec >= options.connections_period) {
/*
* Slide the window forward only after
* completely leaving it.
*/
rc->connections_begin = connections_end;
rc->connections_this_period = 1;
} else {
if (++rc->connections_this_period >
options.connections_per_period)
ratelim_exceeded = 1;
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 (drop_connection(startups) == 1) {
debug("drop connection #%d", 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;
}
if (options.connections_per_period != 0) {
struct timeval diff, connections_end;
struct ratelim_connection *rc;
(void)gettimeofday(&connections_end, NULL);
rc = &ratelim_connections[i];
diff = timevaldiff(&rc->connections_begin,
&connections_end);
if (diff.tv_sec >= options.connections_period) {
/*
* Slide the window forward only after
* completely leaving it.
*/
rc->connections_begin = connections_end;
rc->connections_this_period = 1;
} else {
if (++rc->connections_this_period >
options.connections_per_period)
ratelim_exceeded = 1;
}
}
}
/*
* Got connection. Fork a child to handle it unless
* we are in debugging mode or the maximum number of
* connections per period has been exceeded.
*/
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 if (ratelim_exceeded) {
const char *myaddr;
myaddr = get_ipaddr(newsock);
log("rate limit (%u/%u) on %s port %d "
"exceeded by %s",
options.connections_per_period,
options.connections_period, myaddr,
get_sock_port(newsock, 1), ntop);
free((void *)myaddr);
close(newsock);
ratelim_exceeded = 0;
continue;
} else {
/*
* 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);
startup_pipe = -1;
pid = getpid();
break;
} else if (ratelim_exceeded) {
const char *myaddr;
myaddr = get_ipaddr(newsock);
log("rate limit (%u/%u) on %s port %d "
"exceeded by %s",
options.connections_per_period,
options.connections_period, myaddr,
get_sock_port(newsock, 1), ntop);
free((void *)myaddr);
close(newsock);
ratelim_exceeded = 0;
continue;
} 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);
close(startup_p[1]);
/* Mark that the key has been used (it was "given" to the child). */
key_used = 1;
arc4random_stir();
/* Close the new socket (the child is now taking care of it). */
close(newsock);
}
/* 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;
arc4random_stir();
/* Close the new socket (the child is now taking care of it). */
close(newsock);
} /* for (i = 0; i < num_listen_socks; i++) */
/* child process check (or debug mode) */
if (num_listen_socks < 0)
break;

View File

@ -53,3 +53,7 @@ PermitEmptyPasswords no
CheckMail yes
#UseLogin no
# Uncomment if you want to enable sftp
#Subsystem sftp /usr/libexec/sftp-server
#MaxStartups 10:30:60