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>
|
* Copyright (c) 1999 Dug Song. All rights reserved.
|
||||||
* Kerberos v4 authentication and ticket-passing routines.
|
*
|
||||||
*
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* $FreeBSD$
|
* 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"
|
#include "includes.h"
|
||||||
@ -11,6 +28,9 @@
|
|||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
|
|
||||||
|
RCSID("$OpenBSD: auth-krb4.c,v 1.18 2000/09/07 20:27:49 deraadt Exp $");
|
||||||
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#ifdef KRB4
|
#ifdef KRB4
|
||||||
char *ticket = NULL;
|
char *ticket = NULL;
|
||||||
|
|
||||||
@ -82,11 +102,12 @@ auth_krb4_password(struct passwd * pw, const char *password)
|
|||||||
if (r == RD_AP_UNDEC) {
|
if (r == RD_AP_UNDEC) {
|
||||||
/*
|
/*
|
||||||
* Probably didn't have a srvtab on
|
* Probably didn't have a srvtab on
|
||||||
* localhost. Allow login.
|
* localhost. Disallow login.
|
||||||
*/
|
*/
|
||||||
log("Kerberos V4 TGT for %s unverifiable, "
|
log("Kerberos V4 TGT for %s unverifiable, "
|
||||||
"no srvtab installed? krb_rd_req: %s",
|
"no srvtab installed? krb_rd_req: %s",
|
||||||
pw->pw_name, krb_err_txt[r]);
|
pw->pw_name, krb_err_txt[r]);
|
||||||
|
goto kerberos_auth_failure;
|
||||||
} else if (r != KSUCCESS) {
|
} else if (r != KSUCCESS) {
|
||||||
log("Kerberos V4 %s ticket unverifiable: %s",
|
log("Kerberos V4 %s ticket unverifiable: %s",
|
||||||
KRB4_SERVICE_NAME, krb_err_txt[r]);
|
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) {
|
} 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 the error.
|
||||||
*/
|
*/
|
||||||
log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s "
|
log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s "
|
||||||
"not registered, or srvtab is wrong?", pw->pw_name,
|
"not registered, or srvtab is wrong?", pw->pw_name,
|
||||||
krb_err_txt[r], KRB4_SERVICE_NAME, phost);
|
krb_err_txt[r], KRB4_SERVICE_NAME, phost);
|
||||||
|
goto kerberos_auth_failure;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* TGT is bad, forget it. Possibly spoofed!
|
* TGT is bad, forget it. Possibly spoofed!
|
||||||
@ -152,7 +174,7 @@ krb4_init(uid_t uid)
|
|||||||
if (lstat("/ticket", &st) != -1)
|
if (lstat("/ticket", &st) != -1)
|
||||||
tkt_root = "/ticket/";
|
tkt_root = "/ticket/";
|
||||||
#endif /* AFS */
|
#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);
|
(void) krb_set_tkt_string(ticket);
|
||||||
}
|
}
|
||||||
/* Register ticket cleanup in case of fatal error. */
|
/* Register ticket cleanup in case of fatal error. */
|
||||||
|
@ -2,15 +2,65 @@
|
|||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
* Created: Sat Mar 18 05:11:38 1995 ylo
|
|
||||||
* Password authentication. This file contains the functions to check whether
|
* Password authentication. This file contains the functions to check whether
|
||||||
* the password is valid for the user.
|
* 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"
|
#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 "packet.h"
|
||||||
#include "ssh.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
|
* Tries to authenticate the user using password. Returns true if
|
||||||
* authentication succeeds.
|
* authentication succeeds.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
auth_password(struct passwd * pw, const char *password)
|
auth_password(struct passwd * pw, const char *password)
|
||||||
{
|
{
|
||||||
extern ServerOptions options;
|
extern ServerOptions options;
|
||||||
|
@ -1,22 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* auth-rh-rsa.c
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
|
||||||
* Created: Sun May 7 03:08:06 1995 ylo
|
|
||||||
*
|
|
||||||
* Rhosts or /etc/hosts.equiv authentication combined with RSA host
|
* Rhosts or /etc/hosts.equiv authentication combined with RSA host
|
||||||
* authentication.
|
* 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"
|
#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 "packet.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
|
@ -1,23 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* auth-rsa.c
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
|
||||||
* Created: Mon Mar 27 01:46:52 1995 ylo
|
|
||||||
*
|
|
||||||
* RSA-based authentication. This code determines whether to admit a login
|
* RSA-based authentication. This code determines whether to admit a login
|
||||||
* based on RSA authentication. This file also contains functions to check
|
* based on RSA authentication. This file also contains functions to check
|
||||||
* validity of the host key.
|
* 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"
|
#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 "rsa.h"
|
||||||
#include "packet.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 "uidswap.h"
|
||||||
#include "match.h"
|
#include "match.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
|
#include "auth-options.h"
|
||||||
|
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <openssl/md5.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
|
* Session identifier that is used to bind key exchange and authentication
|
||||||
* responses to a particular session.
|
* responses to a particular session.
|
||||||
@ -187,8 +178,8 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
|
|||||||
}
|
}
|
||||||
if (fail) {
|
if (fail) {
|
||||||
fclose(f);
|
fclose(f);
|
||||||
log(buf);
|
log("%s",buf);
|
||||||
packet_send_debug(buf);
|
packet_send_debug("%s",buf);
|
||||||
restore_uid();
|
restore_uid();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -269,188 +260,10 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
|
|||||||
* authenticated. Note that we have not yet processed the
|
* authenticated. Note that we have not yet processed the
|
||||||
* options; this will be reset if the options cause the
|
* options; this will be reset if the options cause the
|
||||||
* authentication to be rejected.
|
* 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;
|
* Break out of the loop if authentication was successful;
|
||||||
* otherwise continue searching.
|
* otherwise continue searching.
|
||||||
*/
|
*/
|
||||||
|
authenticated = auth_parse_options(pw, options, linenum);
|
||||||
if (authenticated)
|
if (authenticated)
|
||||||
break;
|
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"
|
#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 <sys/sysctl.h>
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
@ -112,7 +135,7 @@ skey_fake_keyinfo(char *username)
|
|||||||
mib[0] = CTL_KERN;
|
mib[0] = CTL_KERN;
|
||||||
mib[1] = KERN_BOOTTIME;
|
mib[1] = KERN_BOOTTIME;
|
||||||
size = sizeof(boottime);
|
size = sizeof(boottime);
|
||||||
bzero(&boottime, sizeof(boottime));
|
bzero(&boottime, size);
|
||||||
if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 &&
|
if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 &&
|
||||||
boottime.tv_sec != 0) {
|
boottime.tv_sec != 0) {
|
||||||
secret = (char *)&boottime;
|
secret = (char *)&boottime;
|
||||||
|
@ -1,13 +1,40 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* 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.
|
* 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"
|
#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 "xmalloc.h"
|
||||||
#include "rsa.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 "ssh2.h"
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
#include "dispatch.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* import */
|
/* import */
|
||||||
extern ServerOptions options;
|
extern ServerOptions options;
|
||||||
extern char *forced_command;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the user is allowed to log in via ssh. If user is listed in
|
* 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;
|
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... */
|
/* We found no reason not to let this user try to log on... */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,16 @@
|
|||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* $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"
|
#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 "xmalloc.h"
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
@ -148,15 +153,15 @@ do_authloop(struct passwd * pw)
|
|||||||
unsigned int ulen;
|
unsigned int ulen;
|
||||||
int type = 0;
|
int type = 0;
|
||||||
void (*authlog) (const char *fmt,...) = verbose;
|
void (*authlog) (const char *fmt,...) = verbose;
|
||||||
#ifdef LOGIN_CAP
|
#ifdef HAVE_LOGIN_CAP
|
||||||
login_cap_t *lc;
|
login_cap_t *lc;
|
||||||
#endif /* LOGIN_CAP */
|
#endif /* HAVE_LOGIN_CAP */
|
||||||
#if defined(LOGIN_CAP) || defined(LOGIN_ACCESS)
|
#if defined(HAVE_LOGIN_CAP) || defined(LOGIN_ACCESS)
|
||||||
const char *from_host, *from_ip;
|
const char *from_host, *from_ip;
|
||||||
|
|
||||||
from_host = get_canonical_hostname();
|
from_host = get_canonical_hostname();
|
||||||
from_ip = get_remote_ipaddr();
|
from_ip = get_remote_ipaddr();
|
||||||
#endif /* LOGIN_CAP || LOGIN_ACCESS */
|
#endif /* HAVE_LOGIN_CAP || LOGIN_ACCESS */
|
||||||
#ifdef HAVE_LIBPAM
|
#ifdef HAVE_LIBPAM
|
||||||
int pam_retval;
|
int pam_retval;
|
||||||
#endif /* HAVE_LIBPAM */
|
#endif /* HAVE_LIBPAM */
|
||||||
@ -452,7 +457,7 @@ do_authloop(struct passwd * pw)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LOGIN_CAP
|
#ifdef HAVE_LOGIN_CAP
|
||||||
lc = login_getpwclass(pw);
|
lc = login_getpwclass(pw);
|
||||||
if (lc == NULL)
|
if (lc == NULL)
|
||||||
lc = login_getclassbyname(NULL, pw);
|
lc = login_getclassbyname(NULL, pw);
|
||||||
@ -467,7 +472,7 @@ do_authloop(struct passwd * pw)
|
|||||||
packet_disconnect("Logins not available right now.");
|
packet_disconnect("Logins not available right now.");
|
||||||
}
|
}
|
||||||
login_close(lc);
|
login_close(lc);
|
||||||
#endif /* LOGIN_CAP */
|
#endif /* HAVE_LOGIN_CAP */
|
||||||
#ifdef LOGIN_ACCESS
|
#ifdef LOGIN_ACCESS
|
||||||
if (!login_access(pw->pw_name, from_host)) {
|
if (!login_access(pw->pw_name, from_host)) {
|
||||||
log("Denied connection for %.200s from %.200s [%.200s].",
|
log("Denied connection for %.200s from %.200s [%.200s].",
|
||||||
@ -548,6 +553,7 @@ do_authentication()
|
|||||||
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
|
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
|
||||||
pwcopy.pw_uid = pw->pw_uid;
|
pwcopy.pw_uid = pw->pw_uid;
|
||||||
pwcopy.pw_gid = pw->pw_gid;
|
pwcopy.pw_gid = pw->pw_gid;
|
||||||
|
pwcopy.pw_class = xstrdup(pw->pw_class);
|
||||||
pwcopy.pw_dir = xstrdup(pw->pw_dir);
|
pwcopy.pw_dir = xstrdup(pw->pw_dir);
|
||||||
pwcopy.pw_shell = xstrdup(pw->pw_shell);
|
pwcopy.pw_shell = xstrdup(pw->pw_shell);
|
||||||
pwcopy.pw_class = xstrdup(pw->pw_class);
|
pwcopy.pw_class = xstrdup(pw->pw_class);
|
||||||
|
@ -9,11 +9,6 @@
|
|||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* 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
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
@ -25,11 +20,11 @@
|
|||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
|
||||||
* $FreeBSD$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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/dsa.h>
|
||||||
#include <openssl/rsa.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 "dsa.h"
|
||||||
#include "uidswap.h"
|
#include "uidswap.h"
|
||||||
|
#include "auth-options.h"
|
||||||
|
|
||||||
/* import */
|
/* import */
|
||||||
extern ServerOptions options;
|
extern ServerOptions options;
|
||||||
@ -71,7 +67,7 @@ void protocol_error(int type, int plen);
|
|||||||
/* auth */
|
/* auth */
|
||||||
int ssh2_auth_none(struct passwd *pw);
|
int ssh2_auth_none(struct passwd *pw);
|
||||||
int ssh2_auth_password(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 */
|
/* helper */
|
||||||
struct passwd* auth_set_user(char *u, char *s);
|
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 void (*authlog) (const char *fmt,...) = verbose;
|
||||||
static int attempt = 0;
|
static int attempt = 0;
|
||||||
unsigned int len, rlen;
|
unsigned int len;
|
||||||
int authenticated = 0;
|
int authenticated = 0;
|
||||||
char *raw, *user, *service, *method, *authmsg = NULL;
|
char *user, *service, *method, *authmsg = NULL;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
|
||||||
if (++attempt == AUTH_FAIL_MAX)
|
if (++attempt == AUTH_FAIL_MAX)
|
||||||
packet_disconnect("too many failed userauth_requests");
|
packet_disconnect("too many failed userauth_requests");
|
||||||
|
|
||||||
raw = packet_get_raw(&rlen);
|
|
||||||
if (plen != rlen)
|
|
||||||
fatal("plen != rlen");
|
|
||||||
user = packet_get_string(&len);
|
user = packet_get_string(&len);
|
||||||
service = packet_get_string(&len);
|
service = packet_get_string(&len);
|
||||||
method = 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) {
|
} else if (strcmp(method, "password") == 0) {
|
||||||
authenticated = ssh2_auth_password(pw);
|
authenticated = ssh2_auth_password(pw);
|
||||||
} else if (strcmp(method, "publickey") == 0) {
|
} 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) {
|
if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
|
||||||
@ -254,7 +247,7 @@ ssh2_auth_password(struct passwd *pw)
|
|||||||
return authenticated;
|
return authenticated;
|
||||||
}
|
}
|
||||||
int
|
int
|
||||||
ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen)
|
ssh2_auth_pubkey(struct passwd *pw, char *service)
|
||||||
{
|
{
|
||||||
Buffer b;
|
Buffer b;
|
||||||
Key *key;
|
Key *key;
|
||||||
@ -267,10 +260,6 @@ ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen)
|
|||||||
debug("pubkey auth disabled");
|
debug("pubkey auth disabled");
|
||||||
return 0;
|
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();
|
have_sig = packet_get_char();
|
||||||
pkalg = packet_get_string(&alen);
|
pkalg = packet_get_string(&alen);
|
||||||
if (strcmp(pkalg, KEX_DSS) != 0) {
|
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);
|
sig = packet_get_string(&slen);
|
||||||
packet_done();
|
packet_done();
|
||||||
buffer_init(&b);
|
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);
|
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
|
||||||
if (slen + 4 > rlen)
|
buffer_put_cstring(&b, pw->pw_name);
|
||||||
fatal("bad rlen/slen");
|
buffer_put_cstring(&b,
|
||||||
buffer_append(&b, raw, rlen - slen - 4);
|
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
|
#ifdef DEBUG_DSS
|
||||||
buffer_dump(&b);
|
buffer_dump(&b);
|
||||||
#endif
|
#endif
|
||||||
@ -357,6 +357,7 @@ auth_set_user(char *u, char *s)
|
|||||||
copy->pw_passwd = xstrdup(pw->pw_passwd);
|
copy->pw_passwd = xstrdup(pw->pw_passwd);
|
||||||
copy->pw_uid = pw->pw_uid;
|
copy->pw_uid = pw->pw_uid;
|
||||||
copy->pw_gid = pw->pw_gid;
|
copy->pw_gid = pw->pw_gid;
|
||||||
|
copy->pw_class = xstrdup(pw->pw_class);
|
||||||
copy->pw_dir = xstrdup(pw->pw_dir);
|
copy->pw_dir = xstrdup(pw->pw_dir);
|
||||||
copy->pw_shell = xstrdup(pw->pw_shell);
|
copy->pw_shell = xstrdup(pw->pw_shell);
|
||||||
copy->pw_class = xstrdup(pw->pw_class);
|
copy->pw_class = xstrdup(pw->pw_class);
|
||||||
@ -438,8 +439,8 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fail) {
|
if (fail) {
|
||||||
log(buf);
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
log("%s",buf);
|
||||||
restore_uid();
|
restore_uid();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -448,17 +449,36 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
|
|||||||
found = key_new(KEY_DSA);
|
found = key_new(KEY_DSA);
|
||||||
|
|
||||||
while (fgets(line, sizeof(line), f)) {
|
while (fgets(line, sizeof(line), f)) {
|
||||||
char *cp;
|
char *cp, *options = NULL;
|
||||||
linenum++;
|
linenum++;
|
||||||
/* Skip leading whitespace, empty and comment lines. */
|
/* Skip leading whitespace, empty and comment lines. */
|
||||||
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
|
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
|
||||||
;
|
;
|
||||||
if (!*cp || *cp == '\n' || *cp == '#')
|
if (!*cp || *cp == '\n' || *cp == '#')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bits = key_read(found, &cp);
|
bits = key_read(found, &cp);
|
||||||
if (bits == 0)
|
if (bits == 0) {
|
||||||
continue;
|
/* no key? check if there are options for this key */
|
||||||
if (key_equal(found, 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;
|
found_key = 1;
|
||||||
debug("matching key found: file %s, line %ld",
|
debug("matching key found: file %s, line %ld",
|
||||||
file, linenum);
|
file, linenum);
|
||||||
|
@ -1,31 +1,60 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* authfd.c
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
|
||||||
* Created: Wed Mar 29 01:30:28 1995 ylo
|
|
||||||
*
|
|
||||||
* Functions for connecting the local authentication agent.
|
* 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"
|
#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 "ssh.h"
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "authfd.h"
|
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "bufaux.h"
|
#include "bufaux.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "getput.h"
|
#include "getput.h"
|
||||||
|
|
||||||
#include <openssl/rsa.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. */
|
/* Returns the number of the authentication fd, or -1 if there is none. */
|
||||||
|
|
||||||
@ -60,6 +89,59 @@ ssh_get_authentication_socket()
|
|||||||
return sock;
|
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
|
* Closes the agent socket if it should be closed (depends on how it was
|
||||||
* obtained). The argument must have been returned by
|
* obtained). The argument must have been returned by
|
||||||
@ -98,7 +180,6 @@ ssh_get_authentication_connection()
|
|||||||
|
|
||||||
auth = xmalloc(sizeof(*auth));
|
auth = xmalloc(sizeof(*auth));
|
||||||
auth->fd = sock;
|
auth->fd = sock;
|
||||||
buffer_init(&auth->packet);
|
|
||||||
buffer_init(&auth->identities);
|
buffer_init(&auth->identities);
|
||||||
auth->howmany = 0;
|
auth->howmany = 0;
|
||||||
|
|
||||||
@ -111,121 +192,108 @@ ssh_get_authentication_connection()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ssh_close_authentication_connection(AuthenticationConnection *ac)
|
ssh_close_authentication_connection(AuthenticationConnection *auth)
|
||||||
{
|
{
|
||||||
buffer_free(&ac->packet);
|
buffer_free(&auth->identities);
|
||||||
buffer_free(&ac->identities);
|
close(auth->fd);
|
||||||
close(ac->fd);
|
xfree(auth);
|
||||||
xfree(ac);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the first authentication identity held by the agent.
|
* 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
|
Key *
|
||||||
ssh_get_first_identity(AuthenticationConnection *auth,
|
ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version)
|
||||||
BIGNUM *e, BIGNUM *n, char **comment)
|
|
||||||
{
|
{
|
||||||
unsigned char msg[8192];
|
int type, code1 = 0, code2 = 0;
|
||||||
int len, l;
|
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
|
* Send a message to the agent requesting for a list of the
|
||||||
* identities it can represent.
|
* identities it can represent.
|
||||||
*/
|
*/
|
||||||
msg[0] = 0;
|
buffer_init(&request);
|
||||||
msg[1] = 0;
|
buffer_put_char(&request, code1);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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);
|
buffer_clear(&auth->identities);
|
||||||
while (len > 0) {
|
if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
|
||||||
l = len;
|
buffer_free(&request);
|
||||||
if (l > sizeof(msg))
|
return NULL;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
buffer_free(&request);
|
||||||
|
|
||||||
/* Get message type, and verify that we got a proper answer. */
|
/* Get message type, and verify that we got a proper answer. */
|
||||||
buffer_get(&auth->identities, (char *) msg, 1);
|
type = buffer_get_char(&auth->identities);
|
||||||
if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)
|
if (type == SSH_AGENT_FAILURE) {
|
||||||
fatal("Bad authentication reply message type: %d", msg[0]);
|
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. */
|
/* Get the number of entries in the response and check it for sanity. */
|
||||||
auth->howmany = buffer_get_int(&auth->identities);
|
auth->howmany = buffer_get_int(&auth->identities);
|
||||||
if (auth->howmany > 1024)
|
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 the first entry (if any). */
|
||||||
return ssh_get_next_identity(auth, e, n, comment);
|
return ssh_get_next_identity(auth, comment, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
Key *
|
||||||
* Returns the next authentication identity for the agent. Other functions
|
ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version)
|
||||||
* 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)
|
|
||||||
{
|
{
|
||||||
unsigned int bits;
|
unsigned int bits;
|
||||||
|
unsigned char *blob;
|
||||||
|
unsigned int blen;
|
||||||
|
Key *key = NULL;
|
||||||
|
|
||||||
/* Return failure if no more entries. */
|
/* Return failure if no more entries. */
|
||||||
if (auth->howmany <= 0)
|
if (auth->howmany <= 0)
|
||||||
return 0;
|
return NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the next entry from the packet. These will abort with a fatal
|
* Get the next entry from the packet. These will abort with a fatal
|
||||||
* error if the packet is too short or contains corrupt data.
|
* error if the packet is too short or contains corrupt data.
|
||||||
*/
|
*/
|
||||||
bits = buffer_get_int(&auth->identities);
|
switch(version){
|
||||||
buffer_get_bignum(&auth->identities, e);
|
case 1:
|
||||||
buffer_get_bignum(&auth->identities, n);
|
key = key_new(KEY_RSA);
|
||||||
*comment = buffer_get_string(&auth->identities, NULL);
|
bits = buffer_get_int(&auth->identities);
|
||||||
|
buffer_get_bignum(&auth->identities, key->rsa->e);
|
||||||
if (bits != BN_num_bits(n))
|
buffer_get_bignum(&auth->identities, key->rsa->n);
|
||||||
log("Warning: identity keysize mismatch: actual %d, announced %u",
|
*comment = buffer_get_string(&auth->identities, NULL);
|
||||||
BN_num_bits(n), bits);
|
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. */
|
/* Decrement the number of remaining entries. */
|
||||||
auth->howmany--;
|
auth->howmany--;
|
||||||
|
return key;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -238,101 +306,124 @@ ssh_get_next_identity(AuthenticationConnection *auth,
|
|||||||
|
|
||||||
int
|
int
|
||||||
ssh_decrypt_challenge(AuthenticationConnection *auth,
|
ssh_decrypt_challenge(AuthenticationConnection *auth,
|
||||||
BIGNUM* e, BIGNUM *n, BIGNUM *challenge,
|
Key* key, BIGNUM *challenge,
|
||||||
unsigned char session_id[16],
|
unsigned char session_id[16],
|
||||||
unsigned int response_type,
|
unsigned int response_type,
|
||||||
unsigned char response[16])
|
unsigned char response[16])
|
||||||
{
|
{
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
unsigned char buf[8192];
|
int success = 0;
|
||||||
int len, l, i;
|
int i;
|
||||||
|
int type;
|
||||||
|
|
||||||
/* Response type 0 is no longer supported. */
|
if (key->type != KEY_RSA)
|
||||||
if (response_type == 0)
|
return 0;
|
||||||
fatal("Compatibility with ssh protocol version 1.0 no longer supported.");
|
if (response_type == 0) {
|
||||||
|
log("Compatibility with ssh protocol version 1.0 no longer supported.");
|
||||||
/* Format a message to the agent. */
|
return 0;
|
||||||
buf[0] = SSH_AGENTC_RSA_CHALLENGE;
|
}
|
||||||
buffer_init(&buffer);
|
buffer_init(&buffer);
|
||||||
buffer_append(&buffer, (char *) buf, 1);
|
buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE);
|
||||||
buffer_put_int(&buffer, BN_num_bits(n));
|
buffer_put_int(&buffer, BN_num_bits(key->rsa->n));
|
||||||
buffer_put_bignum(&buffer, e);
|
buffer_put_bignum(&buffer, key->rsa->e);
|
||||||
buffer_put_bignum(&buffer, n);
|
buffer_put_bignum(&buffer, key->rsa->n);
|
||||||
buffer_put_bignum(&buffer, challenge);
|
buffer_put_bignum(&buffer, challenge);
|
||||||
buffer_append(&buffer, (char *) session_id, 16);
|
buffer_append(&buffer, (char *) session_id, 16);
|
||||||
buffer_put_int(&buffer, response_type);
|
buffer_put_int(&buffer, response_type);
|
||||||
|
|
||||||
/* Get the length of the message, and format it in the buffer. */
|
if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
|
||||||
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);
|
buffer_free(&buffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*
|
type = buffer_get_char(&buffer);
|
||||||
* 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. */
|
if (type == SSH_AGENT_FAILURE) {
|
||||||
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) {
|
|
||||||
log("Agent admitted failure to authenticate using the key.");
|
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);
|
buffer_free(&buffer);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
/* Correct answer. */
|
/* ask agent to sign data, returns -1 on error, 0 on success */
|
||||||
return 1;
|
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
|
int
|
||||||
ssh_add_identity(AuthenticationConnection *auth,
|
ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
|
||||||
RSA * key, const char *comment)
|
|
||||||
{
|
{
|
||||||
Buffer buffer;
|
Buffer msg;
|
||||||
unsigned char buf[8192];
|
int type;
|
||||||
int len, l, type;
|
|
||||||
|
|
||||||
/* Format a message to the agent. */
|
buffer_init(&msg);
|
||||||
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));
|
|
||||||
|
|
||||||
/* Get the length of the message, and format it in the buffer. */
|
switch (key->type) {
|
||||||
len = buffer_len(&buffer);
|
case KEY_RSA:
|
||||||
PUT_32BIT(buf, len);
|
ssh_encode_identity_rsa(&msg, key->rsa, comment);
|
||||||
|
break;
|
||||||
/* Send the length and then the packet to the agent. */
|
case KEY_DSA:
|
||||||
if (atomicio(write, auth->fd, buf, 4) != 4 ||
|
ssh_encode_identity_dsa(&msg, key->dsa, comment);
|
||||||
atomicio(write, auth->fd, buffer_ptr(&buffer),
|
break;
|
||||||
buffer_len(&buffer)) != buffer_len(&buffer)) {
|
|
||||||
error("Error writing to authentication socket.");
|
|
||||||
error_cleanup:
|
|
||||||
buffer_free(&buffer);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* Wait for response from the agent. First read the length of the
|
|
||||||
response packet. */
|
|
||||||
len = 4;
|
|
||||||
while (len > 0) {
|
|
||||||
l = read(auth->fd, buf + 4 - len, len);
|
|
||||||
if (l <= 0) {
|
|
||||||
error("Error reading response length from authentication socket.");
|
|
||||||
goto error_cleanup;
|
|
||||||
}
|
|
||||||
len -= l;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Extract the length, and check it for sanity. */
|
|
||||||
len = GET_32BIT(buf);
|
|
||||||
if (len > 256 * 1024)
|
|
||||||
fatal("Add identity response too long: %d", len);
|
|
||||||
|
|
||||||
/* Read the rest of the response in tothe buffer. */
|
|
||||||
buffer_clear(&buffer);
|
|
||||||
while (len > 0) {
|
|
||||||
l = len;
|
|
||||||
if (l > sizeof(buf))
|
|
||||||
l = sizeof(buf);
|
|
||||||
l = read(auth->fd, buf, l);
|
|
||||||
if (l <= 0) {
|
|
||||||
error("Error reading response from authentication socket.");
|
|
||||||
goto error_cleanup;
|
|
||||||
}
|
|
||||||
buffer_append(&buffer, (char *) buf, l);
|
|
||||||
len -= l;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the type of the packet. */
|
|
||||||
type = buffer_get_char(&buffer);
|
|
||||||
switch (type) {
|
|
||||||
case SSH_AGENT_FAILURE:
|
|
||||||
buffer_free(&buffer);
|
|
||||||
return 0;
|
|
||||||
case SSH_AGENT_SUCCESS:
|
|
||||||
buffer_free(&buffer);
|
|
||||||
return 1;
|
|
||||||
default:
|
default:
|
||||||
fatal("Bad response to add identity from authentication agent: %d",
|
buffer_free(&msg);
|
||||||
type);
|
return 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
/* NOTREACHED */
|
if (ssh_request_reply(auth, &msg, &msg) == 0) {
|
||||||
return 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
|
int
|
||||||
ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
|
ssh_remove_identity(AuthenticationConnection *auth, Key *key)
|
||||||
{
|
{
|
||||||
Buffer buffer;
|
Buffer msg;
|
||||||
unsigned char buf[8192];
|
int type;
|
||||||
int len, l, type;
|
unsigned char *blob;
|
||||||
|
unsigned int blen;
|
||||||
|
|
||||||
/* Format a message to the agent. */
|
buffer_init(&msg);
|
||||||
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);
|
|
||||||
|
|
||||||
/* Get the length of the message, and format it in the buffer. */
|
if (key->type == KEY_RSA) {
|
||||||
len = buffer_len(&buffer);
|
buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY);
|
||||||
PUT_32BIT(buf, len);
|
buffer_put_int(&msg, BN_num_bits(key->rsa->n));
|
||||||
|
buffer_put_bignum(&msg, key->rsa->e);
|
||||||
/* Send the length and then the packet to the agent. */
|
buffer_put_bignum(&msg, key->rsa->n);
|
||||||
if (atomicio(write, auth->fd, buf, 4) != 4 ||
|
} else if (key->type == KEY_DSA) {
|
||||||
atomicio(write, auth->fd, buffer_ptr(&buffer),
|
dsa_make_key_blob(key, &blob, &blen);
|
||||||
buffer_len(&buffer)) != buffer_len(&buffer)) {
|
buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
|
||||||
error("Error writing to authentication socket.");
|
buffer_put_string(&msg, blob, blen);
|
||||||
error_cleanup:
|
xfree(blob);
|
||||||
buffer_free(&buffer);
|
} else {
|
||||||
|
buffer_free(&msg);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*
|
if (ssh_request_reply(auth, &msg, &msg) == 0) {
|
||||||
* Wait for response from the agent. First read the length of the
|
buffer_free(&msg);
|
||||||
* response packet.
|
|
||||||
*/
|
|
||||||
len = 4;
|
|
||||||
while (len > 0) {
|
|
||||||
l = read(auth->fd, buf + 4 - len, len);
|
|
||||||
if (l <= 0) {
|
|
||||||
error("Error reading response length from authentication socket.");
|
|
||||||
goto error_cleanup;
|
|
||||||
}
|
|
||||||
len -= l;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Extract the length, and check it for sanity. */
|
|
||||||
len = GET_32BIT(buf);
|
|
||||||
if (len > 256 * 1024)
|
|
||||||
fatal("Remove identity response too long: %d", len);
|
|
||||||
|
|
||||||
/* Read the rest of the response in tothe buffer. */
|
|
||||||
buffer_clear(&buffer);
|
|
||||||
while (len > 0) {
|
|
||||||
l = len;
|
|
||||||
if (l > sizeof(buf))
|
|
||||||
l = sizeof(buf);
|
|
||||||
l = read(auth->fd, buf, l);
|
|
||||||
if (l <= 0) {
|
|
||||||
error("Error reading response from authentication socket.");
|
|
||||||
goto error_cleanup;
|
|
||||||
}
|
|
||||||
buffer_append(&buffer, (char *) buf, l);
|
|
||||||
len -= l;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the type of the packet. */
|
|
||||||
type = buffer_get_char(&buffer);
|
|
||||||
switch (type) {
|
|
||||||
case SSH_AGENT_FAILURE:
|
|
||||||
buffer_free(&buffer);
|
|
||||||
return 0;
|
return 0;
|
||||||
case SSH_AGENT_SUCCESS:
|
|
||||||
buffer_free(&buffer);
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
fatal("Bad response to remove identity from authentication agent: %d",
|
|
||||||
type);
|
|
||||||
}
|
}
|
||||||
/* NOTREACHED */
|
type = buffer_get_char(&msg);
|
||||||
return 0;
|
buffer_free(&msg);
|
||||||
|
return decode_reply(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -512,68 +504,37 @@ ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
ssh_remove_all_identities(AuthenticationConnection *auth)
|
ssh_remove_all_identities(AuthenticationConnection *auth, int version)
|
||||||
{
|
{
|
||||||
Buffer buffer;
|
Buffer msg;
|
||||||
unsigned char buf[8192];
|
int type;
|
||||||
int len, l, 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. */
|
buffer_init(&msg);
|
||||||
PUT_32BIT(buf, 1);
|
buffer_put_char(&msg, code);
|
||||||
buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
|
|
||||||
|
|
||||||
/* Send the length and then the packet to the agent. */
|
if (ssh_request_reply(auth, &msg, &msg) == 0) {
|
||||||
if (atomicio(write, auth->fd, buf, 5) != 5) {
|
buffer_free(&msg);
|
||||||
error("Error writing to authentication socket.");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*
|
type = buffer_get_char(&msg);
|
||||||
* Wait for response from the agent. First read the length of the
|
buffer_free(&msg);
|
||||||
* response packet.
|
return decode_reply(type);
|
||||||
*/
|
}
|
||||||
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. */
|
int
|
||||||
len = GET_32BIT(buf);
|
decode_reply(int type)
|
||||||
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);
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SSH_AGENT_FAILURE:
|
case SSH_AGENT_FAILURE:
|
||||||
buffer_free(&buffer);
|
log("SSH_AGENT_FAILURE");
|
||||||
return 0;
|
return 0;
|
||||||
case SSH_AGENT_SUCCESS:
|
case SSH_AGENT_SUCCESS:
|
||||||
buffer_free(&buffer);
|
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
fatal("Bad response to remove identity from authentication agent: %d",
|
fatal("Bad response from authentication agent: %d", type);
|
||||||
type);
|
|
||||||
}
|
}
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,22 +1,43 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* authfile.c
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
|
||||||
* Created: Mon Mar 27 03:52:05 1995 ylo
|
|
||||||
*
|
|
||||||
* This file contains functions for reading and writing identity files, and
|
* This file contains functions for reading and writing identity files, and
|
||||||
* for reading the passphrase from the user.
|
* 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"
|
#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/bn.h>
|
||||||
#include <openssl/dsa.h>
|
#include <openssl/dsa.h>
|
||||||
@ -263,6 +284,7 @@ load_public_key_rsa(const char *filename, RSA * pub, char **comment_return)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* load public key from private-key file */
|
||||||
int
|
int
|
||||||
load_public_key(const char *filename, Key * key, char **comment_return)
|
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);
|
close(fd);
|
||||||
return ret;
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
|
||||||
* Created: Wed Mar 29 02:24:47 1995 ylo
|
|
||||||
*
|
|
||||||
* Auxiliary functions for storing and retrieving various data types to/from
|
* Auxiliary functions for storing and retrieving various data types to/from
|
||||||
* Buffers.
|
* 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"
|
#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 "ssh.h"
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* canohost.c
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
|
||||||
* Created: Sun Jul 2 17:52:22 1995 ylo
|
|
||||||
*
|
|
||||||
* Functions for returning the canonical host name of the remote site.
|
* 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"
|
#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 "packet.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
@ -1,19 +1,42 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* cipher.c
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* 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"
|
#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 "ssh.h"
|
||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
@ -175,14 +198,15 @@ cipher_name(int cipher)
|
|||||||
int
|
int
|
||||||
ciphers_valid(const char *names)
|
ciphers_valid(const char *names)
|
||||||
{
|
{
|
||||||
char *ciphers;
|
char *ciphers, *cp;
|
||||||
char *p;
|
char *p;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (names == NULL || strcmp(names, "") == 0)
|
if (names == NULL || strcmp(names, "") == 0)
|
||||||
return 0;
|
return 0;
|
||||||
ciphers = xstrdup(names);
|
ciphers = cp = xstrdup(names);
|
||||||
for ((p = strtok(ciphers, CIPHER_SEP)); p; (p = strtok(NULL, CIPHER_SEP))) {
|
for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
|
||||||
|
(p = strsep(&cp, CIPHER_SEP))) {
|
||||||
i = cipher_number(p);
|
i = cipher_number(p);
|
||||||
if (i == -1 || !(cipher_mask2() & (1 << i))) {
|
if (i == -1 || !(cipher_mask2() & (1 << i))) {
|
||||||
xfree(ciphers);
|
xfree(ciphers);
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* cipher.h
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* Created: Wed Apr 19 16:50:42 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
|
||||||
* $FreeBSD$
|
* 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
|
#ifndef CIPHER_H
|
||||||
#define CIPHER_H
|
#define CIPHER_H
|
||||||
|
@ -1,21 +1,43 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* hostfile.c
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
|
||||||
* Created: Thu Jun 29 07:10:56 1995 ylo
|
|
||||||
*
|
|
||||||
* Functions for manipulating the known hosts files.
|
* 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"
|
#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 "packet.h"
|
||||||
#include "match.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. */
|
/* 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;
|
continue;
|
||||||
|
|
||||||
/* Got a match. Skip host name. */
|
/* Got a match. Skip host name. */
|
||||||
|
@ -1,24 +1,22 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* includes.h
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
|
||||||
* Created: Thu Mar 23 16:29:37 1995 ylo
|
|
||||||
*
|
|
||||||
* This file includes most of the needed system headers.
|
* 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$
|
* $FreeBSD$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef INCLUDES_H
|
#ifndef INCLUDES_H
|
||||||
#define INCLUDES_H
|
#define INCLUDES_H
|
||||||
|
|
||||||
#define RCSID(msg) \
|
#define RCSID(msg) __RCSID(msg)
|
||||||
static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.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.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* 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
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
@ -25,12 +30,6 @@
|
|||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
|
||||||
* $FreeBSD$
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* read_bignum():
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
@ -43,6 +42,9 @@
|
|||||||
#include "dsa.h"
|
#include "dsa.h"
|
||||||
#include "uuencode.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"
|
#define SSH_DSS "ssh-dss"
|
||||||
|
|
||||||
Key *
|
Key *
|
||||||
@ -123,8 +125,6 @@ key_equal(Key *a, Key *b)
|
|||||||
return 0;
|
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.
|
* Generate key fingerprint in ascii format.
|
||||||
* Based on ideas and code from Bjoern Groenvall <bg@sics.se>
|
* Based on ideas and code from Bjoern Groenvall <bg@sics.se>
|
||||||
@ -132,7 +132,7 @@ key_equal(Key *a, Key *b)
|
|||||||
char *
|
char *
|
||||||
key_fingerprint(Key *k)
|
key_fingerprint(Key *k)
|
||||||
{
|
{
|
||||||
static char retval[80];
|
static char retval[(EVP_MAX_MD_SIZE+1)*3];
|
||||||
unsigned char *blob = NULL;
|
unsigned char *blob = NULL;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int nlen, elen;
|
int nlen, elen;
|
||||||
@ -153,15 +153,22 @@ key_fingerprint(Key *k)
|
|||||||
fatal("key_fingerprint: bad key type %d", k->type);
|
fatal("key_fingerprint: bad key type %d", k->type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
retval[0] = '\0';
|
||||||
|
|
||||||
if (blob != NULL) {
|
if (blob != NULL) {
|
||||||
unsigned char d[16];
|
int i;
|
||||||
EVP_MD_CTX md;
|
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||||
EVP_DigestInit(&md, EVP_md5());
|
EVP_MD *md = EVP_md5();
|
||||||
EVP_DigestUpdate(&md, blob, len);
|
EVP_MD_CTX ctx;
|
||||||
EVP_DigestFinal(&md, d, NULL);
|
EVP_DigestInit(&ctx, md);
|
||||||
snprintf(retval, sizeof(retval), FPRINT,
|
EVP_DigestUpdate(&ctx, blob, len);
|
||||||
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
|
EVP_DigestFinal(&ctx, digest, NULL);
|
||||||
d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
|
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);
|
memset(blob, 0, len);
|
||||||
xfree(blob);
|
xfree(blob);
|
||||||
}
|
}
|
||||||
@ -330,3 +337,15 @@ key_type(Key *k)
|
|||||||
}
|
}
|
||||||
return "unknown";
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
|
||||||
* Created: Fri Mar 24 14:51:08 1995 ylo
|
|
||||||
*
|
|
||||||
* This file performs some of the things login(1) normally does. We cannot
|
* 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
|
* 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
|
* 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
|
* login the current system has. Also, we want to be able to execute commands
|
||||||
* on a tty.
|
* 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"
|
#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__
|
#ifdef __FreeBSD__
|
||||||
#include <libutil.h>
|
#include <libutil.h>
|
||||||
|
@ -1,22 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* mpaux.c
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
|
||||||
* Created: Sun Jul 16 04:29:30 1995 ylo
|
|
||||||
*
|
|
||||||
* This file contains various auxiliary functions related to multiple
|
* This file contains various auxiliary functions related to multiple
|
||||||
* precision integers.
|
* 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"
|
#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 <openssl/bn.h>
|
||||||
#include "getput.h"
|
#include "getput.h"
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* packet.h
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
|
||||||
* Created: Sat Mar 18 02:02:14 1995 ylo
|
|
||||||
*
|
|
||||||
* Interface for the packet protocol functions.
|
* 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
|
#ifndef PACKET_H
|
||||||
#define PACKET_H
|
#define PACKET_H
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* pty.c
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
|
||||||
* Created: Fri Mar 17 04:37:25 1995 ylo
|
|
||||||
*
|
|
||||||
* Allocating a pseudo-terminal, and making it the controlling tty.
|
* 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"
|
#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__
|
#ifdef __FreeBSD__
|
||||||
#include <libutil.h>
|
#include <libutil.h>
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* readconf.c
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
|
||||||
* Created: Sat Apr 22 00:03:10 1995 ylo
|
|
||||||
*
|
|
||||||
* Functions for reading the configuration files.
|
* 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"
|
#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 "ssh.h"
|
||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
@ -93,7 +91,7 @@ typedef enum {
|
|||||||
oBadOption,
|
oBadOption,
|
||||||
oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
|
oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
|
||||||
oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
|
oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
|
||||||
oSkeyAuthentication,
|
oSkeyAuthentication, oXAuthLocation,
|
||||||
#ifdef KRB4
|
#ifdef KRB4
|
||||||
oKrb4Authentication,
|
oKrb4Authentication,
|
||||||
#endif /* KRB4 */
|
#endif /* KRB4 */
|
||||||
@ -120,6 +118,7 @@ static struct {
|
|||||||
} keywords[] = {
|
} keywords[] = {
|
||||||
{ "forwardagent", oForwardAgent },
|
{ "forwardagent", oForwardAgent },
|
||||||
{ "forwardx11", oForwardX11 },
|
{ "forwardx11", oForwardX11 },
|
||||||
|
{ "xauthlocation", oXAuthLocation },
|
||||||
{ "gatewayports", oGatewayPorts },
|
{ "gatewayports", oGatewayPorts },
|
||||||
{ "useprivilegedport", oUsePrivilegedPort },
|
{ "useprivilegedport", oUsePrivilegedPort },
|
||||||
{ "rhostsauthentication", oRhostsAuthentication },
|
{ "rhostsauthentication", oRhostsAuthentication },
|
||||||
@ -171,10 +170,6 @@ static struct {
|
|||||||
{ NULL, 0 }
|
{ 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
|
* Adds a local TCP/IP port forward to options. Never returns if there is an
|
||||||
* error.
|
* error.
|
||||||
@ -244,18 +239,20 @@ process_config_line(Options *options, const char *host,
|
|||||||
char *line, const char *filename, int linenum,
|
char *line, const char *filename, int linenum,
|
||||||
int *activep)
|
int *activep)
|
||||||
{
|
{
|
||||||
char buf[256], *cp, *string, **charptr, *cp2;
|
char buf[256], *s, *string, **charptr, *endofnumber, *keyword, *arg;
|
||||||
int opcode, *intptr, value;
|
int opcode, *intptr, value;
|
||||||
u_short fwd_port, fwd_host_port;
|
u_short fwd_port, fwd_host_port;
|
||||||
|
|
||||||
/* Skip leading whitespace. */
|
s = line;
|
||||||
cp = line + strspn(line, WHITESPACE);
|
/* Get the keyword. (Each line is supposed to begin with a keyword). */
|
||||||
if (!*cp || *cp == '\n' || *cp == '#')
|
keyword = strdelim(&s);
|
||||||
|
/* Ignore leading whitespace. */
|
||||||
|
if (*keyword == '\0')
|
||||||
|
keyword = strdelim(&s);
|
||||||
|
if (!*keyword || *keyword == '\n' || *keyword == '#')
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Get the keyword. (Each line is supposed to begin with a keyword). */
|
opcode = parse_token(keyword, filename, linenum);
|
||||||
cp = strtok(cp, WHITESPACE);
|
|
||||||
opcode = parse_token(cp, filename, linenum);
|
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case oBadOption:
|
case oBadOption:
|
||||||
@ -265,13 +262,13 @@ process_config_line(Options *options, const char *host,
|
|||||||
case oForwardAgent:
|
case oForwardAgent:
|
||||||
intptr = &options->forward_agent;
|
intptr = &options->forward_agent;
|
||||||
parse_flag:
|
parse_flag:
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&s);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
|
fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
|
||||||
value = 0; /* To avoid compiler warning... */
|
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;
|
value = 1;
|
||||||
else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
|
else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
|
||||||
value = 0;
|
value = 0;
|
||||||
else
|
else
|
||||||
fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
|
fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
|
||||||
@ -361,16 +358,16 @@ process_config_line(Options *options, const char *host,
|
|||||||
|
|
||||||
case oStrictHostKeyChecking:
|
case oStrictHostKeyChecking:
|
||||||
intptr = &options->strict_host_key_checking;
|
intptr = &options->strict_host_key_checking;
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&s);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing yes/no argument.",
|
fatal("%.200s line %d: Missing yes/no argument.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
value = 0; /* To avoid compiler warning... */
|
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;
|
value = 1;
|
||||||
else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
|
else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
|
||||||
value = 0;
|
value = 0;
|
||||||
else if (strcmp(cp, "ask") == 0)
|
else if (strcmp(arg, "ask") == 0)
|
||||||
value = 2;
|
value = 2;
|
||||||
else
|
else
|
||||||
fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
|
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 oIdentityFile:
|
||||||
case oIdentityFile2:
|
case oIdentityFile2:
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&s);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
||||||
if (*activep) {
|
if (*activep) {
|
||||||
intptr = (opcode == oIdentityFile) ?
|
intptr = (opcode == oIdentityFile) ?
|
||||||
@ -409,19 +406,23 @@ process_config_line(Options *options, const char *host,
|
|||||||
charptr = (opcode == oIdentityFile) ?
|
charptr = (opcode == oIdentityFile) ?
|
||||||
&options->identity_files[*intptr] :
|
&options->identity_files[*intptr] :
|
||||||
&options->identity_files2[*intptr];
|
&options->identity_files2[*intptr];
|
||||||
*charptr = xstrdup(cp);
|
*charptr = xstrdup(arg);
|
||||||
*intptr = *intptr + 1;
|
*intptr = *intptr + 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case oXAuthLocation:
|
||||||
|
charptr=&options->xauth_location;
|
||||||
|
goto parse_string;
|
||||||
|
|
||||||
case oUser:
|
case oUser:
|
||||||
charptr = &options->user;
|
charptr = &options->user;
|
||||||
parse_string:
|
parse_string:
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&s);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
||||||
if (*activep && *charptr == NULL)
|
if (*activep && *charptr == NULL)
|
||||||
*charptr = xstrdup(cp);
|
*charptr = xstrdup(arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case oGlobalKnownHostsFile:
|
case oGlobalKnownHostsFile:
|
||||||
@ -447,10 +448,10 @@ process_config_line(Options *options, const char *host,
|
|||||||
case oProxyCommand:
|
case oProxyCommand:
|
||||||
charptr = &options->proxy_command;
|
charptr = &options->proxy_command;
|
||||||
string = xstrdup("");
|
string = xstrdup("");
|
||||||
while ((cp = strtok(NULL, WHITESPACE)) != NULL) {
|
while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
|
||||||
string = xrealloc(string, strlen(string) + strlen(cp) + 2);
|
string = xrealloc(string, strlen(string) + strlen(arg) + 2);
|
||||||
strcat(string, " ");
|
strcat(string, " ");
|
||||||
strcat(string, cp);
|
strcat(string, arg);
|
||||||
}
|
}
|
||||||
if (*activep && *charptr == NULL)
|
if (*activep && *charptr == NULL)
|
||||||
*charptr = string;
|
*charptr = string;
|
||||||
@ -461,15 +462,15 @@ process_config_line(Options *options, const char *host,
|
|||||||
case oPort:
|
case oPort:
|
||||||
intptr = &options->port;
|
intptr = &options->port;
|
||||||
parse_int:
|
parse_int:
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&s);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
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);
|
fatal("%.200s line %d: Bad number.", filename, linenum);
|
||||||
|
|
||||||
/* Octal, decimal, or hex format? */
|
/* Octal, decimal, or hex format? */
|
||||||
value = strtol(cp, &cp2, 0);
|
value = strtol(arg, &endofnumber, 0);
|
||||||
if (cp == cp2)
|
if (arg == endofnumber)
|
||||||
fatal("%.200s line %d: Bad number.", filename, linenum);
|
fatal("%.200s line %d: Bad number.", filename, linenum);
|
||||||
if (*activep && *intptr == -1)
|
if (*activep && *intptr == -1)
|
||||||
*intptr = value;
|
*intptr = value;
|
||||||
@ -481,65 +482,65 @@ process_config_line(Options *options, const char *host,
|
|||||||
|
|
||||||
case oCipher:
|
case oCipher:
|
||||||
intptr = &options->cipher;
|
intptr = &options->cipher;
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&s);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
||||||
value = cipher_number(cp);
|
value = cipher_number(arg);
|
||||||
if (value == -1)
|
if (value == -1)
|
||||||
fatal("%.200s line %d: Bad cipher '%s'.",
|
fatal("%.200s line %d: Bad cipher '%s'.",
|
||||||
filename, linenum, cp ? cp : "<NONE>");
|
filename, linenum, arg ? arg : "<NONE>");
|
||||||
if (*activep && *intptr == -1)
|
if (*activep && *intptr == -1)
|
||||||
*intptr = value;
|
*intptr = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case oCiphers:
|
case oCiphers:
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&s);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
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'.",
|
fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
|
||||||
filename, linenum, cp ? cp : "<NONE>");
|
filename, linenum, arg ? arg : "<NONE>");
|
||||||
if (*activep && options->ciphers == NULL)
|
if (*activep && options->ciphers == NULL)
|
||||||
options->ciphers = xstrdup(cp);
|
options->ciphers = xstrdup(arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case oProtocol:
|
case oProtocol:
|
||||||
intptr = &options->protocol;
|
intptr = &options->protocol;
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&s);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
||||||
value = proto_spec(cp);
|
value = proto_spec(arg);
|
||||||
if (value == SSH_PROTO_UNKNOWN)
|
if (value == SSH_PROTO_UNKNOWN)
|
||||||
fatal("%.200s line %d: Bad protocol spec '%s'.",
|
fatal("%.200s line %d: Bad protocol spec '%s'.",
|
||||||
filename, linenum, cp ? cp : "<NONE>");
|
filename, linenum, arg ? arg : "<NONE>");
|
||||||
if (*activep && *intptr == SSH_PROTO_UNKNOWN)
|
if (*activep && *intptr == SSH_PROTO_UNKNOWN)
|
||||||
*intptr = value;
|
*intptr = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case oLogLevel:
|
case oLogLevel:
|
||||||
intptr = (int *) &options->log_level;
|
intptr = (int *) &options->log_level;
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&s);
|
||||||
value = log_level_number(cp);
|
value = log_level_number(arg);
|
||||||
if (value == (LogLevel) - 1)
|
if (value == (LogLevel) - 1)
|
||||||
fatal("%.200s line %d: unsupported log level '%s'\n",
|
fatal("%.200s line %d: unsupported log level '%s'\n",
|
||||||
filename, linenum, cp ? cp : "<NONE>");
|
filename, linenum, arg ? arg : "<NONE>");
|
||||||
if (*activep && (LogLevel) * intptr == -1)
|
if (*activep && (LogLevel) * intptr == -1)
|
||||||
*intptr = (LogLevel) value;
|
*intptr = (LogLevel) value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case oRemoteForward:
|
case oRemoteForward:
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&s);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
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.",
|
fatal("%.200s line %d: Badly formatted port number.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
fwd_port = atoi(cp);
|
fwd_port = atoi(arg);
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&s);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing second argument.",
|
fatal("%.200s line %d: Missing second argument.",
|
||||||
filename, linenum);
|
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.",
|
fatal("%.200s line %d: Badly formatted host:port.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
if (*activep)
|
if (*activep)
|
||||||
@ -547,18 +548,18 @@ process_config_line(Options *options, const char *host,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case oLocalForward:
|
case oLocalForward:
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&s);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
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.",
|
fatal("%.200s line %d: Badly formatted port number.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
fwd_port = atoi(cp);
|
fwd_port = atoi(arg);
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&s);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing second argument.",
|
fatal("%.200s line %d: Missing second argument.",
|
||||||
filename, linenum);
|
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.",
|
fatal("%.200s line %d: Badly formatted host:port.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
if (*activep)
|
if (*activep)
|
||||||
@ -567,26 +568,26 @@ process_config_line(Options *options, const char *host,
|
|||||||
|
|
||||||
case oHost:
|
case oHost:
|
||||||
*activep = 0;
|
*activep = 0;
|
||||||
while ((cp = strtok(NULL, WHITESPACE)) != NULL)
|
while ((arg = strdelim(&s)) != NULL && *arg != '\0')
|
||||||
if (match_pattern(host, cp)) {
|
if (match_pattern(host, arg)) {
|
||||||
debug("Applying options for %.100s", cp);
|
debug("Applying options for %.100s", arg);
|
||||||
*activep = 1;
|
*activep = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Avoid garbage check below, as strtok already returned NULL. */
|
/* Avoid garbage check below, as strdelim is done. */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case oEscapeChar:
|
case oEscapeChar:
|
||||||
intptr = &options->escape_char;
|
intptr = &options->escape_char;
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&s);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
||||||
if (cp[0] == '^' && cp[2] == 0 &&
|
if (arg[0] == '^' && arg[2] == 0 &&
|
||||||
(unsigned char) cp[1] >= 64 && (unsigned char) cp[1] < 128)
|
(unsigned char) arg[1] >= 64 && (unsigned char) arg[1] < 128)
|
||||||
value = (unsigned char) cp[1] & 31;
|
value = (unsigned char) arg[1] & 31;
|
||||||
else if (strlen(cp) == 1)
|
else if (strlen(arg) == 1)
|
||||||
value = (unsigned char) cp[0];
|
value = (unsigned char) arg[0];
|
||||||
else if (strcmp(cp, "none") == 0)
|
else if (strcmp(arg, "none") == 0)
|
||||||
value = -2;
|
value = -2;
|
||||||
else {
|
else {
|
||||||
fatal("%.200s line %d: Bad escape character.",
|
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. */
|
/* Check that there is no garbage at end of line. */
|
||||||
if (strtok(NULL, WHITESPACE) != NULL)
|
if ((arg = strdelim(&s)) != NULL && *arg != '\0')
|
||||||
fatal("%.200s line %d: garbage at end of line.",
|
{
|
||||||
filename, linenum);
|
fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
|
||||||
|
filename, linenum, arg);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -662,6 +665,7 @@ initialize_options(Options * options)
|
|||||||
memset(options, 'X', sizeof(*options));
|
memset(options, 'X', sizeof(*options));
|
||||||
options->forward_agent = -1;
|
options->forward_agent = -1;
|
||||||
options->forward_x11 = -1;
|
options->forward_x11 = -1;
|
||||||
|
options->xauth_location = NULL;
|
||||||
options->gateway_ports = -1;
|
options->gateway_ports = -1;
|
||||||
options->use_privileged_port = -1;
|
options->use_privileged_port = -1;
|
||||||
options->rhosts_authentication = -1;
|
options->rhosts_authentication = -1;
|
||||||
@ -722,6 +726,10 @@ fill_default_options(Options * options)
|
|||||||
options->forward_agent = 0;
|
options->forward_agent = 0;
|
||||||
if (options->forward_x11 == -1)
|
if (options->forward_x11 == -1)
|
||||||
options->forward_x11 = 0;
|
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)
|
if (options->gateway_ports == -1)
|
||||||
options->gateway_ports = 0;
|
options->gateway_ports = 0;
|
||||||
if (options->use_privileged_port == -1)
|
if (options->use_privileged_port == -1)
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* readconf.h
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
|
||||||
* Created: Sat Apr 22 00:25:29 1995 ylo
|
|
||||||
*
|
|
||||||
* Functions for reading the configuration file.
|
* 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
|
#ifndef READCONF_H
|
||||||
#define READCONF_H
|
#define READCONF_H
|
||||||
@ -31,6 +29,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
int forward_agent; /* Forward authentication agent. */
|
int forward_agent; /* Forward authentication agent. */
|
||||||
int forward_x11; /* Forward X11 display. */
|
int forward_x11; /* Forward X11 display. */
|
||||||
|
char *xauth_location; /* Location for xauth program */
|
||||||
int gateway_ports; /* Allow remote connects to forwarded ports. */
|
int gateway_ports; /* Allow remote connects to forwarded ports. */
|
||||||
int use_privileged_port; /* Don't use privileged port if false. */
|
int use_privileged_port; /* Don't use privileged port if false. */
|
||||||
int rhosts_authentication; /* Try rhosts authentication. */
|
int rhosts_authentication; /* Try rhosts authentication. */
|
||||||
|
@ -1,15 +1,40 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* rsa.c
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* 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.
|
* Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994.
|
||||||
*
|
*
|
||||||
@ -25,18 +50,18 @@
|
|||||||
* Hans Riesel: Prime Numbers and Computer Methods for Factorization.
|
* Hans Riesel: Prime Numbers and Computer Methods for Factorization.
|
||||||
* Birkhauser, 1994.
|
* 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
|
* RSA in 3 lines of perl by Adam Back <aba@atlax.ex.ac.uk>, 1995, as
|
||||||
* below:
|
* included below:
|
||||||
*
|
*
|
||||||
* [gone - had to be deleted - what a pity]
|
* [gone - had to be deleted - what a pity]
|
||||||
*
|
*/
|
||||||
* $FreeBSD$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "rsa.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* rsa.h
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
|
||||||
* Created: Fri Mar 3 22:01:06 1995 ylo
|
|
||||||
*
|
|
||||||
* RSA key generation, encryption and decryption.
|
* 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
|
#ifndef RSA_H
|
||||||
#define 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
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* Created: Mon Aug 21 15:48:58 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
|
||||||
* $FreeBSD$
|
* 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"
|
#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 "ssh.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
@ -45,6 +43,7 @@ initialize_server_options(ServerOptions *options)
|
|||||||
options->check_mail = -1;
|
options->check_mail = -1;
|
||||||
options->x11_forwarding = -1;
|
options->x11_forwarding = -1;
|
||||||
options->x11_display_offset = -1;
|
options->x11_display_offset = -1;
|
||||||
|
options->xauth_location = NULL;
|
||||||
options->strict_modes = -1;
|
options->strict_modes = -1;
|
||||||
options->keepalives = -1;
|
options->keepalives = -1;
|
||||||
options->log_facility = (SyslogFacility) - 1;
|
options->log_facility = (SyslogFacility) - 1;
|
||||||
@ -81,6 +80,10 @@ initialize_server_options(ServerOptions *options)
|
|||||||
options->gateway_ports = -1;
|
options->gateway_ports = -1;
|
||||||
options->connections_per_period = 0;
|
options->connections_per_period = 0;
|
||||||
options->connections_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
|
void
|
||||||
@ -116,6 +119,10 @@ fill_default_server_options(ServerOptions *options)
|
|||||||
options->x11_forwarding = 1;
|
options->x11_forwarding = 1;
|
||||||
if (options->x11_display_offset == -1)
|
if (options->x11_display_offset == -1)
|
||||||
options->x11_display_offset = 10;
|
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)
|
if (options->strict_modes == -1)
|
||||||
options->strict_modes = 1;
|
options->strict_modes = 1;
|
||||||
if (options->keepalives == -1)
|
if (options->keepalives == -1)
|
||||||
@ -166,10 +173,14 @@ fill_default_server_options(ServerOptions *options)
|
|||||||
options->protocol = SSH_PROTO_1|SSH_PROTO_2;
|
options->protocol = SSH_PROTO_1|SSH_PROTO_2;
|
||||||
if (options->gateway_ports == -1)
|
if (options->gateway_ports == -1)
|
||||||
options->gateway_ports = 0;
|
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. */
|
/* Keyword tokens. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
sBadOption, /* == unknown option */
|
sBadOption, /* == unknown option */
|
||||||
@ -193,7 +204,8 @@ typedef enum {
|
|||||||
sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
|
sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
|
||||||
sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
|
sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
|
||||||
sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile,
|
sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile,
|
||||||
sGatewayPorts, sDSAAuthentication, sConnectionsPerPeriod
|
sGatewayPorts, sDSAAuthentication, sConnectionsPerPeriod, sXAuthLocation,
|
||||||
|
sSubsystem, sMaxStartups
|
||||||
} ServerOpCodes;
|
} ServerOpCodes;
|
||||||
|
|
||||||
/* Textual representation of the tokens. */
|
/* Textual representation of the tokens. */
|
||||||
@ -239,6 +251,7 @@ static struct {
|
|||||||
{ "ignoreuserknownhosts", sIgnoreUserKnownHosts },
|
{ "ignoreuserknownhosts", sIgnoreUserKnownHosts },
|
||||||
{ "x11forwarding", sX11Forwarding },
|
{ "x11forwarding", sX11Forwarding },
|
||||||
{ "x11displayoffset", sX11DisplayOffset },
|
{ "x11displayoffset", sX11DisplayOffset },
|
||||||
|
{ "xauthlocation", sXAuthLocation },
|
||||||
{ "strictmodes", sStrictModes },
|
{ "strictmodes", sStrictModes },
|
||||||
{ "permitemptypasswords", sEmptyPasswd },
|
{ "permitemptypasswords", sEmptyPasswd },
|
||||||
{ "uselogin", sUseLogin },
|
{ "uselogin", sUseLogin },
|
||||||
@ -252,6 +265,8 @@ static struct {
|
|||||||
{ "protocol", sProtocol },
|
{ "protocol", sProtocol },
|
||||||
{ "gatewayports", sGatewayPorts },
|
{ "gatewayports", sGatewayPorts },
|
||||||
{ "connectionsperperiod", sConnectionsPerPeriod },
|
{ "connectionsperperiod", sConnectionsPerPeriod },
|
||||||
|
{ "subsystem", sSubsystem },
|
||||||
|
{ "maxstartups", sMaxStartups },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -313,10 +328,11 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char line[1024];
|
char line[1024];
|
||||||
char *cp, **charptr;
|
char *cp, **charptr, *arg;
|
||||||
int linenum, *intptr, value;
|
int linenum, *intptr, value;
|
||||||
int bad_options = 0;
|
int bad_options = 0;
|
||||||
ServerOpCodes opcode;
|
ServerOpCodes opcode;
|
||||||
|
int i;
|
||||||
|
|
||||||
f = fopen(filename, "r");
|
f = fopen(filename, "r");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
@ -326,11 +342,14 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
linenum = 0;
|
linenum = 0;
|
||||||
while (fgets(line, sizeof(line), f)) {
|
while (fgets(line, sizeof(line), f)) {
|
||||||
linenum++;
|
linenum++;
|
||||||
cp = line + strspn(line, WHITESPACE);
|
cp = line;
|
||||||
if (!*cp || *cp == '#')
|
arg = strdelim(&cp);
|
||||||
|
/* Ignore leading whitespace */
|
||||||
|
if (*arg == '\0')
|
||||||
|
arg = strdelim(&cp);
|
||||||
|
if (!*arg || *arg == '#')
|
||||||
continue;
|
continue;
|
||||||
cp = strtok(cp, WHITESPACE);
|
opcode = parse_token(arg, filename, linenum);
|
||||||
opcode = parse_token(cp, filename, linenum);
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case sBadOption:
|
case sBadOption:
|
||||||
bad_options++;
|
bad_options++;
|
||||||
@ -345,23 +364,24 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
if (options->num_ports >= MAX_PORTS)
|
if (options->num_ports >= MAX_PORTS)
|
||||||
fatal("%s line %d: too many ports.\n",
|
fatal("%s line %d: too many ports.\n",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&cp);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%s line %d: missing port number.\n",
|
fatal("%s line %d: missing port number.\n",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
options->ports[options->num_ports++] = atoi(cp);
|
options->ports[options->num_ports++] = atoi(arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sServerKeyBits:
|
case sServerKeyBits:
|
||||||
intptr = &options->server_key_bits;
|
intptr = &options->server_key_bits;
|
||||||
parse_int:
|
parse_int:
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&cp);
|
||||||
if (!cp) {
|
if (!arg || *arg == '\0') {
|
||||||
fprintf(stderr, "%s line %d: missing integer value.\n",
|
fprintf(stderr, "%s line %d: missing integer value.\n",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (sscanf(cp, " %d ", &value) != 1) {
|
value = atoi(arg);
|
||||||
|
if (value == 0) {
|
||||||
fprintf(stderr, "%s line %d: invalid integer value.\n",
|
fprintf(stderr, "%s line %d: invalid integer value.\n",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -379,62 +399,55 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
goto parse_int;
|
goto parse_int;
|
||||||
|
|
||||||
case sListenAddress:
|
case sListenAddress:
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&cp);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%s line %d: missing inet addr.\n",
|
fatal("%s line %d: missing inet addr.\n",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
add_listen_addr(options, cp);
|
add_listen_addr(options, arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sHostKeyFile:
|
case sHostKeyFile:
|
||||||
case sHostDSAKeyFile:
|
case sHostDSAKeyFile:
|
||||||
charptr = (opcode == sHostKeyFile ) ?
|
charptr = (opcode == sHostKeyFile ) ?
|
||||||
&options->host_key_file : &options->host_dsa_key_file;
|
&options->host_key_file : &options->host_dsa_key_file;
|
||||||
cp = strtok(NULL, WHITESPACE);
|
parse_filename:
|
||||||
if (!cp) {
|
arg = strdelim(&cp);
|
||||||
|
if (!arg || *arg == '\0') {
|
||||||
fprintf(stderr, "%s line %d: missing file name.\n",
|
fprintf(stderr, "%s line %d: missing file name.\n",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (*charptr == NULL)
|
if (*charptr == NULL)
|
||||||
*charptr = tilde_expand_filename(cp, getuid());
|
*charptr = tilde_expand_filename(arg, getuid());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sPidFile:
|
case sPidFile:
|
||||||
charptr = &options->pid_file;
|
charptr = &options->pid_file;
|
||||||
cp = strtok(NULL, WHITESPACE);
|
goto parse_filename;
|
||||||
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;
|
|
||||||
|
|
||||||
case sRandomSeedFile:
|
case sRandomSeedFile:
|
||||||
fprintf(stderr, "%s line %d: \"randomseed\" option is obsolete.\n",
|
fprintf(stderr, "%s line %d: \"randomseed\" option is obsolete.\n",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&cp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sPermitRootLogin:
|
case sPermitRootLogin:
|
||||||
intptr = &options->permit_root_login;
|
intptr = &options->permit_root_login;
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&cp);
|
||||||
if (!cp) {
|
if (!arg || *arg == '\0') {
|
||||||
fprintf(stderr, "%s line %d: missing yes/without-password/no argument.\n",
|
fprintf(stderr, "%s line %d: missing yes/without-password/no argument.\n",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (strcmp(cp, "without-password") == 0)
|
if (strcmp(arg, "without-password") == 0)
|
||||||
value = 2;
|
value = 2;
|
||||||
else if (strcmp(cp, "yes") == 0)
|
else if (strcmp(arg, "yes") == 0)
|
||||||
value = 1;
|
value = 1;
|
||||||
else if (strcmp(cp, "no") == 0)
|
else if (strcmp(arg, "no") == 0)
|
||||||
value = 0;
|
value = 0;
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "%s line %d: Bad yes/without-password/no argument: %s\n",
|
fprintf(stderr, "%s line %d: Bad yes/without-password/no argument: %s\n",
|
||||||
filename, linenum, cp);
|
filename, linenum, arg);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (*intptr == -1)
|
if (*intptr == -1)
|
||||||
@ -444,19 +457,19 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
case sIgnoreRhosts:
|
case sIgnoreRhosts:
|
||||||
intptr = &options->ignore_rhosts;
|
intptr = &options->ignore_rhosts;
|
||||||
parse_flag:
|
parse_flag:
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&cp);
|
||||||
if (!cp) {
|
if (!arg || *arg == '\0') {
|
||||||
fprintf(stderr, "%s line %d: missing yes/no argument.\n",
|
fprintf(stderr, "%s line %d: missing yes/no argument.\n",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (strcmp(cp, "yes") == 0)
|
if (strcmp(arg, "yes") == 0)
|
||||||
value = 1;
|
value = 1;
|
||||||
else if (strcmp(cp, "no") == 0)
|
else if (strcmp(arg, "no") == 0)
|
||||||
value = 0;
|
value = 0;
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "%s line %d: Bad yes/no argument: %s\n",
|
fprintf(stderr, "%s line %d: Bad yes/no argument: %s\n",
|
||||||
filename, linenum, cp);
|
filename, linenum, arg);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (*intptr == -1)
|
if (*intptr == -1)
|
||||||
@ -543,6 +556,10 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
intptr = &options->x11_display_offset;
|
intptr = &options->x11_display_offset;
|
||||||
goto parse_int;
|
goto parse_int;
|
||||||
|
|
||||||
|
case sXAuthLocation:
|
||||||
|
charptr = &options->xauth_location;
|
||||||
|
goto parse_filename;
|
||||||
|
|
||||||
case sStrictModes:
|
case sStrictModes:
|
||||||
intptr = &options->strict_modes;
|
intptr = &options->strict_modes;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
@ -565,92 +582,92 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
|
|
||||||
case sLogFacility:
|
case sLogFacility:
|
||||||
intptr = (int *) &options->log_facility;
|
intptr = (int *) &options->log_facility;
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&cp);
|
||||||
value = log_facility_number(cp);
|
value = log_facility_number(arg);
|
||||||
if (value == (SyslogFacility) - 1)
|
if (value == (SyslogFacility) - 1)
|
||||||
fatal("%.200s line %d: unsupported log facility '%s'\n",
|
fatal("%.200s line %d: unsupported log facility '%s'\n",
|
||||||
filename, linenum, cp ? cp : "<NONE>");
|
filename, linenum, arg ? arg : "<NONE>");
|
||||||
if (*intptr == -1)
|
if (*intptr == -1)
|
||||||
*intptr = (SyslogFacility) value;
|
*intptr = (SyslogFacility) value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sLogLevel:
|
case sLogLevel:
|
||||||
intptr = (int *) &options->log_level;
|
intptr = (int *) &options->log_level;
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&cp);
|
||||||
value = log_level_number(cp);
|
value = log_level_number(arg);
|
||||||
if (value == (LogLevel) - 1)
|
if (value == (LogLevel) - 1)
|
||||||
fatal("%.200s line %d: unsupported log level '%s'\n",
|
fatal("%.200s line %d: unsupported log level '%s'\n",
|
||||||
filename, linenum, cp ? cp : "<NONE>");
|
filename, linenum, arg ? arg : "<NONE>");
|
||||||
if (*intptr == -1)
|
if (*intptr == -1)
|
||||||
*intptr = (LogLevel) value;
|
*intptr = (LogLevel) value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sAllowUsers:
|
case sAllowUsers:
|
||||||
while ((cp = strtok(NULL, WHITESPACE))) {
|
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
||||||
if (options->num_allow_users >= MAX_ALLOW_USERS)
|
if (options->num_allow_users >= MAX_ALLOW_USERS)
|
||||||
fatal("%.200s line %d: too many allow users.\n",
|
fatal("%.200s line %d: too many allow users.\n",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
options->allow_users[options->num_allow_users++] = xstrdup(cp);
|
options->allow_users[options->num_allow_users++] = xstrdup(arg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sDenyUsers:
|
case sDenyUsers:
|
||||||
while ((cp = strtok(NULL, WHITESPACE))) {
|
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
||||||
if (options->num_deny_users >= MAX_DENY_USERS)
|
if (options->num_deny_users >= MAX_DENY_USERS)
|
||||||
fatal("%.200s line %d: too many deny users.\n",
|
fatal("%.200s line %d: too many deny users.\n",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
options->deny_users[options->num_deny_users++] = xstrdup(cp);
|
options->deny_users[options->num_deny_users++] = xstrdup(arg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sAllowGroups:
|
case sAllowGroups:
|
||||||
while ((cp = strtok(NULL, WHITESPACE))) {
|
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
||||||
if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
|
if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
|
||||||
fatal("%.200s line %d: too many allow groups.\n",
|
fatal("%.200s line %d: too many allow groups.\n",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
options->allow_groups[options->num_allow_groups++] = xstrdup(cp);
|
options->allow_groups[options->num_allow_groups++] = xstrdup(arg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sDenyGroups:
|
case sDenyGroups:
|
||||||
while ((cp = strtok(NULL, WHITESPACE))) {
|
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
||||||
if (options->num_deny_groups >= MAX_DENY_GROUPS)
|
if (options->num_deny_groups >= MAX_DENY_GROUPS)
|
||||||
fatal("%.200s line %d: too many deny groups.\n",
|
fatal("%.200s line %d: too many deny groups.\n",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
options->deny_groups[options->num_deny_groups++] = xstrdup(cp);
|
options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sCiphers:
|
case sCiphers:
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&cp);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%s line %d: Missing argument.", filename, linenum);
|
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'.",
|
fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
|
||||||
filename, linenum, cp ? cp : "<NONE>");
|
filename, linenum, arg ? arg : "<NONE>");
|
||||||
if (options->ciphers == NULL)
|
if (options->ciphers == NULL)
|
||||||
options->ciphers = xstrdup(cp);
|
options->ciphers = xstrdup(arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sProtocol:
|
case sProtocol:
|
||||||
intptr = &options->protocol;
|
intptr = &options->protocol;
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&cp);
|
||||||
if (!cp)
|
if (!arg || *arg == '\0')
|
||||||
fatal("%s line %d: Missing argument.", filename, linenum);
|
fatal("%s line %d: Missing argument.", filename, linenum);
|
||||||
value = proto_spec(cp);
|
value = proto_spec(arg);
|
||||||
if (value == SSH_PROTO_UNKNOWN)
|
if (value == SSH_PROTO_UNKNOWN)
|
||||||
fatal("%s line %d: Bad protocol spec '%s'.",
|
fatal("%s line %d: Bad protocol spec '%s'.",
|
||||||
filename, linenum, cp ? cp : "<NONE>");
|
filename, linenum, arg ? arg : "<NONE>");
|
||||||
if (*intptr == SSH_PROTO_UNKNOWN)
|
if (*intptr == SSH_PROTO_UNKNOWN)
|
||||||
*intptr = value;
|
*intptr = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sConnectionsPerPeriod:
|
case sConnectionsPerPeriod:
|
||||||
cp = strtok(NULL, WHITESPACE);
|
arg = strdelim(&cp);
|
||||||
if (cp == NULL)
|
if (cp == NULL)
|
||||||
fatal("%.200s line %d: missing (>= 0) number argument.\n",
|
fatal("%.200s line %d: missing (>= 0) number argument.\n",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
if (sscanf(cp, " %u/%u ", &options->connections_per_period,
|
if (sscanf(arg, "%u/%u", &options->connections_per_period,
|
||||||
&options->connections_period) != 2)
|
&options->connections_period) != 2)
|
||||||
fatal("%.200s line %d: invalid numerical argument(s).\n",
|
fatal("%.200s line %d: invalid numerical argument(s).\n",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
@ -660,13 +677,57 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
filename, linenum);
|
filename, linenum);
|
||||||
break;
|
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:
|
default:
|
||||||
fatal("%.200s line %d: Missing handler for opcode %s (%d)\n",
|
fatal("%.200s line %d: Missing handler for opcode %s (%d)\n",
|
||||||
filename, linenum, cp, opcode);
|
filename, linenum,arg, opcode);
|
||||||
}
|
}
|
||||||
if (strtok(NULL, WHITESPACE) != NULL) {
|
if ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
|
||||||
fatal("%.200s line %d: garbage at end of line.\n",
|
fprintf(stderr,
|
||||||
filename, linenum);
|
"%s line %d: garbage at end of line; \"%.200s\".\n",
|
||||||
|
filename, linenum, arg);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
*
|
|
||||||
* servconf.h
|
|
||||||
*
|
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
|
||||||
* Created: Mon Aug 21 15:35:03 1995 ylo
|
|
||||||
*
|
|
||||||
* Definitions for server configuration data and for the functions reading it.
|
* 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
|
#ifndef SERVCONF_H
|
||||||
#define SERVCONF_H
|
#define SERVCONF_H
|
||||||
@ -25,6 +23,7 @@
|
|||||||
#define MAX_DENY_USERS 256 /* Max # users on deny list. */
|
#define MAX_DENY_USERS 256 /* Max # users on deny list. */
|
||||||
#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */
|
#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */
|
||||||
#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
|
#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
|
||||||
|
#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int num_ports;
|
unsigned int num_ports;
|
||||||
@ -48,6 +47,7 @@ typedef struct {
|
|||||||
int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */
|
int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */
|
||||||
int x11_display_offset; /* What DISPLAY number to start
|
int x11_display_offset; /* What DISPLAY number to start
|
||||||
* searching at */
|
* searching at */
|
||||||
|
char *xauth_location; /* Location of xauth program */
|
||||||
int strict_modes; /* If true, require string home dir modes. */
|
int strict_modes; /* If true, require string home dir modes. */
|
||||||
int keepalives; /* If true, set SO_KEEPALIVE. */
|
int keepalives; /* If true, set SO_KEEPALIVE. */
|
||||||
char *ciphers; /* Ciphers in order of preference. */
|
char *ciphers; /* Ciphers in order of preference. */
|
||||||
@ -105,6 +105,15 @@ typedef struct {
|
|||||||
* connections_period.
|
* connections_period.
|
||||||
*/
|
*/
|
||||||
unsigned int 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;
|
} ServerOptions;
|
||||||
/*
|
/*
|
||||||
* Initializes the server options to special values that indicate that they
|
* 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
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* 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.
|
* SSH2 support by Markus Friedl.
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* 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"
|
#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 "xmalloc.h"
|
||||||
#include "ssh.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 "bufaux.h"
|
||||||
#include "ssh2.h"
|
#include "ssh2.h"
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
|
#include "auth-options.h"
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
#define _PATH_CHPASS "/usr/bin/passwd"
|
#define _PATH_CHPASS "/usr/bin/passwd"
|
||||||
#endif /* __FreeBSD__ */
|
#endif /* __FreeBSD__ */
|
||||||
|
|
||||||
#ifdef LOGIN_CAP
|
#ifdef HAVE_LOGIN_CAP
|
||||||
#include <login_cap.h>
|
#include <login_cap.h>
|
||||||
#endif /* LOGIN_CAP */
|
#endif
|
||||||
|
|
||||||
#ifdef KRB5
|
#ifdef KRB5
|
||||||
extern krb5_context ssh_context;
|
extern krb5_context ssh_context;
|
||||||
@ -74,6 +99,7 @@ void session_pty_cleanup(Session *s);
|
|||||||
void session_proctitle(Session *s);
|
void session_proctitle(Session *s);
|
||||||
void do_exec_pty(Session *s, const char *command, struct passwd * pw);
|
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);
|
void do_exec_no_pty(Session *s, const char *command, struct passwd * pw);
|
||||||
|
char *do_login(Session *s, const char *command);
|
||||||
|
|
||||||
void
|
void
|
||||||
do_child(const char *command, struct passwd * pw, const char *term,
|
do_child(const char *command, struct passwd * pw, const char *term,
|
||||||
@ -85,25 +111,23 @@ extern ServerOptions options;
|
|||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
extern int log_stderr;
|
extern int log_stderr;
|
||||||
extern int debug_flag;
|
extern int debug_flag;
|
||||||
|
extern unsigned int utmp_len;
|
||||||
|
|
||||||
|
extern int startup_pipe;
|
||||||
|
|
||||||
/* Local Xauthority file. */
|
/* Local Xauthority file. */
|
||||||
static char *xauthfile;
|
static char *xauthfile;
|
||||||
|
|
||||||
|
/* original command from peer. */
|
||||||
|
char *original_command = NULL;
|
||||||
|
|
||||||
/* data */
|
/* data */
|
||||||
#define MAX_SESSIONS 10
|
#define MAX_SESSIONS 10
|
||||||
Session sessions[MAX_SESSIONS];
|
Session sessions[MAX_SESSIONS];
|
||||||
|
|
||||||
/* Flags set in auth-rsa from authorized_keys flags. These are set in auth-rsa.c. */
|
#ifdef HAVE_LOGIN_CAP
|
||||||
int no_port_forwarding_flag = 0;
|
static login_cap_t *lc;
|
||||||
int no_agent_forwarding_flag = 0;
|
#endif
|
||||||
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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove local Xauthority file.
|
* Remove local Xauthority file.
|
||||||
@ -157,7 +181,7 @@ void
|
|||||||
do_authenticated(struct passwd * pw)
|
do_authenticated(struct passwd * pw)
|
||||||
{
|
{
|
||||||
Session *s;
|
Session *s;
|
||||||
int type;
|
int type, fd;
|
||||||
int compression_level = 0, enable_compression_after_reply = 0;
|
int compression_level = 0, enable_compression_after_reply = 0;
|
||||||
int have_pty = 0;
|
int have_pty = 0;
|
||||||
char *command;
|
char *command;
|
||||||
@ -170,6 +194,10 @@ do_authenticated(struct passwd * pw)
|
|||||||
* authentication.
|
* authentication.
|
||||||
*/
|
*/
|
||||||
alarm(0);
|
alarm(0);
|
||||||
|
if (startup_pipe != -1) {
|
||||||
|
close(startup_pipe);
|
||||||
|
startup_pipe = -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inform the channel mechanism that we are the server side and that
|
* 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 = session_new();
|
||||||
s->pw = pw;
|
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
|
* We stay in this loop until the client requests to execute a shell
|
||||||
* or a command.
|
* or a command.
|
||||||
@ -262,7 +297,10 @@ do_authenticated(struct passwd * pw)
|
|||||||
packet_send_debug("X11 forwarding disabled in server configuration file.");
|
packet_send_debug("X11 forwarding disabled in server configuration file.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef XAUTH_PATH
|
if (!options.xauth_location) {
|
||||||
|
packet_send_debug("No xauth program; cannot forward with spoofing.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (no_x11_forwarding_flag) {
|
if (no_x11_forwarding_flag) {
|
||||||
packet_send_debug("X11 forwarding not permitted for this authentication.");
|
packet_send_debug("X11 forwarding not permitted for this authentication.");
|
||||||
break;
|
break;
|
||||||
@ -298,15 +336,13 @@ do_authenticated(struct passwd * pw)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
strlcat(xauthfile, "/cookies", MAXPATHLEN);
|
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();
|
restore_uid();
|
||||||
fatal_add_cleanup(xauthfile_cleanup_proc, NULL);
|
fatal_add_cleanup(xauthfile_cleanup_proc, NULL);
|
||||||
success = 1;
|
success = 1;
|
||||||
break;
|
break;
|
||||||
#else /* XAUTH_PATH */
|
|
||||||
packet_send_debug("No xauth program; cannot forward with spoofing.");
|
|
||||||
break;
|
|
||||||
#endif /* XAUTH_PATH */
|
|
||||||
|
|
||||||
case SSH_CMSG_AGENT_REQUEST_FORWARDING:
|
case SSH_CMSG_AGENT_REQUEST_FORWARDING:
|
||||||
if (no_agent_forwarding_flag || compat13) {
|
if (no_agent_forwarding_flag || compat13) {
|
||||||
@ -347,6 +383,7 @@ do_authenticated(struct passwd * pw)
|
|||||||
packet_integrity_check(plen, 0, type);
|
packet_integrity_check(plen, 0, type);
|
||||||
}
|
}
|
||||||
if (forced_command != NULL) {
|
if (forced_command != NULL) {
|
||||||
|
original_command = command;
|
||||||
command = forced_command;
|
command = forced_command;
|
||||||
debug("Forced command '%.500s'", 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
|
void
|
||||||
do_exec_pty(Session *s, const char *command, struct passwd * pw)
|
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 fdout, ptyfd, ttyfd, ptymaster;
|
||||||
int quiet_login;
|
|
||||||
pid_t pid;
|
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)
|
if (s == NULL)
|
||||||
fatal("do_exec_pty: no session");
|
fatal("do_exec_pty: no session");
|
||||||
ptyfd = s->ptyfd;
|
ptyfd = s->ptyfd;
|
||||||
ttyfd = s->ttyfd;
|
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. */
|
/* Fork the child. */
|
||||||
if ((pid = fork()) == 0) {
|
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);
|
log_init(__progname, options.log_level, options.log_facility, log_stderr);
|
||||||
|
|
||||||
/* Close the master side of the pseudo tty. */
|
/* 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 the extra descriptor for the pseudo tty. */
|
||||||
close(ttyfd);
|
close(ttyfd);
|
||||||
|
|
||||||
/* XXXX ? move to do_child() ??*/
|
/* record login, etc. similar to login(1) */
|
||||||
/*
|
if (!options.use_login)
|
||||||
* Get IP address of client. This is needed because we want
|
command = do_login(s, command);
|
||||||
* 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 */
|
|
||||||
|
|
||||||
/* Do common processing for the child, such as execing the command. */
|
/* Do common processing for the child, such as execing the command. */
|
||||||
do_child(command, pw, s->term, s->display, s->auth_proto,
|
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
|
* Sets the value of the given variable in the environment. If the variable
|
||||||
* already exists, its value is overriden.
|
* 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 *display, const char *auth_proto,
|
||||||
const char *auth_data, const char *ttyname)
|
const char *auth_data, const char *ttyname)
|
||||||
{
|
{
|
||||||
char *shell;
|
const char *shell, *hostname = NULL, *cp = NULL;
|
||||||
const char *cp = NULL;
|
|
||||||
char buf[256];
|
char buf[256];
|
||||||
FILE *f;
|
char cmd[1024];
|
||||||
|
FILE *f = NULL;
|
||||||
unsigned int envsize, i;
|
unsigned int envsize, i;
|
||||||
char **env = NULL;
|
char **env = NULL;
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char *argv[10];
|
char *argv[10];
|
||||||
#ifdef LOGIN_CAP
|
#ifdef HAVE_LOGIN_CAP
|
||||||
login_cap_t *lc;
|
login_cap_t *lc;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -864,36 +916,32 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
|||||||
if (options.use_login && command != NULL)
|
if (options.use_login && command != NULL)
|
||||||
options.use_login = 0;
|
options.use_login = 0;
|
||||||
|
|
||||||
#ifdef LOGIN_CAP
|
if (!options.use_login) {
|
||||||
lc = login_getpwclass(pw);
|
#ifdef HAVE_LOGIN_CAP
|
||||||
if (lc == NULL)
|
lc = login_getpwclass(pw);
|
||||||
lc = login_getclassbyname(NULL, pw);
|
if (lc == NULL)
|
||||||
if (pw->pw_uid != 0)
|
lc = login_getclassbyname(NULL, pw);
|
||||||
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 (pw->pw_uid != 0)
|
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);
|
exit(254);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* LOGIN_CAP */
|
/* Set login name, uid, gid, and groups. */
|
||||||
|
|
||||||
#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. */
|
|
||||||
/* Login(1) does this as well, and it needs uid 0 for the "-h"
|
/* Login(1) does this as well, and it needs uid 0 for the "-h"
|
||||||
switch, so we let login(1) to this for us. */
|
switch, so we let login(1) to this for us. */
|
||||||
if (!options.use_login) {
|
if (!options.use_login) {
|
||||||
#ifdef LOGIN_CAP
|
#ifdef HAVE_LOGIN_CAP
|
||||||
char **tmpenv;
|
char **tmpenv;
|
||||||
|
|
||||||
/* Initialize temp environment */
|
/* Initialize temp environment */
|
||||||
@ -928,8 +976,18 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
|||||||
envsize = (envsize < 100) ? 100 : envsize + 16;
|
envsize = (envsize < 100) ? 100 : envsize + 16;
|
||||||
env = xrealloc(env, envsize * sizeof(char *));
|
env = xrealloc(env, envsize * sizeof(char *));
|
||||||
|
|
||||||
#else /* !LOGIN_CAP */
|
#endif /* !HAVE_LOGIN_CAP */
|
||||||
if (getuid() == 0 || geteuid() == 0) {
|
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) {
|
if (setgid(pw->pw_gid) < 0) {
|
||||||
perror("setgid");
|
perror("setgid");
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -943,19 +1001,19 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
|||||||
|
|
||||||
/* Permanently switch to the desired uid. */
|
/* Permanently switch to the desired uid. */
|
||||||
permanently_set_uid(pw->pw_uid);
|
permanently_set_uid(pw->pw_uid);
|
||||||
|
#endif /* HAVE_LOGIN_CAP */
|
||||||
}
|
}
|
||||||
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
|
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
|
||||||
fatal("Failed to set uids to %d.", (int) pw->pw_uid);
|
fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
|
||||||
#endif /* LOGIN_CAP */
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Get the shell from the password data. An empty shell field is
|
* Get the shell from the password data. An empty shell field is
|
||||||
* legal, and means /bin/sh.
|
* legal, and means /bin/sh.
|
||||||
*/
|
*/
|
||||||
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
|
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
|
||||||
#ifdef LOGIN_CAP
|
#ifdef HAVE_LOGIN_CAP
|
||||||
shell = login_getcapstr(lc, "shell", shell, shell);
|
shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
|
||||||
#endif /* LOGIN_CAP */
|
#endif
|
||||||
|
|
||||||
#ifdef AFS
|
#ifdef AFS
|
||||||
/* Try to get AFS tokens for the local cell. */
|
/* 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, "USER", pw->pw_name);
|
||||||
child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
|
child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
|
||||||
child_set_env(&env, &envsize, "HOME", pw->pw_dir);
|
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);
|
child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
|
||||||
|
#endif
|
||||||
|
|
||||||
snprintf(buf, sizeof buf, "%.200s/%.50s",
|
snprintf(buf, sizeof buf, "%.200s/%.50s",
|
||||||
_PATH_MAILDIR, pw->pw_name);
|
_PATH_MAILDIR, pw->pw_name);
|
||||||
child_set_env(&env, &envsize, "MAIL", buf);
|
child_set_env(&env, &envsize, "MAIL", buf);
|
||||||
#endif /* !LOGIN_CAP */
|
|
||||||
|
|
||||||
/* Normal systems set SHELL by default. */
|
/* Normal systems set SHELL by default. */
|
||||||
child_set_env(&env, &envsize, "SHELL", shell);
|
child_set_env(&env, &envsize, "SHELL", shell);
|
||||||
}
|
}
|
||||||
#ifdef LOGIN_CAP
|
|
||||||
if (options.use_login)
|
|
||||||
#endif /* LOGIN_CAP */
|
|
||||||
if (getenv("TZ"))
|
if (getenv("TZ"))
|
||||||
child_set_env(&env, &envsize, "TZ", 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);
|
child_set_env(&env, &envsize, "TERM", term);
|
||||||
if (display)
|
if (display)
|
||||||
child_set_env(&env, &envsize, "DISPLAY", display);
|
child_set_env(&env, &envsize, "DISPLAY", display);
|
||||||
|
if (original_command)
|
||||||
|
child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",
|
||||||
|
original_command);
|
||||||
|
|
||||||
#ifdef KRB4
|
#ifdef KRB4
|
||||||
{
|
{
|
||||||
@ -1076,6 +1137,9 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
|||||||
for (i = 0; env[i]; i++)
|
for (i = 0; env[i]; i++)
|
||||||
fprintf(stderr, " %.200s\n", env[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
|
* Close the connection descriptors; note that this is the child, and
|
||||||
* the server will still have the socket open, and it is important
|
* 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__
|
#ifdef __FreeBSD__
|
||||||
int quiet_login = 0;
|
int quiet_login = 0;
|
||||||
#endif /* __FreeBSD__ */
|
#endif /* __FreeBSD__ */
|
||||||
#ifdef LOGIN_CAP
|
#ifdef HAVE_LOGIN_CAP
|
||||||
if (login_getcapbool(lc, "requirehome", 0)) {
|
if (login_getcapbool(lc, "requirehome", 0)) {
|
||||||
(void)printf("Home directory not available\n");
|
(void)printf("Home directory not available\n");
|
||||||
log("LOGIN %.200s REFUSED (HOMEDIR) ON TTY %.200s",
|
log("LOGIN %.200s REFUSED (HOMEDIR) ON TTY %.200s",
|
||||||
pw->pw_name, ttyname);
|
pw->pw_name, ttyname);
|
||||||
exit(254);
|
exit(254);
|
||||||
}
|
}
|
||||||
#endif /* LOGIN_CAP */
|
#endif /* HAVE_LOGIN_CAP */
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
if (chdir("/") < 0) {
|
if (chdir("/") < 0) {
|
||||||
(void)printf("Cannot find root directory\n");
|
(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);
|
pw->pw_name, ttyname);
|
||||||
exit(254);
|
exit(254);
|
||||||
}
|
}
|
||||||
#ifdef LOGIN_CAP
|
#ifdef HAVE_LOGIN_CAP
|
||||||
quiet_login = login_getcapbool(lc, "hushlogin", 0);
|
quiet_login = login_getcapbool(lc, "hushlogin", 0);
|
||||||
#endif /* LOGIN_CAP */
|
#endif /* HAVE_LOGIN_CAP */
|
||||||
if (!quiet_login || *pw->pw_dir)
|
if (!quiet_login || *pw->pw_dir)
|
||||||
(void)printf(
|
(void)printf(
|
||||||
"No home directory.\nLogging in with home = \"/\".\n");
|
"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));
|
pw->pw_dir, strerror(errno));
|
||||||
#endif /* __FreeBSD__ */
|
#endif /* __FreeBSD__ */
|
||||||
}
|
}
|
||||||
#ifdef LOGIN_CAP
|
#ifdef HAVE_LOGIN_CAP
|
||||||
login_close(lc);
|
login_close(lc);
|
||||||
#endif /* LOGIN_CAP */
|
#endif /* HAVE_LOGIN_CAP */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Must take new environment into use so that .ssh/rc, /etc/sshrc and
|
* 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);
|
pclose(f);
|
||||||
} else
|
} else
|
||||||
fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC);
|
fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC);
|
||||||
}
|
} else if (options.xauth_location != NULL) {
|
||||||
#ifdef XAUTH_PATH
|
|
||||||
else {
|
|
||||||
/* Add authority data to .Xauthority if appropriate. */
|
/* Add authority data to .Xauthority if appropriate. */
|
||||||
if (auth_proto != NULL && auth_data != NULL) {
|
if (auth_proto != NULL && auth_data != NULL) {
|
||||||
char *screen = strchr(display, ':');
|
char *screen = strchr(display, ':');
|
||||||
if (debug_flag) {
|
if (debug_flag) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Running %.100s add %.100s %.100s %.100s\n",
|
"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)
|
if (screen != NULL)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Adding %.*s/unix%s %s %s\n",
|
"Adding %.*s/unix%s %s %s\n",
|
||||||
screen-display, display,
|
(int)(screen-display), display,
|
||||||
screen, auth_proto, auth_data);
|
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) {
|
if (f) {
|
||||||
fprintf(f, "add %s %s %s\n", display,
|
fprintf(f, "add %s %s %s\n", display,
|
||||||
auth_proto, auth_data);
|
auth_proto, auth_data);
|
||||||
if (screen != NULL)
|
if (screen != NULL)
|
||||||
fprintf(f, "add %.*s/unix%s %s %s\n",
|
fprintf(f, "add %.*s/unix%s %s %s\n",
|
||||||
screen-display, display,
|
(int)(screen-display), display,
|
||||||
screen, auth_proto, auth_data);
|
screen, auth_proto, auth_data);
|
||||||
pclose(f);
|
pclose(f);
|
||||||
} else
|
} else {
|
||||||
fprintf(stderr, "Could not run %s -q -\n",
|
fprintf(stderr, "Could not run %s\n",
|
||||||
XAUTH_PATH);
|
cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* XAUTH_PATH */
|
|
||||||
|
|
||||||
/* Get the last component of the shell name. */
|
/* Get the last component of the shell name. */
|
||||||
cp = strrchr(shell, '/');
|
cp = strrchr(shell, '/');
|
||||||
if (cp)
|
if (cp)
|
||||||
@ -1273,8 +1337,8 @@ do_child(const char *command, struct passwd * pw, const char *term,
|
|||||||
} else {
|
} else {
|
||||||
/* Launch login(1). */
|
/* Launch login(1). */
|
||||||
|
|
||||||
execl("/usr/bin/login", "login", "-h", get_remote_ipaddr(),
|
execl("/usr/bin/login", "login", "-h", hostname,
|
||||||
"-p", "-f", "--", pw->pw_name, NULL);
|
"-p", "-f", "--", pw->pw_name, NULL);
|
||||||
|
|
||||||
/* Login couldn't be executed, die. */
|
/* Login couldn't be executed, die. */
|
||||||
|
|
||||||
@ -1412,6 +1476,8 @@ session_pty_req(Session *s)
|
|||||||
unsigned int len;
|
unsigned int len;
|
||||||
char *term_modes; /* encoded terminal modes */
|
char *term_modes; /* encoded terminal modes */
|
||||||
|
|
||||||
|
if (no_pty_flag)
|
||||||
|
return 0;
|
||||||
if (s->ttyfd != -1)
|
if (s->ttyfd != -1)
|
||||||
return 0;
|
return 0;
|
||||||
s->term = packet_get_string(&len);
|
s->term = packet_get_string(&len);
|
||||||
@ -1459,10 +1525,22 @@ session_subsystem_req(Session *s)
|
|||||||
unsigned int len;
|
unsigned int len;
|
||||||
int success = 0;
|
int success = 0;
|
||||||
char *subsys = packet_get_string(&len);
|
char *subsys = packet_get_string(&len);
|
||||||
|
int i;
|
||||||
|
|
||||||
packet_done();
|
packet_done();
|
||||||
log("subsystem request for %s", subsys);
|
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);
|
xfree(subsys);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
@ -1470,6 +1548,11 @@ session_subsystem_req(Session *s)
|
|||||||
int
|
int
|
||||||
session_x11_req(Session *s)
|
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) {
|
if (!options.x11_forwarding) {
|
||||||
debug("X11 forwarding disabled in server configuration file.");
|
debug("X11 forwarding disabled in server configuration file.");
|
||||||
return 0;
|
return 0;
|
||||||
@ -1510,12 +1593,49 @@ session_x11_req(Session *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
strlcat(xauthfile, "/cookies", MAXPATHLEN);
|
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();
|
restore_uid();
|
||||||
fatal_add_cleanup(xauthfile_cleanup_proc, s);
|
fatal_add_cleanup(xauthfile_cleanup_proc, s);
|
||||||
return 1;
|
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
|
void
|
||||||
session_input_channel_req(int id, void *arg)
|
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 (c->type == SSH_CHANNEL_LARVAL) {
|
||||||
if (strcmp(rtype, "shell") == 0) {
|
if (strcmp(rtype, "shell") == 0) {
|
||||||
packet_done();
|
success = session_shell_req(s);
|
||||||
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;
|
|
||||||
} else if (strcmp(rtype, "exec") == 0) {
|
} else if (strcmp(rtype, "exec") == 0) {
|
||||||
char *command = packet_get_string(&len);
|
success = session_exec_req(s);
|
||||||
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;
|
|
||||||
} else if (strcmp(rtype, "pty-req") == 0) {
|
} else if (strcmp(rtype, "pty-req") == 0) {
|
||||||
success = session_pty_req(s);
|
success = session_pty_req(s);
|
||||||
} else if (strcmp(rtype, "x11-req") == 0) {
|
} else if (strcmp(rtype, "x11-req") == 0) {
|
||||||
@ -1765,11 +1871,24 @@ session_proctitle(Session *s)
|
|||||||
void
|
void
|
||||||
do_authenticated2(void)
|
do_authenticated2(void)
|
||||||
{
|
{
|
||||||
|
struct passwd *pw;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cancel the alarm we set to limit the time taken for
|
* Cancel the alarm we set to limit the time taken for
|
||||||
* authentication.
|
* authentication.
|
||||||
*/
|
*/
|
||||||
alarm(0);
|
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();
|
server_loop2();
|
||||||
if (xauthfile)
|
if (xauthfile)
|
||||||
xauthfile_cleanup_proc(NULL);
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
* Created: Wed Mar 29 03:46:59 1995 ylo
|
|
||||||
* The authentication agent program.
|
* 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"
|
#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 "ssh.h"
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "authfd.h"
|
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "bufaux.h"
|
#include "bufaux.h"
|
||||||
#include "xmalloc.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 "getput.h"
|
||||||
#include "mpaux.h"
|
#include "mpaux.h"
|
||||||
|
|
||||||
|
#include <openssl/evp.h>
|
||||||
#include <openssl/md5.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 {
|
typedef struct {
|
||||||
int fd;
|
int fd;
|
||||||
@ -37,12 +69,17 @@ unsigned int sockets_alloc = 0;
|
|||||||
SocketEntry *sockets = NULL;
|
SocketEntry *sockets = NULL;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
RSA *key;
|
Key *key;
|
||||||
char *comment;
|
char *comment;
|
||||||
} Identity;
|
} Identity;
|
||||||
|
|
||||||
unsigned int num_identities = 0;
|
typedef struct {
|
||||||
Identity *identities = NULL;
|
int nentries;
|
||||||
|
Identity *identities;
|
||||||
|
} Idtab;
|
||||||
|
|
||||||
|
/* private key table, one per protocol version */
|
||||||
|
Idtab idtable[3];
|
||||||
|
|
||||||
int max_fd = 0;
|
int max_fd = 0;
|
||||||
|
|
||||||
@ -56,175 +93,244 @@ char socket_dir[1024];
|
|||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
void
|
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;
|
Buffer msg;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
buffer_init(&msg);
|
buffer_init(&msg);
|
||||||
buffer_put_char(&msg, SSH_AGENT_RSA_IDENTITIES_ANSWER);
|
buffer_put_char(&msg, (version == 1) ?
|
||||||
buffer_put_int(&msg, num_identities);
|
SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
|
||||||
for (i = 0; i < num_identities; i++) {
|
buffer_put_int(&msg, tab->nentries);
|
||||||
buffer_put_int(&msg, BN_num_bits(identities[i].key->n));
|
for (i = 0; i < tab->nentries; i++) {
|
||||||
buffer_put_bignum(&msg, identities[i].key->e);
|
Identity *id = &tab->identities[i];
|
||||||
buffer_put_bignum(&msg, identities[i].key->n);
|
if (id->key->type == KEY_RSA) {
|
||||||
buffer_put_string(&msg, identities[i].comment,
|
buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
|
||||||
strlen(identities[i].comment));
|
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_put_int(&e->output, buffer_len(&msg));
|
||||||
buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
|
buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
|
||||||
buffer_free(&msg);
|
buffer_free(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ssh1 only */
|
||||||
void
|
void
|
||||||
process_authentication_challenge(SocketEntry *e)
|
process_authentication_challenge1(SocketEntry *e)
|
||||||
{
|
{
|
||||||
int i, pub_bits, len;
|
Key *key, *private;
|
||||||
BIGNUM *pub_e, *pub_n, *challenge;
|
BIGNUM *challenge;
|
||||||
|
int i, len;
|
||||||
Buffer msg;
|
Buffer msg;
|
||||||
MD5_CTX md;
|
MD5_CTX md;
|
||||||
unsigned char buf[32], mdbuf[16], session_id[16];
|
unsigned char buf[32], mdbuf[16], session_id[16];
|
||||||
unsigned int response_type;
|
unsigned int response_type;
|
||||||
|
|
||||||
buffer_init(&msg);
|
buffer_init(&msg);
|
||||||
pub_e = BN_new();
|
key = key_new(KEY_RSA);
|
||||||
pub_n = BN_new();
|
|
||||||
challenge = BN_new();
|
challenge = BN_new();
|
||||||
pub_bits = buffer_get_int(&e->input);
|
|
||||||
buffer_get_bignum(&e->input, pub_e);
|
buffer_get_int(&e->input); /* ignored */
|
||||||
buffer_get_bignum(&e->input, pub_n);
|
buffer_get_bignum(&e->input, key->rsa->e);
|
||||||
|
buffer_get_bignum(&e->input, key->rsa->n);
|
||||||
buffer_get_bignum(&e->input, challenge);
|
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. */
|
/* Only protocol 1.1 is supported */
|
||||||
switch (response_type) {
|
if (buffer_len(&e->input) == 0)
|
||||||
case 0:/* As of protocol 1.0 */
|
goto failure;
|
||||||
/* This response type is no longer supported. */
|
buffer_get(&e->input, (char *) session_id, 16);
|
||||||
log("Compatibility with ssh protocol 1.0 no longer supported.");
|
response_type = buffer_get_int(&e->input);
|
||||||
buffer_put_char(&msg, SSH_AGENT_FAILURE);
|
if (response_type != 1)
|
||||||
goto send;
|
goto failure;
|
||||||
|
|
||||||
case 1:/* As of protocol 1.1 */
|
private = lookup_private_key(key, NULL, 1);
|
||||||
/* The response is MD5 of decrypted challenge plus session id. */
|
if (private != NULL) {
|
||||||
len = BN_num_bytes(challenge);
|
/* Decrypt the challenge using the private key. */
|
||||||
|
rsa_private_decrypt(challenge, challenge, private->rsa);
|
||||||
|
|
||||||
if (len <= 0 || len > 32) {
|
/* The response is MD5 of decrypted challenge plus session id. */
|
||||||
fatal("process_authentication_challenge: "
|
len = BN_num_bytes(challenge);
|
||||||
"bad challenge length %d", len);
|
if (len <= 0 || len > 32) {
|
||||||
}
|
log("process_authentication_challenge: bad challenge length %d", len);
|
||||||
memset(buf, 0, 32);
|
goto failure;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
/* 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);
|
buffer_put_char(&msg, SSH_AGENT_FAILURE);
|
||||||
send:
|
send:
|
||||||
buffer_put_int(&e->output, buffer_len(&msg));
|
buffer_put_int(&e->output, buffer_len(&msg));
|
||||||
buffer_append(&e->output, buffer_ptr(&msg),
|
buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
|
||||||
buffer_len(&msg));
|
key_free(key);
|
||||||
buffer_free(&msg);
|
|
||||||
BN_clear_free(pub_e);
|
|
||||||
BN_clear_free(pub_n);
|
|
||||||
BN_clear_free(challenge);
|
BN_clear_free(challenge);
|
||||||
|
buffer_free(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ssh2 only */
|
||||||
void
|
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 bits;
|
||||||
unsigned int i;
|
int success = 0;
|
||||||
BIGNUM *dummy, *n;
|
|
||||||
|
|
||||||
dummy = BN_new();
|
switch(version){
|
||||||
n = BN_new();
|
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. */
|
if (bits != key_size(key))
|
||||||
bits = buffer_get_int(&e->input);
|
log("Warning: identity keysize mismatch: actual %d, announced %d",
|
||||||
buffer_get_bignum(&e->input, dummy);
|
key_size(key), bits);
|
||||||
buffer_get_bignum(&e->input, n);
|
break;
|
||||||
|
case 2:
|
||||||
if (bits != BN_num_bits(n))
|
blob = buffer_get_string(&e->input, &blen);
|
||||||
log("Warning: identity keysize mismatch: actual %d, announced %d",
|
key = dsa_key_from_blob(blob, blen);
|
||||||
BN_num_bits(n), bits);
|
xfree(blob);
|
||||||
|
break;
|
||||||
/* Check if we have the key. */
|
}
|
||||||
for (i = 0; i < num_identities; i++)
|
if (key != NULL) {
|
||||||
if (BN_cmp(identities[i].key->n, n) == 0) {
|
int idx;
|
||||||
|
private = lookup_private_key(key, &idx, version);
|
||||||
|
if (private != NULL) {
|
||||||
/*
|
/*
|
||||||
* We have this key. Free the old key. Since we
|
* We have this key. Free the old key. Since we
|
||||||
* don\'t want to leave empty slots in the middle of
|
* don\'t want to leave empty slots in the middle of
|
||||||
* the array, we actually free the key there and copy
|
* the array, we actually free the key there and copy
|
||||||
* data from the last entry.
|
* data from the last entry.
|
||||||
*/
|
*/
|
||||||
RSA_free(identities[i].key);
|
Idtab *tab = idtab_lookup(version);
|
||||||
xfree(identities[i].comment);
|
key_free(tab->identities[idx].key);
|
||||||
if (i < num_identities - 1)
|
xfree(tab->identities[idx].comment);
|
||||||
identities[i] = identities[num_identities - 1];
|
if (idx != tab->nentries)
|
||||||
num_identities--;
|
tab->identities[idx] = tab->identities[tab->nentries];
|
||||||
BN_clear_free(dummy);
|
tab->nentries--;
|
||||||
BN_clear_free(n);
|
success = 1;
|
||||||
|
|
||||||
/* Send success. */
|
|
||||||
buffer_put_int(&e->output, 1);
|
|
||||||
buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
/* We did not have the key. */
|
key_free(key);
|
||||||
BN_clear(dummy);
|
}
|
||||||
BN_clear(n);
|
|
||||||
|
|
||||||
/* Send failure. */
|
|
||||||
buffer_put_int(&e->output, 1);
|
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
|
void
|
||||||
process_remove_all_identities(SocketEntry *e)
|
process_remove_all_identities(SocketEntry *e, int version)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
Idtab *tab = idtab_lookup(version);
|
||||||
|
|
||||||
/* Loop over all identities and clear the keys. */
|
/* Loop over all identities and clear the keys. */
|
||||||
for (i = 0; i < num_identities; i++) {
|
for (i = 0; i < tab->nentries; i++) {
|
||||||
RSA_free(identities[i].key);
|
key_free(tab->identities[i].key);
|
||||||
xfree(identities[i].comment);
|
xfree(tab->identities[i].comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark that there are no identities. */
|
/* Mark that there are no identities. */
|
||||||
num_identities = 0;
|
tab->nentries = 0;
|
||||||
|
|
||||||
/* Send success. */
|
/* Send success. */
|
||||||
buffer_put_int(&e->output, 1);
|
buffer_put_int(&e->output, 1);
|
||||||
@ -232,79 +338,108 @@ process_remove_all_identities(SocketEntry *e)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Adds an identity to the agent.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
process_add_identity(SocketEntry *e)
|
process_add_identity(SocketEntry *e, int version)
|
||||||
{
|
{
|
||||||
RSA *k;
|
Key *k = NULL;
|
||||||
int i;
|
RSA *rsa;
|
||||||
BIGNUM *aux;
|
BIGNUM *aux;
|
||||||
BN_CTX *ctx;
|
BN_CTX *ctx;
|
||||||
|
char *type;
|
||||||
|
char *comment;
|
||||||
|
int success = 0;
|
||||||
|
Idtab *tab = idtab_lookup(version);
|
||||||
|
|
||||||
if (num_identities == 0)
|
switch (version) {
|
||||||
identities = xmalloc(sizeof(Identity));
|
case 1:
|
||||||
else
|
k = key_new(KEY_RSA);
|
||||||
identities = xrealloc(identities, (num_identities + 1) * sizeof(Identity));
|
rsa = k->rsa;
|
||||||
|
|
||||||
identities[num_identities].key = RSA_new();
|
/* allocate mem for private key */
|
||||||
k = identities[num_identities].key;
|
/* XXX rsa->n and rsa->e are already allocated */
|
||||||
buffer_get_int(&e->input); /* bits */
|
rsa->d = BN_new();
|
||||||
k->n = BN_new();
|
rsa->iqmp = BN_new();
|
||||||
buffer_get_bignum(&e->input, k->n);
|
rsa->q = BN_new();
|
||||||
k->e = BN_new();
|
rsa->p = BN_new();
|
||||||
buffer_get_bignum(&e->input, k->e);
|
rsa->dmq1 = BN_new();
|
||||||
k->d = BN_new();
|
rsa->dmp1 = 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 */
|
|
||||||
|
|
||||||
/* Generate additional parameters */
|
buffer_get_int(&e->input); /* ignored */
|
||||||
aux = BN_new();
|
|
||||||
ctx = BN_CTX_new();
|
|
||||||
|
|
||||||
BN_sub(aux, k->q, BN_value_one());
|
buffer_get_bignum(&e->input, rsa->n);
|
||||||
k->dmq1 = BN_new();
|
buffer_get_bignum(&e->input, rsa->e);
|
||||||
BN_mod(k->dmq1, k->d, aux, ctx);
|
buffer_get_bignum(&e->input, rsa->d);
|
||||||
|
buffer_get_bignum(&e->input, rsa->iqmp);
|
||||||
|
|
||||||
BN_sub(aux, k->p, BN_value_one());
|
/* SSH and SSL have p and q swapped */
|
||||||
k->dmp1 = BN_new();
|
buffer_get_bignum(&e->input, rsa->q); /* p */
|
||||||
BN_mod(k->dmp1, k->d, aux, ctx);
|
buffer_get_bignum(&e->input, rsa->p); /* q */
|
||||||
|
|
||||||
BN_clear_free(aux);
|
/* Generate additional parameters */
|
||||||
BN_CTX_free(ctx);
|
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. */
|
BN_sub(aux, rsa->p, BN_value_one());
|
||||||
for (i = 0; i < num_identities; i++)
|
BN_mod(rsa->dmp1, rsa->d, aux, ctx);
|
||||||
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);
|
|
||||||
|
|
||||||
/* Send success. */
|
BN_clear_free(aux);
|
||||||
buffer_put_int(&e->output, 1);
|
BN_CTX_free(ctx);
|
||||||
buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
|
|
||||||
return;
|
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. */
|
xfree(type);
|
||||||
num_identities++;
|
|
||||||
|
|
||||||
/* 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_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
|
void
|
||||||
process_message(SocketEntry *e)
|
process_message(SocketEntry *e)
|
||||||
{
|
{
|
||||||
@ -327,20 +462,37 @@ process_message(SocketEntry *e)
|
|||||||
type = buffer_get_char(&e->input);
|
type = buffer_get_char(&e->input);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
|
/* ssh1 */
|
||||||
process_request_identity(e);
|
|
||||||
break;
|
|
||||||
case SSH_AGENTC_RSA_CHALLENGE:
|
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;
|
break;
|
||||||
case SSH_AGENTC_ADD_RSA_IDENTITY:
|
case SSH_AGENTC_ADD_RSA_IDENTITY:
|
||||||
process_add_identity(e);
|
process_add_identity(e, 1);
|
||||||
break;
|
break;
|
||||||
case SSH_AGENTC_REMOVE_RSA_IDENTITY:
|
case SSH_AGENTC_REMOVE_RSA_IDENTITY:
|
||||||
process_remove_identity(e);
|
process_remove_identity(e, 1);
|
||||||
break;
|
break;
|
||||||
case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Unknown message. Respond with failure. */
|
/* Unknown message. Respond with failure. */
|
||||||
@ -537,7 +689,7 @@ main(int ac, char **av)
|
|||||||
if (ac > 0 && (c_flag || k_flag || s_flag))
|
if (ac > 0 && (c_flag || k_flag || s_flag))
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
if (ac == 0 && !c_flag && !s_flag) {
|
if (ac == 0 && !c_flag && !k_flag && !s_flag) {
|
||||||
shell = getenv("SHELL");
|
shell = getenv("SHELL");
|
||||||
if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
|
if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
|
||||||
c_flag = 1;
|
c_flag = 1;
|
||||||
@ -641,6 +793,7 @@ main(int ac, char **av)
|
|||||||
signal(SIGALRM, check_parent_exists);
|
signal(SIGALRM, check_parent_exists);
|
||||||
alarm(10);
|
alarm(10);
|
||||||
}
|
}
|
||||||
|
idtab_init();
|
||||||
signal(SIGINT, SIG_IGN);
|
signal(SIGINT, SIG_IGN);
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
signal(SIGHUP, cleanup_exit);
|
signal(SIGHUP, cleanup_exit);
|
||||||
|
@ -1,15 +1,39 @@
|
|||||||
.\" -*- nroff -*-
|
.\" -*- nroff -*-
|
||||||
.\"
|
.\"
|
||||||
.\" ssh.1.in
|
|
||||||
.\"
|
|
||||||
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
|
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
.\"
|
|
||||||
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
.\" All rights reserved
|
.\" All rights reserved
|
||||||
.\"
|
.\"
|
||||||
.\" 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$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd September 25, 1999
|
.Dd September 25, 1999
|
||||||
@ -942,6 +966,13 @@ The argument must be
|
|||||||
.Dq yes
|
.Dq yes
|
||||||
or
|
or
|
||||||
.Dq no .
|
.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
|
.Sh ENVIRONMENT
|
||||||
.Nm
|
.Nm
|
||||||
will normally set the following environment variables:
|
will normally set the following environment variables:
|
||||||
@ -1186,6 +1217,7 @@ above.
|
|||||||
.It Pa libcrypto.so.X.1
|
.It Pa libcrypto.so.X.1
|
||||||
A version of this library which includes support for the RSA algorithm
|
A version of this library which includes support for the RSA algorithm
|
||||||
is required for proper operation.
|
is required for proper operation.
|
||||||
|
.El
|
||||||
.Sh AUTHOR
|
.Sh AUTHOR
|
||||||
OpenSSH
|
OpenSSH
|
||||||
is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen,
|
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 .
|
.Xr skey 1 .
|
||||||
.El
|
.El
|
||||||
.Pp
|
.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,
|
OpenSSH has been created by Aaron Campbell, Bob Beck, Markus Friedl,
|
||||||
Niels Provos, Theo de Raadt, and Dug Song.
|
Niels Provos, Theo de Raadt, and Dug Song.
|
||||||
.Pp
|
.Pp
|
||||||
|
@ -2,18 +2,45 @@
|
|||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
* Created: Sat Mar 18 16:36:11 1995 ylo
|
|
||||||
* Ssh client program. This program can be used to log into a remote machine.
|
* Ssh client program. This program can be used to log into a remote machine.
|
||||||
* The software supports strong authentication, encryption, and forwarding
|
* The software supports strong authentication, encryption, and forwarding
|
||||||
* of X11, TCP/IP, and authentication connections.
|
* 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"
|
#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/evp.h>
|
||||||
#include <openssl/dsa.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 "ssh.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "authfd.h"
|
|
||||||
#include "readconf.h"
|
#include "readconf.h"
|
||||||
#include "uidswap.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 "compat.h"
|
||||||
#include "channels.h"
|
#include "channels.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
#include "authfd.h"
|
||||||
#include "authfile.h"
|
#include "authfile.h"
|
||||||
|
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
@ -117,7 +144,6 @@ usage()
|
|||||||
#endif /* AFS */
|
#endif /* AFS */
|
||||||
fprintf(stderr, " -X Enable X11 connection forwarding.\n");
|
fprintf(stderr, " -X Enable X11 connection forwarding.\n");
|
||||||
fprintf(stderr, " -x Disable 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, " -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 Tty; allocate a tty even if command is given.\n");
|
||||||
fprintf(stderr, " -T Do not allocate a tty.\n");
|
fprintf(stderr, " -T Do not allocate a tty.\n");
|
||||||
@ -249,8 +275,8 @@ main(int ac, char **av)
|
|||||||
cp = strrchr(av0, '/') + 1;
|
cp = strrchr(av0, '/') + 1;
|
||||||
else
|
else
|
||||||
cp = av0;
|
cp = av0;
|
||||||
if (strcmp(cp, "rsh") != 0 && strcmp(cp, "ssh") != 0 &&
|
if (strcmp(cp, "rsh") && strcmp(cp, "ssh") && strcmp(cp, "rlogin") &&
|
||||||
strcmp(cp, "rlogin") != 0 && strcmp(cp, "slogin") != 0)
|
strcmp(cp, "slogin") && strcmp(cp, "remsh"))
|
||||||
host = cp;
|
host = cp;
|
||||||
|
|
||||||
for (optind = 1; optind < ac; optind++) {
|
for (optind = 1; optind < ac; optind++) {
|
||||||
@ -458,7 +484,7 @@ main(int ac, char **av)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Cannot fork to background if no command. */
|
/* 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.");
|
fatal("Cannot fork into background without a command to execute.");
|
||||||
|
|
||||||
/* Allocate a tty by default if no command specified. */
|
/* 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_passwd = xstrdup(pw->pw_passwd);
|
||||||
pwcopy.pw_uid = pw->pw_uid;
|
pwcopy.pw_uid = pw->pw_uid;
|
||||||
pwcopy.pw_gid = pw->pw_gid;
|
pwcopy.pw_gid = pw->pw_gid;
|
||||||
|
pwcopy.pw_class = xstrdup(pw->pw_class);
|
||||||
pwcopy.pw_dir = xstrdup(pw->pw_dir);
|
pwcopy.pw_dir = xstrdup(pw->pw_dir);
|
||||||
pwcopy.pw_shell = xstrdup(pw->pw_shell);
|
pwcopy.pw_shell = xstrdup(pw->pw_shell);
|
||||||
pwcopy.pw_class = xstrdup(pw->pw_class);
|
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);
|
snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_DIR);
|
||||||
if (stat(buf, &st) < 0)
|
if (stat(buf, &st) < 0)
|
||||||
if (mkdir(buf, 0755) < 0)
|
if (mkdir(buf, 0700) < 0)
|
||||||
error("Could not create directory '%.200s'.", buf);
|
error("Could not create directory '%.200s'.", buf);
|
||||||
|
|
||||||
/* Check if the connection failed, and try "rsh" if appropriate. */
|
/* 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;
|
FILE *f;
|
||||||
int got_data = 0, i;
|
int got_data = 0, i;
|
||||||
|
|
||||||
#ifdef XAUTH_PATH
|
if (options.xauth_location) {
|
||||||
/* Try to get Xauthority information for the display. */
|
/* Try to get Xauthority information for the display. */
|
||||||
snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null",
|
snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null",
|
||||||
XAUTH_PATH, getenv("DISPLAY"));
|
options.xauth_location, getenv("DISPLAY"));
|
||||||
f = popen(line, "r");
|
f = popen(line, "r");
|
||||||
if (f && fgets(line, sizeof(line), f) &&
|
if (f && fgets(line, sizeof(line), f) &&
|
||||||
sscanf(line, "%*s %s %s", proto, data) == 2)
|
sscanf(line, "%*s %s %s", proto, data) == 2)
|
||||||
got_data = 1;
|
got_data = 1;
|
||||||
if (f)
|
if (f)
|
||||||
pclose(f);
|
pclose(f);
|
||||||
#endif /* XAUTH_PATH */
|
}
|
||||||
/*
|
/*
|
||||||
* If we didn't get authentication data, just make up some
|
* If we didn't get authentication data, just make up some
|
||||||
* data. The forwarding code will check the validity of the
|
* data. The forwarding code will check the validity of the
|
||||||
@ -871,7 +898,7 @@ ssh_session(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Enter the interactive session. */
|
/* 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
|
void
|
||||||
@ -954,31 +981,40 @@ int
|
|||||||
ssh_session2(void)
|
ssh_session2(void)
|
||||||
{
|
{
|
||||||
int window, packetmax, id;
|
int window, packetmax, id;
|
||||||
int in = dup(STDIN_FILENO);
|
int in, out, err;
|
||||||
int out = dup(STDOUT_FILENO);
|
|
||||||
int err = dup(STDERR_FILENO);
|
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)
|
if (in < 0 || out < 0 || err < 0)
|
||||||
fatal("dump in/out/err failed");
|
fatal("dup() in/out/err failed");
|
||||||
|
|
||||||
/* should be pre-session */
|
/* should be pre-session */
|
||||||
init_local_fwd();
|
init_local_fwd();
|
||||||
|
|
||||||
window = 32*1024;
|
/* If requested, let ssh continue in the background. */
|
||||||
if (tty_flag) {
|
if (fork_after_authentication_flag)
|
||||||
packetmax = window/8;
|
if (daemon(1, 1) < 0)
|
||||||
} else {
|
fatal("daemon() failed: %.200s", strerror(errno));
|
||||||
window *= 2;
|
|
||||||
packetmax = window/2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
window = CHAN_SES_WINDOW_DEFAULT;
|
||||||
|
packetmax = CHAN_SES_PACKET_DEFAULT;
|
||||||
|
if (!tty_flag) {
|
||||||
|
window *= 2;
|
||||||
|
packetmax *=2;
|
||||||
|
}
|
||||||
id = channel_new(
|
id = channel_new(
|
||||||
"session", SSH_CHANNEL_OPENING, in, out, err,
|
"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_open(id);
|
||||||
channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0);
|
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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
*
|
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* Created: Fri Mar 17 17:09:37 1995 ylo
|
|
||||||
*
|
|
||||||
* Generic header file for ssh.
|
* 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
|
#ifndef SSH_H
|
||||||
#define 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 */
|
/* remove newline at end of string */
|
||||||
char *chop(char *s);
|
char *chop(char *s);
|
||||||
|
|
||||||
|
/* return next token in configuration line */
|
||||||
|
char *strdelim(char **s);
|
||||||
|
|
||||||
/* set filedescriptor to non-blocking */
|
/* set filedescriptor to non-blocking */
|
||||||
void set_nonblock(int fd);
|
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);
|
void server_loop2(void);
|
||||||
|
|
||||||
/* Client side main loop for the interactive session. */
|
/* 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). */
|
/* Linked list of custom environment strings (see auth-rsa.c). */
|
||||||
struct envstring {
|
struct envstring {
|
||||||
|
@ -2,15 +2,19 @@
|
|||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
* Created: Sat Mar 18 22:15:47 1995 ylo
|
|
||||||
* Code to connect to a remote host, and to perform the client side of the
|
* Code to connect to a remote host, and to perform the client side of the
|
||||||
* login (authentication) dialog.
|
* 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"
|
#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/bn.h>
|
||||||
#include <openssl/dsa.h>
|
#include <openssl/dsa.h>
|
||||||
@ -191,8 +195,8 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
|
|||||||
int gaierr;
|
int gaierr;
|
||||||
struct linger linger;
|
struct linger linger;
|
||||||
|
|
||||||
debug("ssh_connect: getuid %d geteuid %d anon %d",
|
debug("ssh_connect: getuid %u geteuid %u anon %d",
|
||||||
(int) getuid(), (int) geteuid(), anonymous);
|
(u_int) getuid(), (u_int) geteuid(), anonymous);
|
||||||
|
|
||||||
/* Get default port if port has not been set. */
|
/* Get default port if port has not been set. */
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
@ -312,23 +316,28 @@ ssh_exchange_identification()
|
|||||||
int connection_out = packet_get_connection_out();
|
int connection_out = packet_get_connection_out();
|
||||||
|
|
||||||
/* Read other side\'s version identification. */
|
/* Read other side\'s version identification. */
|
||||||
for (i = 0; i < sizeof(buf) - 1; i++) {
|
for (;;) {
|
||||||
int len = read(connection_in, &buf[i], 1);
|
for (i = 0; i < sizeof(buf) - 1; i++) {
|
||||||
if (len < 0)
|
int len = atomicio(read, connection_in, &buf[i], 1);
|
||||||
fatal("ssh_exchange_identification: read: %.100s", strerror(errno));
|
if (len < 0)
|
||||||
if (len != 1)
|
fatal("ssh_exchange_identification: read: %.100s", strerror(errno));
|
||||||
fatal("ssh_exchange_identification: Connection closed by remote host");
|
if (len != 1)
|
||||||
if (buf[i] == '\r') {
|
fatal("ssh_exchange_identification: Connection closed by remote host");
|
||||||
buf[i] = '\n';
|
if (buf[i] == '\r') {
|
||||||
buf[i + 1] = 0;
|
buf[i] = '\n';
|
||||||
continue; /**XXX wait for \n */
|
buf[i + 1] = 0;
|
||||||
|
continue; /**XXX wait for \n */
|
||||||
|
}
|
||||||
|
if (buf[i] == '\n') {
|
||||||
|
buf[i + 1] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (buf[i] == '\n') {
|
buf[sizeof(buf) - 1] = 0;
|
||||||
buf[i + 1] = 0;
|
if (strncmp(buf, "SSH-", 4) == 0)
|
||||||
break;
|
break;
|
||||||
}
|
debug("ssh_exchange_identification: %s", buf);
|
||||||
}
|
}
|
||||||
buf[sizeof(buf) - 1] = 0;
|
|
||||||
server_version_string = xstrdup(buf);
|
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. */
|
/* Get local user name. Use it as server user if no user name was given. */
|
||||||
pw = getpwuid(original_real_uid);
|
pw = getpwuid(original_real_uid);
|
||||||
if (!pw)
|
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);
|
local_user = xstrdup(pw->pw_name);
|
||||||
server_user = options.user ? options.user : local_user;
|
server_user = options.user ? options.user : local_user;
|
||||||
|
|
||||||
|
@ -2,15 +2,19 @@
|
|||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
* Created: Sat Mar 18 22:15:47 1995 ylo
|
|
||||||
* Code to connect to a remote host, and to perform the client side of the
|
* Code to connect to a remote host, and to perform the client side of the
|
||||||
* login (authentication) dialog.
|
* 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"
|
#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/bn.h>
|
||||||
#include <openssl/dsa.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 "ssh.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "authfd.h"
|
|
||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
#include "mpaux.h"
|
#include "mpaux.h"
|
||||||
#include "uidswap.h"
|
#include "uidswap.h"
|
||||||
#include "readconf.h"
|
#include "readconf.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
#include "authfd.h"
|
||||||
#include "sshconnect.h"
|
#include "sshconnect.h"
|
||||||
#include "authfile.h"
|
#include "authfile.h"
|
||||||
|
|
||||||
@ -45,27 +49,27 @@ extern char *__progname;
|
|||||||
int
|
int
|
||||||
try_agent_authentication()
|
try_agent_authentication()
|
||||||
{
|
{
|
||||||
int status, type;
|
int type;
|
||||||
char *comment;
|
char *comment;
|
||||||
AuthenticationConnection *auth;
|
AuthenticationConnection *auth;
|
||||||
unsigned char response[16];
|
unsigned char response[16];
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
BIGNUM *e, *n, *challenge;
|
int plen, clen;
|
||||||
|
Key *key;
|
||||||
|
BIGNUM *challenge;
|
||||||
|
|
||||||
/* Get connection to the agent. */
|
/* Get connection to the agent. */
|
||||||
auth = ssh_get_authentication_connection();
|
auth = ssh_get_authentication_connection();
|
||||||
if (!auth)
|
if (!auth)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
e = BN_new();
|
|
||||||
n = BN_new();
|
|
||||||
challenge = BN_new();
|
challenge = BN_new();
|
||||||
|
key = key_new(KEY_RSA);
|
||||||
|
|
||||||
/* Loop through identities served by the agent. */
|
/* Loop through identities served by the agent. */
|
||||||
for (status = ssh_get_first_identity(auth, e, n, &comment);
|
for (key = ssh_get_first_identity(auth, &comment, 1);
|
||||||
status;
|
key != NULL;
|
||||||
status = ssh_get_next_identity(auth, e, n, &comment)) {
|
key = ssh_get_next_identity(auth, &comment, 1)) {
|
||||||
int plen, clen;
|
|
||||||
|
|
||||||
/* Try this identity. */
|
/* Try this identity. */
|
||||||
debug("Trying RSA authentication via agent with '%.100s'", comment);
|
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. */
|
/* Tell the server that we are willing to authenticate using this key. */
|
||||||
packet_start(SSH_CMSG_AUTH_RSA);
|
packet_start(SSH_CMSG_AUTH_RSA);
|
||||||
packet_put_bignum(n);
|
packet_put_bignum(key->rsa->n);
|
||||||
packet_send();
|
packet_send();
|
||||||
packet_write_wait();
|
packet_write_wait();
|
||||||
|
|
||||||
@ -84,6 +88,7 @@ try_agent_authentication()
|
|||||||
does not support RSA authentication. */
|
does not support RSA authentication. */
|
||||||
if (type == SSH_SMSG_FAILURE) {
|
if (type == SSH_SMSG_FAILURE) {
|
||||||
debug("Server refused our key.");
|
debug("Server refused our key.");
|
||||||
|
key_free(key);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Otherwise it should have sent a challenge. */
|
/* Otherwise it should have sent a challenge. */
|
||||||
@ -98,13 +103,16 @@ try_agent_authentication()
|
|||||||
debug("Received RSA challenge from server.");
|
debug("Received RSA challenge from server.");
|
||||||
|
|
||||||
/* Ask the agent to decrypt the challenge. */
|
/* Ask the agent to decrypt the challenge. */
|
||||||
if (!ssh_decrypt_challenge(auth, e, n, challenge,
|
if (!ssh_decrypt_challenge(auth, key, challenge, session_id, 1, response)) {
|
||||||
session_id, 1, response)) {
|
/*
|
||||||
/* The agent failed to authenticate this identifier although it
|
* The agent failed to authenticate this identifier
|
||||||
advertised it supports this. Just return a wrong value. */
|
* although it advertised it supports this. Just
|
||||||
|
* return a wrong value.
|
||||||
|
*/
|
||||||
log("Authentication agent failed to decrypt challenge.");
|
log("Authentication agent failed to decrypt challenge.");
|
||||||
memset(response, 0, sizeof(response));
|
memset(response, 0, sizeof(response));
|
||||||
}
|
}
|
||||||
|
key_free(key);
|
||||||
debug("Sending response to RSA challenge.");
|
debug("Sending response to RSA challenge.");
|
||||||
|
|
||||||
/* Send the decrypted challenge back to the server. */
|
/* Send the decrypted challenge back to the server. */
|
||||||
@ -119,10 +127,8 @@ try_agent_authentication()
|
|||||||
|
|
||||||
/* The server returns success if it accepted the authentication. */
|
/* The server returns success if it accepted the authentication. */
|
||||||
if (type == SSH_SMSG_SUCCESS) {
|
if (type == SSH_SMSG_SUCCESS) {
|
||||||
debug("RSA authentication accepted by server.");
|
|
||||||
BN_clear_free(e);
|
|
||||||
BN_clear_free(n);
|
|
||||||
BN_clear_free(challenge);
|
BN_clear_free(challenge);
|
||||||
|
debug("RSA authentication accepted by server.");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* Otherwise it should return failure. */
|
/* Otherwise it should return failure. */
|
||||||
@ -130,11 +136,7 @@ try_agent_authentication()
|
|||||||
packet_disconnect("Protocol error waiting RSA auth response: %d",
|
packet_disconnect("Protocol error waiting RSA auth response: %d",
|
||||||
type);
|
type);
|
||||||
}
|
}
|
||||||
|
|
||||||
BN_clear_free(e);
|
|
||||||
BN_clear_free(n);
|
|
||||||
BN_clear_free(challenge);
|
BN_clear_free(challenge);
|
||||||
|
|
||||||
debug("RSA authentication using agent refused.");
|
debug("RSA authentication using agent refused.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,39 @@
|
|||||||
.\" -*- nroff -*-
|
.\" -*- nroff -*-
|
||||||
.\"
|
.\"
|
||||||
.\" sshd.8.in
|
|
||||||
.\"
|
|
||||||
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
|
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
.\"
|
|
||||||
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
.\" All rights reserved
|
.\" All rights reserved
|
||||||
.\"
|
.\"
|
||||||
.\" 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$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd September 25, 1999
|
.Dd September 25, 1999
|
||||||
@ -27,6 +51,7 @@
|
|||||||
.Op Fl h Ar host_key_file
|
.Op Fl h Ar host_key_file
|
||||||
.Op Fl k Ar key_gen_time
|
.Op Fl k Ar key_gen_time
|
||||||
.Op Fl p Ar port
|
.Op Fl p Ar port
|
||||||
|
.Op Fl u Ar len
|
||||||
.Op Fl V Ar client_protocol_id
|
.Op Fl V Ar client_protocol_id
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
@ -105,7 +130,7 @@ into the machine).
|
|||||||
.Pp
|
.Pp
|
||||||
.Ss SSH protocol version 2
|
.Ss SSH protocol version 2
|
||||||
.Pp
|
.Pp
|
||||||
Version 2 works similar:
|
Version 2 works similarly:
|
||||||
Each host has a host-specific DSA key used to identify the host.
|
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.
|
However, when the daemon starts, it does not generate a server key.
|
||||||
Forward security is provided through a Diffie-Hellman key agreement.
|
Forward security is provided through a Diffie-Hellman key agreement.
|
||||||
@ -212,6 +237,22 @@ Quiet mode.
|
|||||||
Nothing is sent to the system log.
|
Nothing is sent to the system log.
|
||||||
Normally the beginning,
|
Normally the beginning,
|
||||||
authentication, and termination of each connection is logged.
|
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
|
.It Fl Q
|
||||||
Do not print an error message if RSA support is missing.
|
Do not print an error message if RSA support is missing.
|
||||||
.It Fl V Ar client_protocol_id
|
.It Fl V Ar client_protocol_id
|
||||||
@ -258,7 +299,7 @@ and
|
|||||||
.Ql ?
|
.Ql ?
|
||||||
can be used as
|
can be used as
|
||||||
wildcards in the patterns.
|
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.
|
By default login is allowed regardless of the primary group.
|
||||||
.Pp
|
.Pp
|
||||||
.It Cm AllowUsers
|
.It Cm AllowUsers
|
||||||
@ -271,7 +312,7 @@ and
|
|||||||
.Ql ?
|
.Ql ?
|
||||||
can be used as
|
can be used as
|
||||||
wildcards in the patterns.
|
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.
|
By default login is allowed regardless of the user name.
|
||||||
.Pp
|
.Pp
|
||||||
.It Cm Ciphers
|
.It Cm Ciphers
|
||||||
@ -320,7 +361,7 @@ and
|
|||||||
.Ql ?
|
.Ql ?
|
||||||
can be used as
|
can be used as
|
||||||
wildcards in the patterns.
|
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.
|
By default login is allowed regardless of the primary group.
|
||||||
.Pp
|
.Pp
|
||||||
.It Cm DenyUsers
|
.It Cm DenyUsers
|
||||||
@ -331,7 +372,7 @@ Login is disallowed for user names that match one of the patterns.
|
|||||||
and
|
and
|
||||||
.Ql ?
|
.Ql ?
|
||||||
can be used as wildcards in the patterns.
|
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.
|
By default login is allowed regardless of the user name.
|
||||||
.It Cm DSAAuthentication
|
.It Cm DSAAuthentication
|
||||||
Specifies whether DSA authentication is allowed.
|
Specifies whether DSA authentication is allowed.
|
||||||
@ -347,7 +388,7 @@ or
|
|||||||
.Dq no .
|
.Dq no .
|
||||||
The default is
|
The default is
|
||||||
.Dq no .
|
.Dq no .
|
||||||
.It Cm HostDsaKey
|
.It Cm HostDSAKey
|
||||||
Specifies the file containing the private DSA host key (default
|
Specifies the file containing the private DSA host key (default
|
||||||
.Pa /etc/ssh/ssh_host_dsa_key )
|
.Pa /etc/ssh/ssh_host_dsa_key )
|
||||||
used by SSH protocol 2.0.
|
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
|
This can be in the form of a Kerberos ticket, or if
|
||||||
.Cm PasswordAuthentication
|
.Cm PasswordAuthentication
|
||||||
is yes, the password provided by the user will be validated through
|
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
|
Default is
|
||||||
.Dq yes .
|
.Dq yes .
|
||||||
.It Cm KerberosOrLocalPasswd
|
.It Cm KerberosOrLocalPasswd
|
||||||
@ -461,11 +503,36 @@ QUIET, FATAL, ERROR, INFO, VERBOSE and DEBUG.
|
|||||||
The default is INFO.
|
The default is INFO.
|
||||||
Logging with level DEBUG violates the privacy of users
|
Logging with level DEBUG violates the privacy of users
|
||||||
and is not recommended.
|
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
|
.It Cm PasswordAuthentication
|
||||||
Specifies whether password authentication is allowed.
|
Specifies whether password authentication is allowed.
|
||||||
The default is
|
The default is
|
||||||
.Dq yes .
|
.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
|
.It Cm PermitEmptyPasswords
|
||||||
When password authentication is allowed, it specifies whether the
|
When password authentication is allowed, it specifies whether the
|
||||||
server allows login to accounts with empty password strings.
|
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.
|
directory or files world-writable.
|
||||||
The default is
|
The default is
|
||||||
.Dq yes .
|
.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
|
.It Cm SyslogFacility
|
||||||
Gives the facility code that is used when logging messages from
|
Gives the facility code that is used when logging messages from
|
||||||
.Nm sshd .
|
.Nm sshd .
|
||||||
@ -583,7 +660,10 @@ The default is AUTH.
|
|||||||
.It Cm UseLogin
|
.It Cm UseLogin
|
||||||
Specifies whether
|
Specifies whether
|
||||||
.Xr login 1
|
.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
|
The default is
|
||||||
.Dq no .
|
.Dq no .
|
||||||
.It Cm X11DisplayOffset
|
.It Cm X11DisplayOffset
|
||||||
@ -600,6 +680,12 @@ The default is
|
|||||||
.Dq no .
|
.Dq no .
|
||||||
Note that disabling X11 forwarding does not improve security in any
|
Note that disabling X11 forwarding does not improve security in any
|
||||||
way, as users can always install their own forwarders.
|
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
|
.El
|
||||||
.Sh LOGIN PROCESS
|
.Sh LOGIN PROCESS
|
||||||
When a user successfully logs in,
|
When a user successfully logs in,
|
||||||
@ -677,7 +763,7 @@ You don't want to type them in; instead, copy the
|
|||||||
.Pa identity.pub
|
.Pa identity.pub
|
||||||
file and edit it.
|
file and edit it.
|
||||||
.Pp
|
.Pp
|
||||||
The options (if present) consists of comma-separated option
|
The options (if present) consist of comma-separated option
|
||||||
specifications.
|
specifications.
|
||||||
No spaces are permitted, except within double quotes.
|
No spaces are permitted, except within double quotes.
|
||||||
The following option specifications are supported:
|
The following option specifications are supported:
|
||||||
@ -751,7 +837,7 @@ and
|
|||||||
files contain host public keys for all known hosts.
|
files contain host public keys for all known hosts.
|
||||||
The global file should
|
The global file should
|
||||||
be prepared by the administrator (optional), and the per-user file is
|
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.
|
its key is added to the per-user file.
|
||||||
.Pp
|
.Pp
|
||||||
Each line in these files contains the following fields: hostnames,
|
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
|
listening for connections (if there are several daemons running
|
||||||
concurrently for different ports, this contains the pid of the one
|
concurrently for different ports, this contains the pid of the one
|
||||||
started last).
|
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
|
.It Pa $HOME/.ssh/authorized_keys
|
||||||
Lists the RSA keys that can be used to log into the user's account.
|
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
|
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.
|
authentication to check the public key of the host.
|
||||||
The key must be listed in one of these files to be accepted.
|
The key must be listed in one of these files to be accepted.
|
||||||
The client uses the same files
|
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.
|
These files should be writable only by root/the owner.
|
||||||
.Pa /etc/ssh/ssh_known_hosts
|
.Pa /etc/ssh/ssh_known_hosts
|
||||||
should be world-readable, and
|
should be world-readable, and
|
||||||
@ -983,6 +1069,7 @@ Like
|
|||||||
This can be used to specify
|
This can be used to specify
|
||||||
machine-specific login-time initializations globally.
|
machine-specific login-time initializations globally.
|
||||||
This file should be writable only by root, and should be world-readable.
|
This file should be writable only by root, and should be world-readable.
|
||||||
|
.El
|
||||||
.Sh AUTHOR
|
.Sh AUTHOR
|
||||||
OpenSSH
|
OpenSSH
|
||||||
is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen,
|
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 .
|
.Xr skey 1 .
|
||||||
.El
|
.El
|
||||||
.Pp
|
.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,
|
OpenSSH has been created by Aaron Campbell, Bob Beck, Markus Friedl,
|
||||||
Niels Provos, Theo de Raadt, and Dug Song.
|
Niels Provos, Theo de Raadt, and Dug Song.
|
||||||
.Pp
|
.Pp
|
||||||
The support for SSH protocol 2 was written by Markus Friedl.
|
The support for SSH protocol 2 was written by Markus Friedl.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr scp 1 ,
|
.Xr scp 1 ,
|
||||||
|
.Xr sftp-server 8 ,
|
||||||
.Xr ssh 1 ,
|
.Xr ssh 1 ,
|
||||||
.Xr ssh-add 1 ,
|
.Xr ssh-add 1 ,
|
||||||
.Xr ssh-agent 1 ,
|
.Xr ssh-agent 1 ,
|
||||||
|
@ -2,21 +2,46 @@
|
|||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
* Created: Fri Mar 17 17:09:28 1995 ylo
|
* This program is the ssh daemon. It listens for connections from clients,
|
||||||
* This program is the ssh daemon. It listens for connections from clients, and
|
* and performs authentication, executes use commands or shell, and forwards
|
||||||
* performs authentication, executes use commands or shell, and forwards
|
|
||||||
* information to/from the application to the user client over an encrypted
|
* information to/from the application to the user client over an encrypted
|
||||||
* connection. This can also handle forwarding of X11, TCP/IP, and authentication
|
* connection. This can also handle forwarding of X11, TCP/IP, and
|
||||||
* agent connections.
|
* authentication agent connections.
|
||||||
*
|
*
|
||||||
* SSH2 implementation,
|
* As far as I am concerned, the code I have written for this software
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* 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"
|
#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 "xmalloc.h"
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
@ -168,6 +193,9 @@ timevaldiff(struct timeval *tv1, struct timeval *tv2) {
|
|||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* record remote hostname or ip */
|
||||||
|
unsigned int utmp_len = MAXHOSTNAMELEN;
|
||||||
|
|
||||||
/* Prototypes for various functions defined later in this file. */
|
/* Prototypes for various functions defined later in this file. */
|
||||||
void do_ssh1_kex();
|
void do_ssh1_kex();
|
||||||
void do_ssh2_kex();
|
void do_ssh2_kex();
|
||||||
@ -327,7 +355,7 @@ sshd_exchange_identification(int sock_in, int sock_out)
|
|||||||
|
|
||||||
/* Read other side\'s version identification. */
|
/* Read other side\'s version identification. */
|
||||||
for (i = 0; i < sizeof(buf) - 1; i++) {
|
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());
|
log("Did not receive ident string from %s.", get_remote_ipaddr());
|
||||||
fatal_cleanup();
|
fatal_cleanup();
|
||||||
}
|
}
|
||||||
@ -380,7 +408,7 @@ sshd_exchange_identification(int sock_in, int sock_out)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (remote_minor < 3) {
|
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.");
|
"is no longer supported. Please install a newer version.");
|
||||||
} else if (remote_minor == 3) {
|
} else if (remote_minor == 3) {
|
||||||
/* note that this disables agent-forwarding */
|
/* note that this disables agent-forwarding */
|
||||||
@ -430,6 +458,38 @@ destroy_sensitive_data(void)
|
|||||||
key_free(sensitive_data.dsa_host_key);
|
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.
|
* Main program for the daemon.
|
||||||
*/
|
*/
|
||||||
@ -438,7 +498,7 @@ main(int ac, char **av)
|
|||||||
{
|
{
|
||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
extern int optind;
|
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;
|
pid_t pid;
|
||||||
socklen_t fromlen;
|
socklen_t fromlen;
|
||||||
int ratelim_exceeded = 0;
|
int ratelim_exceeded = 0;
|
||||||
@ -452,6 +512,8 @@ main(int ac, char **av)
|
|||||||
struct addrinfo *ai;
|
struct addrinfo *ai;
|
||||||
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
|
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
|
||||||
int listen_sock, maxfd;
|
int listen_sock, maxfd;
|
||||||
|
int startup_p[2];
|
||||||
|
int startups = 0;
|
||||||
|
|
||||||
/* Save argv[0]. */
|
/* Save argv[0]. */
|
||||||
saved_argv = av;
|
saved_argv = av;
|
||||||
@ -464,7 +526,7 @@ main(int ac, char **av)
|
|||||||
initialize_server_options(&options);
|
initialize_server_options(&options);
|
||||||
|
|
||||||
/* Parse command-line arguments. */
|
/* Parse command-line arguments. */
|
||||||
while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:diqQ46")) != EOF) {
|
while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:diqQ46")) != EOF) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case '4':
|
case '4':
|
||||||
IPv4or6 = AF_INET;
|
IPv4or6 = AF_INET;
|
||||||
@ -511,6 +573,9 @@ main(int ac, char **av)
|
|||||||
/* only makes sense with inetd_flag, i.e. no listen() */
|
/* only makes sense with inetd_flag, i.e. no listen() */
|
||||||
inetd_flag = 1;
|
inetd_flag = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'u':
|
||||||
|
utmp_len = atoi(optarg);
|
||||||
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "sshd version %s\n", SSH_VERSION);
|
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, " -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",
|
fprintf(stderr, " -h file File from which to read host key (default: %s)\n",
|
||||||
HOST_KEY_FILE);
|
HOST_KEY_FILE);
|
||||||
|
fprintf(stderr, " -u len Maximum hostname length for utmp recording\n");
|
||||||
fprintf(stderr, " -4 Use IPv4 only\n");
|
fprintf(stderr, " -4 Use IPv4 only\n");
|
||||||
fprintf(stderr, " -6 Use IPv6 only\n");
|
fprintf(stderr, " -6 Use IPv6 only\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -665,6 +731,7 @@ main(int ac, char **av)
|
|||||||
s2 = dup(s1);
|
s2 = dup(s1);
|
||||||
sock_in = dup(0);
|
sock_in = dup(0);
|
||||||
sock_out = dup(1);
|
sock_out = dup(1);
|
||||||
|
startup_pipe = -1;
|
||||||
/*
|
/*
|
||||||
* We intentionally do not close the descriptors 0, 1, and 2
|
* We intentionally do not close the descriptors 0, 1, and 2
|
||||||
* as our code for setting the descriptors won\'t work if
|
* 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. */
|
/* Arrange to restart on SIGHUP. The handler needs listen_sock. */
|
||||||
signal(SIGHUP, sighup_handler);
|
signal(SIGHUP, sighup_handler);
|
||||||
|
|
||||||
signal(SIGTERM, sigterm_handler);
|
signal(SIGTERM, sigterm_handler);
|
||||||
signal(SIGQUIT, sigterm_handler);
|
signal(SIGQUIT, sigterm_handler);
|
||||||
|
|
||||||
@ -780,12 +848,15 @@ main(int ac, char **av)
|
|||||||
signal(SIGCHLD, main_sigchld_handler);
|
signal(SIGCHLD, main_sigchld_handler);
|
||||||
|
|
||||||
/* setup fd set for listen */
|
/* setup fd set for listen */
|
||||||
|
fdset = NULL;
|
||||||
maxfd = 0;
|
maxfd = 0;
|
||||||
for (i = 0; i < num_listen_socks; i++)
|
for (i = 0; i < num_listen_socks; i++)
|
||||||
if (listen_socks[i] > maxfd)
|
if (listen_socks[i] > maxfd)
|
||||||
maxfd = listen_socks[i];
|
maxfd = listen_socks[i];
|
||||||
fdsetsz = howmany(maxfd, NFDBITS) * sizeof(fd_mask);
|
/* pipes connected to unauthenticated childs */
|
||||||
fdset = (fd_set *)xmalloc(fdsetsz);
|
startup_pipes = xmalloc(options.max_startups * sizeof(int));
|
||||||
|
for (i = 0; i < options.max_startups; i++)
|
||||||
|
startup_pipes[i] = -1;
|
||||||
|
|
||||||
ratelim_init();
|
ratelim_init();
|
||||||
|
|
||||||
@ -796,116 +867,165 @@ main(int ac, char **av)
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
if (received_sighup)
|
if (received_sighup)
|
||||||
sighup_restart();
|
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);
|
memset(fdset, 0, fdsetsz);
|
||||||
|
|
||||||
for (i = 0; i < num_listen_socks; i++)
|
for (i = 0; i < num_listen_socks; i++)
|
||||||
FD_SET(listen_socks[i], fdset);
|
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 (select(maxfd + 1, fdset, NULL, NULL, NULL) < 0) {
|
||||||
if (errno != EINTR)
|
if (errno != EINTR)
|
||||||
error("select: %.100s", strerror(errno));
|
error("select: %.100s", strerror(errno));
|
||||||
continue;
|
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++) {
|
for (i = 0; i < num_listen_socks; i++) {
|
||||||
if (!FD_ISSET(listen_socks[i], fdset))
|
if (!FD_ISSET(listen_socks[i], fdset))
|
||||||
continue;
|
continue;
|
||||||
fromlen = sizeof(from);
|
fromlen = sizeof(from);
|
||||||
newsock = accept(listen_socks[i], (struct sockaddr *)&from,
|
newsock = accept(listen_socks[i], (struct sockaddr *)&from,
|
||||||
&fromlen);
|
&fromlen);
|
||||||
if (newsock < 0) {
|
if (newsock < 0) {
|
||||||
if (errno != EINTR && errno != EWOULDBLOCK)
|
if (errno != EINTR && errno != EWOULDBLOCK)
|
||||||
error("accept: %.100s", strerror(errno));
|
error("accept: %.100s", strerror(errno));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (fcntl(newsock, F_SETFL, 0) < 0) {
|
if (fcntl(newsock, F_SETFL, 0) < 0) {
|
||||||
error("newsock del O_NONBLOCK: %s", strerror(errno));
|
error("newsock del O_NONBLOCK: %s", strerror(errno));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (options.connections_per_period != 0) {
|
if (drop_connection(startups) == 1) {
|
||||||
struct timeval diff, connections_end;
|
debug("drop connection #%d", startups);
|
||||||
struct ratelim_connection *rc;
|
close(newsock);
|
||||||
|
continue;
|
||||||
(void)gettimeofday(&connections_end, NULL);
|
}
|
||||||
rc = &ratelim_connections[i];
|
if (pipe(startup_p) == -1) {
|
||||||
diff = timevaldiff(&rc->connections_begin,
|
close(newsock);
|
||||||
&connections_end);
|
continue;
|
||||||
if (diff.tv_sec >= options.connections_period) {
|
}
|
||||||
/*
|
|
||||||
* Slide the window forward only after
|
for (j = 0; j < options.max_startups; j++)
|
||||||
* completely leaving it.
|
if (startup_pipes[j] == -1) {
|
||||||
*/
|
startup_pipes[j] = startup_p[0];
|
||||||
rc->connections_begin = connections_end;
|
if (maxfd < startup_p[0])
|
||||||
rc->connections_this_period = 1;
|
maxfd = startup_p[0];
|
||||||
} else {
|
startups++;
|
||||||
if (++rc->connections_this_period >
|
break;
|
||||||
options.connections_per_period)
|
}
|
||||||
ratelim_exceeded = 1;
|
|
||||||
|
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
|
* Got connection. Fork a child to handle it, unless
|
||||||
* the child process the connection. The
|
* we are in debugging mode.
|
||||||
* parent continues listening.
|
|
||||||
*/
|
*/
|
||||||
if ((pid = fork()) == 0) {
|
if (debug_flag) {
|
||||||
/*
|
/*
|
||||||
* Child. Close the listening socket, and start using the
|
* In debugging mode. Close the listening
|
||||||
* accepted socket. Reinitialize logging (since our pid has
|
* socket, and start processing the
|
||||||
* changed). We break out of the loop to handle the connection.
|
* connection without forking.
|
||||||
*/
|
*/
|
||||||
|
debug("Server will not fork when running in debugging mode.");
|
||||||
close_listen_socks();
|
close_listen_socks();
|
||||||
sock_in = newsock;
|
sock_in = newsock;
|
||||||
sock_out = newsock;
|
sock_out = newsock;
|
||||||
log_init(av0, options.log_level, options.log_facility, log_stderr);
|
startup_pipe = -1;
|
||||||
|
pid = getpid();
|
||||||
break;
|
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) */
|
/* child process check (or debug mode) */
|
||||||
if (num_listen_socks < 0)
|
if (num_listen_socks < 0)
|
||||||
break;
|
break;
|
||||||
|
@ -53,3 +53,7 @@ PermitEmptyPasswords no
|
|||||||
|
|
||||||
CheckMail yes
|
CheckMail yes
|
||||||
#UseLogin no
|
#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