Resolve conflicts and update for OpenSSH 2.2.0
Reviewed by: gshapiro, peter, green
This commit is contained in:
parent
d345e9b7aa
commit
71b51dc832
@ -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. */
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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. */
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 ,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user