- Merged very large OpenBSD source code reformat

- OpenBSD CVS updates
   - [channels.c cipher.c compat.c log-client.c scp.c serverloop.c]
     [ssh.h sshd.8 sshd.c]
     syslog changes:
     * Unified Logmessage for all auth-types, for success and for failed
     * Standard connections get only ONE line in the LOG when level==LOG:
       Auth-attempts are logged only, if authentication is:
          a) successfull or
          b) with passwd or
          c) we had more than AUTH_FAIL_LOG failues
     * many log() became verbose()
     * old behaviour with level=VERBOSE
   - [readconf.c readconf.h ssh.1 ssh.h sshconnect.c sshd.c]
     tranfer s/key challenge/response data in SSH_SMSG_AUTH_TIS_CHALLENGE
     messages. allows use of s/key in windows (ttssh, securecrt) and
     ssh-1.2.27 clients without 'ssh -v', ok: niels@
   - [sshd.8]
     -V, for fallback to openssh in SSH2 compatibility mode
   - [sshd.c]
     fix sigchld race; cjc5@po.cwru.edu
This commit is contained in:
Damien Miller 1999-11-25 00:26:21 +11:00
Родитель 4d2f15f895
Коммит 95def09838
73 изменённых файлов: 14494 добавлений и 14898 удалений

Просмотреть файл

@ -1,3 +1,26 @@
19991124
- Merged very large OpenBSD source code reformat
- OpenBSD CVS updates
- [channels.c cipher.c compat.c log-client.c scp.c serverloop.c]
[ssh.h sshd.8 sshd.c]
syslog changes:
* Unified Logmessage for all auth-types, for success and for failed
* Standard connections get only ONE line in the LOG when level==LOG:
Auth-attempts are logged only, if authentication is:
a) successfull or
b) with passwd or
c) we had more than AUTH_FAIL_LOG failues
* many log() became verbose()
* old behaviour with level=VERBOSE
- [readconf.c readconf.h ssh.1 ssh.h sshconnect.c sshd.c]
tranfer s/key challenge/response data in SSH_SMSG_AUTH_TIS_CHALLENGE
messages. allows use of s/key in windows (ttssh, securecrt) and
ssh-1.2.27 clients without 'ssh -v', ok: niels@
- [sshd.8]
-V, for fallback to openssh in SSH2 compatibility mode
- [sshd.c]
fix sigchld race; cjc5@po.cwru.edu
19991123
- Added SuSE package files from Chris Saia <csaia@wtower.com>
- Restructured package-related files under packages/*

Просмотреть файл

@ -1,13 +1,7 @@
/*
auth-kerberos.c
Dug Song <dugsong@UMICH.EDU>
Kerberos v4 authentication and ticket-passing routines.
$Id: auth-krb4.c,v 1.4 1999/11/15 04:25:10 damien Exp $
*/
* Dug Song <dugsong@UMICH.EDU>
* Kerberos v4 authentication and ticket-passing routines.
*/
#include "includes.h"
#include "packet.h"
@ -20,216 +14,222 @@ char *ticket = NULL;
void
krb4_cleanup_proc(void *ignore)
{
debug("krb4_cleanup_proc called");
if (ticket) {
(void) dest_tkt();
xfree(ticket);
ticket = NULL;
}
debug("krb4_cleanup_proc called");
if (ticket) {
(void) dest_tkt();
xfree(ticket);
ticket = NULL;
}
}
int krb4_init(uid_t uid)
int
krb4_init(uid_t uid)
{
static int cleanup_registered = 0;
char *tkt_root = TKT_ROOT;
struct stat st;
int fd;
static int cleanup_registered = 0;
char *tkt_root = TKT_ROOT;
struct stat st;
int fd;
if (!ticket) {
/* Set unique ticket string manually since we're still root. */
ticket = xmalloc(MAXPATHLEN);
if (!ticket) {
/* Set unique ticket string manually since we're still root. */
ticket = xmalloc(MAXPATHLEN);
#ifdef AFS
if (lstat("/ticket", &st) != -1)
tkt_root = "/ticket/";
if (lstat("/ticket", &st) != -1)
tkt_root = "/ticket/";
#endif /* AFS */
snprintf(ticket, MAXPATHLEN, "%s%d_%d", tkt_root, uid, getpid());
(void) krb_set_tkt_string(ticket);
}
/* Register ticket cleanup in case of fatal error. */
if (!cleanup_registered) {
fatal_add_cleanup(krb4_cleanup_proc, NULL);
cleanup_registered = 1;
}
/* Try to create our ticket file. */
if ((fd = mkstemp(ticket)) != -1) {
close(fd);
return 1;
}
/* Ticket file exists - make sure user owns it (just passed ticket). */
if (lstat(ticket, &st) != -1) {
if (st.st_mode == (S_IFREG|S_IRUSR|S_IWUSR) && st.st_uid == uid)
return 1;
}
/* Failure - cancel cleanup function, leaving bad ticket for inspection. */
log("WARNING: bad ticket file %s", ticket);
fatal_remove_cleanup(krb4_cleanup_proc, NULL);
cleanup_registered = 0;
xfree(ticket);
ticket = NULL;
return 0;
snprintf(ticket, MAXPATHLEN, "%s%d_%d", tkt_root, uid, getpid());
(void) krb_set_tkt_string(ticket);
}
/* Register ticket cleanup in case of fatal error. */
if (!cleanup_registered) {
fatal_add_cleanup(krb4_cleanup_proc, NULL);
cleanup_registered = 1;
}
/* Try to create our ticket file. */
if ((fd = mkstemp(ticket)) != -1) {
close(fd);
return 1;
}
/* Ticket file exists - make sure user owns it (just passed ticket). */
if (lstat(ticket, &st) != -1) {
if (st.st_mode == (S_IFREG | S_IRUSR | S_IWUSR) &&
st.st_uid == uid)
return 1;
}
/* Failure - cancel cleanup function, leaving bad ticket for inspection. */
log("WARNING: bad ticket file %s", ticket);
fatal_remove_cleanup(krb4_cleanup_proc, NULL);
cleanup_registered = 0;
xfree(ticket);
ticket = NULL;
return 0;
}
int auth_krb4(const char *server_user, KTEXT auth, char **client)
int
auth_krb4(const char *server_user, KTEXT auth, char **client)
{
AUTH_DAT adat = { 0 };
KTEXT_ST reply;
char instance[INST_SZ];
int r, s;
u_int cksum;
Key_schedule schedule;
struct sockaddr_in local, foreign;
s = packet_get_connection_in();
r = sizeof(local);
memset(&local, 0, sizeof(local));
if (getsockname(s, (struct sockaddr *) &local, &r) < 0)
debug("getsockname failed: %.100s", strerror(errno));
r = sizeof(foreign);
memset(&foreign, 0, sizeof(foreign));
if (getpeername(s, (struct sockaddr *)&foreign, &r) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
instance[0] = '*'; instance[1] = 0;
/* Get the encrypted request, challenge, and session key. */
if ((r = krb_rd_req(auth, KRB4_SERVICE_NAME, instance, 0, &adat, ""))) {
packet_send_debug("Kerberos V4 krb_rd_req: %.100s", krb_err_txt[r]);
return 0;
}
des_key_sched((des_cblock *)adat.session, schedule);
*client = xmalloc(MAX_K_NAME_SZ);
(void) snprintf(*client, MAX_K_NAME_SZ, "%s%s%s@%s", adat.pname,
*adat.pinst ? "." : "", adat.pinst, adat.prealm);
AUTH_DAT adat = {0};
KTEXT_ST reply;
char instance[INST_SZ];
int r, s;
u_int cksum;
Key_schedule schedule;
struct sockaddr_in local, foreign;
/* Check ~/.klogin authorization now. */
if (kuserok(&adat, (char *)server_user) != KSUCCESS) {
packet_send_debug("Kerberos V4 .klogin authorization failed!");
log("Kerberos V4 .klogin authorization failed for %s to account %s",
*client, server_user);
xfree(*client);
return 0;
}
/* Increment the checksum, and return it encrypted with the session key. */
cksum = adat.checksum + 1;
cksum = htonl(cksum);
/* If we can't successfully encrypt the checksum, we send back an empty
message, admitting our failure. */
if ((r = krb_mk_priv((u_char *)&cksum, reply.dat, sizeof(cksum)+1,
schedule, &adat.session, &local, &foreign)) < 0) {
packet_send_debug("Kerberos V4 mk_priv: (%d) %s", r, krb_err_txt[r]);
reply.dat[0] = 0;
reply.length = 0;
}
else reply.length = r;
/* Clear session key. */
memset(&adat.session, 0, sizeof(&adat.session));
packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE);
packet_put_string((char *) reply.dat, reply.length);
packet_send();
packet_write_wait();
return 1;
s = packet_get_connection_in();
r = sizeof(local);
memset(&local, 0, sizeof(local));
if (getsockname(s, (struct sockaddr *) & local, &r) < 0)
debug("getsockname failed: %.100s", strerror(errno));
r = sizeof(foreign);
memset(&foreign, 0, sizeof(foreign));
if (getpeername(s, (struct sockaddr *) & foreign, &r) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
instance[0] = '*';
instance[1] = 0;
/* Get the encrypted request, challenge, and session key. */
if ((r = krb_rd_req(auth, KRB4_SERVICE_NAME, instance, 0, &adat, ""))) {
packet_send_debug("Kerberos V4 krb_rd_req: %.100s", krb_err_txt[r]);
return 0;
}
des_key_sched((des_cblock *) adat.session, schedule);
*client = xmalloc(MAX_K_NAME_SZ);
(void) snprintf(*client, MAX_K_NAME_SZ, "%s%s%s@%s", adat.pname,
*adat.pinst ? "." : "", adat.pinst, adat.prealm);
/* Check ~/.klogin authorization now. */
if (kuserok(&adat, (char *) server_user) != KSUCCESS) {
packet_send_debug("Kerberos V4 .klogin authorization failed!");
log("Kerberos V4 .klogin authorization failed for %s to account %s",
*client, server_user);
xfree(*client);
return 0;
}
/* Increment the checksum, and return it encrypted with the
session key. */
cksum = adat.checksum + 1;
cksum = htonl(cksum);
/* If we can't successfully encrypt the checksum, we send back an
empty message, admitting our failure. */
if ((r = krb_mk_priv((u_char *) & cksum, reply.dat, sizeof(cksum) + 1,
schedule, &adat.session, &local, &foreign)) < 0) {
packet_send_debug("Kerberos V4 mk_priv: (%d) %s", r, krb_err_txt[r]);
reply.dat[0] = 0;
reply.length = 0;
} else
reply.length = r;
/* Clear session key. */
memset(&adat.session, 0, sizeof(&adat.session));
packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE);
packet_put_string((char *) reply.dat, reply.length);
packet_send();
packet_write_wait();
return 1;
}
#endif /* KRB4 */
#ifdef AFS
int auth_kerberos_tgt(struct passwd *pw, const char *string)
int
auth_kerberos_tgt(struct passwd *pw, const char *string)
{
CREDENTIALS creds;
if (!radix_to_creds(string, &creds)) {
log("Protocol error decoding Kerberos V4 tgt");
packet_send_debug("Protocol error decoding Kerberos V4 tgt");
goto auth_kerberos_tgt_failure;
}
if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */
strlcpy(creds.service, "krbtgt", sizeof creds.service);
if (strcmp(creds.service, "krbtgt")) {
log("Kerberos V4 tgt (%s%s%s@%s) rejected for %s", creds.pname,
creds.pinst[0] ? "." : "", creds.pinst, creds.realm, pw->pw_name);
packet_send_debug("Kerberos V4 tgt (%s%s%s@%s) rejected for %s",
creds.pname, creds.pinst[0] ? "." : "", creds.pinst,
creds.realm, pw->pw_name);
goto auth_kerberos_tgt_failure;
}
if (!krb4_init(pw->pw_uid))
goto auth_kerberos_tgt_failure;
CREDENTIALS creds;
if (in_tkt(creds.pname, creds.pinst) != KSUCCESS)
goto auth_kerberos_tgt_failure;
if (save_credentials(creds.service, creds.instance, creds.realm,
creds.session, creds.lifetime, creds.kvno,
&creds.ticket_st, creds.issue_date) != KSUCCESS) {
packet_send_debug("Kerberos V4 tgt refused: couldn't save credentials");
goto auth_kerberos_tgt_failure;
}
/* Successful authentication, passed all checks. */
chown(tkt_string(), pw->pw_uid, pw->pw_gid);
packet_send_debug("Kerberos V4 tgt accepted (%s.%s@%s, %s%s%s@%s)",
creds.service, creds.instance, creds.realm, creds.pname,
creds.pinst[0] ? "." : "", creds.pinst, creds.realm);
memset(&creds, 0, sizeof(creds));
packet_start(SSH_SMSG_SUCCESS);
packet_send();
packet_write_wait();
return 1;
auth_kerberos_tgt_failure:
krb4_cleanup_proc(NULL);
memset(&creds, 0, sizeof(creds));
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
return 0;
if (!radix_to_creds(string, &creds)) {
log("Protocol error decoding Kerberos V4 tgt");
packet_send_debug("Protocol error decoding Kerberos V4 tgt");
goto auth_kerberos_tgt_failure;
}
if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */
strlcpy(creds.service, "krbtgt", sizeof creds.service);
if (strcmp(creds.service, "krbtgt")) {
log("Kerberos V4 tgt (%s%s%s@%s) rejected for %s", creds.pname,
creds.pinst[0] ? "." : "", creds.pinst, creds.realm,
pw->pw_name);
packet_send_debug("Kerberos V4 tgt (%s%s%s@%s) rejected for %s",
creds.pname, creds.pinst[0] ? "." : "", creds.pinst,
creds.realm, pw->pw_name);
goto auth_kerberos_tgt_failure;
}
if (!krb4_init(pw->pw_uid))
goto auth_kerberos_tgt_failure;
if (in_tkt(creds.pname, creds.pinst) != KSUCCESS)
goto auth_kerberos_tgt_failure;
if (save_credentials(creds.service, creds.instance, creds.realm,
creds.session, creds.lifetime, creds.kvno,
&creds.ticket_st, creds.issue_date) != KSUCCESS) {
packet_send_debug("Kerberos V4 tgt refused: couldn't save credentials");
goto auth_kerberos_tgt_failure;
}
/* Successful authentication, passed all checks. */
chown(tkt_string(), pw->pw_uid, pw->pw_gid);
packet_send_debug("Kerberos V4 tgt accepted (%s.%s@%s, %s%s%s@%s)",
creds.service, creds.instance, creds.realm, creds.pname,
creds.pinst[0] ? "." : "", creds.pinst, creds.realm);
memset(&creds, 0, sizeof(creds));
packet_start(SSH_SMSG_SUCCESS);
packet_send();
packet_write_wait();
return 1;
auth_kerberos_tgt_failure:
krb4_cleanup_proc(NULL);
memset(&creds, 0, sizeof(creds));
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
return 0;
}
int auth_afs_token(struct passwd *pw, const char *token_string)
int
auth_afs_token(struct passwd *pw, const char *token_string)
{
CREDENTIALS creds;
uid_t uid = pw->pw_uid;
CREDENTIALS creds;
uid_t uid = pw->pw_uid;
if (!radix_to_creds(token_string, &creds)) {
log("Protocol error decoding AFS token");
packet_send_debug("Protocol error decoding AFS token");
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
return 0;
}
if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */
strlcpy(creds.service, "afs", sizeof creds.service);
if (strncmp(creds.pname, "AFS ID ", 7) == 0)
uid = atoi(creds.pname + 7);
if (kafs_settoken(creds.realm, uid, &creds)) {
log("AFS token (%s@%s) rejected for %s", creds.pname, creds.realm,
pw->pw_name);
packet_send_debug("AFS token (%s@%s) rejected for %s", creds.pname,
creds.realm, pw->pw_name);
memset(&creds, 0, sizeof(creds));
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
return 0;
}
packet_send_debug("AFS token accepted (%s@%s, %s@%s)", creds.service,
creds.realm, creds.pname, creds.realm);
memset(&creds, 0, sizeof(creds));
packet_start(SSH_SMSG_SUCCESS);
packet_send();
packet_write_wait();
return 1;
if (!radix_to_creds(token_string, &creds)) {
log("Protocol error decoding AFS token");
packet_send_debug("Protocol error decoding AFS token");
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
return 0;
}
if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */
strlcpy(creds.service, "afs", sizeof creds.service);
if (strncmp(creds.pname, "AFS ID ", 7) == 0)
uid = atoi(creds.pname + 7);
if (kafs_settoken(creds.realm, uid, &creds)) {
log("AFS token (%s@%s) rejected for %s", creds.pname, creds.realm,
pw->pw_name);
packet_send_debug("AFS token (%s@%s) rejected for %s", creds.pname,
creds.realm, pw->pw_name);
memset(&creds, 0, sizeof(creds));
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
return 0;
}
packet_send_debug("AFS token accepted (%s@%s, %s@%s)", creds.service,
creds.realm, creds.pname, creds.realm);
memset(&creds, 0, sizeof(creds));
packet_start(SSH_SMSG_SUCCESS);
packet_send();
packet_write_wait();
return 1;
}
#endif /* AFS */

Просмотреть файл

@ -1,30 +1,22 @@
/*
auth-passwd.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Sat Mar 18 05:11:38 1995 ylo
Password authentication. This file contains the functions to check whether
the password is valid for the user.
*/
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Created: Sat Mar 18 05:11:38 1995 ylo
* Password authentication. This file contains the functions to check whether
* the password is valid for the user.
*/
#include "includes.h"
#ifndef HAVE_PAM
RCSID("$Id: auth-passwd.c,v 1.5 1999/11/19 04:53:20 damien Exp $");
RCSID("$Id: auth-passwd.c,v 1.6 1999/11/24 13:26:21 damien Exp $");
#include "packet.h"
#include "ssh.h"
#include "servconf.h"
#include "xmalloc.h"
#include "config.h"
#ifdef HAVE_SHADOW_H
#include <shadow.h>
@ -34,185 +26,189 @@ RCSID("$Id: auth-passwd.c,v 1.5 1999/11/19 04:53:20 damien Exp $");
#include "md5crypt.h"
#endif
/* Don't need anything from here if we are using PAM */
/* Tries to authenticate the user using password. Returns true if
authentication succeeds. */
int auth_password(struct passwd *pw, const char *password)
/*
* Tries to authenticate the user using password. Returns true if
* authentication succeeds.
*/
int
auth_password(struct passwd * pw, const char *password)
{
extern ServerOptions options;
char *encrypted_password;
extern ServerOptions options;
char *encrypted_password;
#ifdef HAVE_SHADOW_H
struct spwd *spw;
struct spwd *spw;
#endif
if (pw->pw_uid == 0 && options.permit_root_login == 2)
{
/*packet_send_debug("Server does not permit root login with password.");*/
return 0;
}
if (*password == '\0' && options.permit_empty_passwd == 0)
{
/*packet_send_debug("Server does not permit empty password login.");*/
return 0;
}
/* deny if no user. */
if (pw == NULL)
return 0;
if (pw->pw_uid == 0 && options.permit_root_login == 2) {
/* Server does not permit root login with password */
return 0;
}
if (*password == '\0' && options.permit_empty_passwd == 0) {
/* Server does not permit empty password login */
return 0;
}
/* deny if no user. */
if (pw == NULL)
return 0;
#ifdef SKEY
if (options.skey_authentication == 1) {
if (strncasecmp(password, "s/key", 5) == 0) {
char *skeyinfo = skey_keyinfo(pw->pw_name);
if(skeyinfo == NULL){
debug("generating fake skeyinfo for %.100s.", pw->pw_name);
skeyinfo = skey_fake_keyinfo(pw->pw_name);
}
if(skeyinfo != NULL)
packet_send_debug(skeyinfo);
/* Try again. */
return 0;
}
else if (skey_haskey(pw->pw_name) == 0 &&
skey_passcheck(pw->pw_name, (char *)password) != -1) {
/* Authentication succeeded. */
return 1;
}
/* Fall back to ordinary passwd authentication. */
}
if (options.skey_authentication == 1) {
if (strncasecmp(password, "s/key", 5) == 0) {
char *skeyinfo = skey_keyinfo(pw->pw_name);
if (skeyinfo == NULL) {
debug("generating fake skeyinfo for %.100s.",
pw->pw_name);
skeyinfo = skey_fake_keyinfo(pw->pw_name);
}
if (skeyinfo != NULL)
packet_send_debug(skeyinfo);
/* Try again. */
return 0;
} else if (skey_haskey(pw->pw_name) == 0 &&
skey_passcheck(pw->pw_name, (char *) password) != -1) {
/* Authentication succeeded. */
return 1;
}
/* Fall back to ordinary passwd authentication. */
}
#endif
#if defined(KRB4)
/* Support for Kerberos v4 authentication - Dug Song <dugsong@UMICH.EDU> */
if (options.kerberos_authentication)
{
AUTH_DAT adata;
KTEXT_ST tkt;
struct hostent *hp;
unsigned long faddr;
char localhost[MAXHOSTNAMELEN];
char phost[INST_SZ];
char realm[REALM_SZ];
int r;
/* Try Kerberos password authentication only for non-root
users and only if Kerberos is installed. */
if (pw->pw_uid != 0 && krb_get_lrealm(realm, 1) == KSUCCESS) {
/* Support for Kerberos v4 authentication - Dug Song
<dugsong@UMICH.EDU> */
if (options.kerberos_authentication) {
AUTH_DAT adata;
KTEXT_ST tkt;
struct hostent *hp;
unsigned long faddr;
char localhost[MAXHOSTNAMELEN];
char phost[INST_SZ];
char realm[REALM_SZ];
int r;
/* Set up our ticket file. */
if (!krb4_init(pw->pw_uid)) {
log("Couldn't initialize Kerberos ticket file for %s!", pw->pw_name);
goto kerberos_auth_failure;
}
/* Try to get TGT using our password. */
r = krb_get_pw_in_tkt((char *)pw->pw_name, "", realm, "krbtgt", realm,
DEFAULT_TKT_LIFE, (char *)password);
if (r != INTK_OK) {
packet_send_debug("Kerberos V4 password authentication for %s "
"failed: %s", pw->pw_name, krb_err_txt[r]);
goto kerberos_auth_failure;
}
/* Successful authentication. */
chown(tkt_string(), pw->pw_uid, pw->pw_gid);
/* Now that we have a TGT, try to get a local "rcmd" ticket to
ensure that we are not talking to a bogus Kerberos server. */
(void) gethostname(localhost, sizeof(localhost));
(void) strlcpy(phost, (char *)krb_get_phost(localhost), INST_SZ);
r = krb_mk_req(&tkt, KRB4_SERVICE_NAME, phost, realm, 33);
/* Try Kerberos password authentication only for non-root
users and only if Kerberos is installed. */
if (pw->pw_uid != 0 && krb_get_lrealm(realm, 1) == KSUCCESS) {
if (r == KSUCCESS) {
if (!(hp = gethostbyname(localhost))) {
log("Couldn't get local host address!");
goto kerberos_auth_failure;
}
memmove((void *)&faddr, (void *)hp->h_addr, sizeof(faddr));
/* Set up our ticket file. */
if (!krb4_init(pw->pw_uid)) {
log("Couldn't initialize Kerberos ticket file for %s!",
pw->pw_name);
goto kerberos_auth_failure;
}
/* Try to get TGT using our password. */
r = krb_get_pw_in_tkt((char *) pw->pw_name, "",
realm, "krbtgt", realm,
DEFAULT_TKT_LIFE, (char *) password);
if (r != INTK_OK) {
packet_send_debug("Kerberos V4 password "
"authentication for %s failed: %s",
pw->pw_name, krb_err_txt[r]);
goto kerberos_auth_failure;
}
/* Successful authentication. */
chown(tkt_string(), pw->pw_uid, pw->pw_gid);
/* Verify our "rcmd" ticket. */
r = krb_rd_req(&tkt, KRB4_SERVICE_NAME, phost, faddr, &adata, "");
if (r == RD_AP_UNDEC) {
/* Probably didn't have a srvtab on localhost. Allow login. */
log("Kerberos V4 TGT for %s unverifiable, no srvtab installed? "
"krb_rd_req: %s", pw->pw_name, krb_err_txt[r]);
}
else if (r != KSUCCESS) {
log("Kerberos V4 %s ticket unverifiable: %s",
KRB4_SERVICE_NAME, krb_err_txt[r]);
goto kerberos_auth_failure;
}
/*
* Now that we have a TGT, try to get a local
* "rcmd" ticket to ensure that we are not talking
* to a bogus Kerberos server.
*/
(void) gethostname(localhost, sizeof(localhost));
(void) strlcpy(phost, (char *) krb_get_phost(localhost),
INST_SZ);
r = krb_mk_req(&tkt, KRB4_SERVICE_NAME, phost, realm, 33);
if (r == KSUCCESS) {
if (!(hp = gethostbyname(localhost))) {
log("Couldn't get local host address!");
goto kerberos_auth_failure;
}
memmove((void *) &faddr, (void *) hp->h_addr,
sizeof(faddr));
/* Verify our "rcmd" ticket. */
r = krb_rd_req(&tkt, KRB4_SERVICE_NAME, phost,
faddr, &adata, "");
if (r == RD_AP_UNDEC) {
/*
* Probably didn't have a srvtab on
* localhost. Allow login.
*/
log("Kerberos V4 TGT for %s unverifiable, "
"no srvtab installed? krb_rd_req: %s",
pw->pw_name, krb_err_txt[r]);
} else if (r != KSUCCESS) {
log("Kerberos V4 %s ticket unverifiable: %s",
KRB4_SERVICE_NAME, krb_err_txt[r]);
goto kerberos_auth_failure;
}
} else if (r == KDC_PR_UNKNOWN) {
/* Allow login if no rcmd service exists,
but log the error. */
log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s "
"not registered, or srvtab is wrong?", pw->pw_name,
krb_err_txt[r], KRB4_SERVICE_NAME, phost);
} else {
/* TGT is bad, forget it. Possibly
spoofed! */
packet_send_debug("WARNING: Kerberos V4 TGT "
"possibly spoofed for %s: %s",
pw->pw_name, krb_err_txt[r]);
goto kerberos_auth_failure;
}
/* Authentication succeeded. */
return 1;
kerberos_auth_failure:
krb4_cleanup_proc(NULL);
if (!options.kerberos_or_local_passwd)
return 0;
} else {
/* Logging in as root or no local Kerberos realm. */
packet_send_debug("Unable to authenticate to Kerberos.");
}
/* Fall back to ordinary passwd authentication. */
}
else if (r == KDC_PR_UNKNOWN) {
/* Allow login if no rcmd service exists, but log the error. */
log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s "
"not registered, or srvtab is wrong?", pw->pw_name,
krb_err_txt[r], KRB4_SERVICE_NAME, phost);
#endif /* KRB4 */
/* Check for users with no password. */
if (strcmp(password, "") == 0 && strcmp(pw->pw_passwd, "") == 0) {
packet_send_debug("Login permitted without a password "
"because the account has no password.");
return 1;
}
else {
/* TGT is bad, forget it. Possibly spoofed! */
packet_send_debug("WARNING: Kerberos V4 TGT possibly spoofed for"
"%s: %s", pw->pw_name, krb_err_txt[r]);
goto kerberos_auth_failure;
}
/* Authentication succeeded. */
return 1;
kerberos_auth_failure:
krb4_cleanup_proc(NULL);
if (!options.kerberos_or_local_passwd)
return 0;
}
else {
/* Logging in as root or no local Kerberos realm. */
packet_send_debug("Unable to authenticate to Kerberos.");
}
/* Fall back to ordinary passwd authentication. */
}
#endif /* KRB4 */
/* Check for users with no password. */
if (strcmp(password, "") == 0 && strcmp(pw->pw_passwd, "") == 0)
{
packet_send_debug("Login permitted without a password because the account has no password.");
return 1; /* The user has no password and an empty password was tried. */
}
#ifdef HAVE_SHADOW_H
spw = getspnam(pw->pw_name);
if (spw == NULL)
return(0);
spw = getspnam(pw->pw_name);
if (spw == NULL)
return(0);
if ((spw->sp_namp == NULL) || (strcmp(pw->pw_name, spw->sp_namp) != 0))
fatal("Shadow lookup returned garbage.");
if ((spw->sp_namp == NULL) || (strcmp(pw->pw_name, spw->sp_namp) != 0))
fatal("Shadow lookup returned garbage.");
if (strlen(spw->sp_pwdp) < 3)
return(0);
if (strlen(spw->sp_pwdp) < 3)
return(0);
/* Encrypt the candidate password using the proper salt. */
/* Encrypt the candidate password using the proper salt. */
#ifdef HAVE_MD5_PASSWORDS
if (is_md5_salt(spw->sp_pwdp))
encrypted_password = md5_crypt(password, spw->sp_pwdp);
else
encrypted_password = crypt(password, spw->sp_pwdp);
if (is_md5_salt(spw->sp_pwdp))
encrypted_password = md5_crypt(password, spw->sp_pwdp);
else
encrypted_password = crypt(password, spw->sp_pwdp);
#else /* HAVE_MD5_PASSWORDS */
encrypted_password = crypt(password, spw->sp_pwdp);
encrypted_password = crypt(password, spw->sp_pwdp);
#endif /* HAVE_MD5_PASSWORDS */
/* Authentication is accepted if the encrypted passwords are identical. */
return (strcmp(encrypted_password, spw->sp_pwdp) == 0);
/* Authentication is accepted if the encrypted passwords are identical. */
return (strcmp(encrypted_password, spw->sp_pwdp) == 0);
#else /* !HAVE_SHADOW_H */
encrypted_password = crypt(password,
(pw->pw_passwd[0] && pw->pw_passwd[1]) ? pw->pw_passwd : "xx");
/* Encrypt the candidate password using the proper salt. */
encrypted_password = crypt(password,
(pw->pw_passwd[0] && pw->pw_passwd[1]) ?
pw->pw_passwd : "xx");
/* Authentication is accepted if the encrypted passwords are identical. */
return (strcmp(encrypted_password, pw->pw_passwd) == 0);
/* Authentication is accepted if the encrypted passwords are identical. */
return (strcmp(encrypted_password, pw->pw_passwd) == 0);
#endif /* !HAVE_SHADOW_H */
}
#endif /* !HAVE_PAM */

Просмотреть файл

@ -1,21 +1,21 @@
/*
auth-rh-rsa.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Sun May 7 03:08:06 1995 ylo
Rhosts or /etc/hosts.equiv authentication combined with RSA host
authentication.
*/
*
* auth-rh-rsa.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Sun May 7 03:08:06 1995 ylo
*
* Rhosts or /etc/hosts.equiv authentication combined with RSA host
* authentication.
*
*/
#include "includes.h"
RCSID("$Id: auth-rh-rsa.c,v 1.5 1999/11/16 02:37:16 damien Exp $");
RCSID("$Id: auth-rh-rsa.c,v 1.6 1999/11/24 13:26:21 damien Exp $");
#include "packet.h"
#include "ssh.h"
@ -26,78 +26,76 @@ RCSID("$Id: auth-rh-rsa.c,v 1.5 1999/11/16 02:37:16 damien Exp $");
/* Tries to authenticate the user using the .rhosts file and the host using
its host key. Returns true if authentication succeeds. */
int auth_rhosts_rsa(struct passwd *pw, const char *client_user,
BIGNUM *client_host_key_e, BIGNUM *client_host_key_n)
int
auth_rhosts_rsa(struct passwd *pw, const char *client_user,
BIGNUM *client_host_key_e, BIGNUM *client_host_key_n)
{
extern ServerOptions options;
const char *canonical_hostname;
HostStatus host_status;
BIGNUM *ke, *kn;
extern ServerOptions options;
const char *canonical_hostname;
HostStatus host_status;
BIGNUM *ke, *kn;
debug("Trying rhosts with RSA host authentication for %.100s", client_user);
debug("Trying rhosts with RSA host authentication for %.100s", client_user);
/* Check if we would accept it using rhosts authentication. */
if (!auth_rhosts(pw, client_user))
return 0;
/* Check if we would accept it using rhosts authentication. */
if (!auth_rhosts(pw, client_user))
return 0;
canonical_hostname = get_canonical_hostname();
canonical_hostname = get_canonical_hostname();
debug("Rhosts RSA authentication: canonical host %.900s",
canonical_hostname);
/* Check if we know the host and its host key. */
/* Check system-wide host file. */
ke = BN_new();
kn = BN_new();
host_status = check_host_in_hostfile(SSH_SYSTEM_HOSTFILE, canonical_hostname,
client_host_key_e, client_host_key_n, ke, kn);
debug("Rhosts RSA authentication: canonical host %.900s",
canonical_hostname);
/* Check user host file unless ignored. */
if (host_status != HOST_OK && !options.ignore_user_known_hosts) {
struct stat st;
char *user_hostfile = tilde_expand_filename(SSH_USER_HOSTFILE, pw->pw_uid);
/* Check file permissions of SSH_USER_HOSTFILE,
auth_rsa() did already check pw->pw_dir, but there is a race XXX */
if (options.strict_modes &&
(stat(user_hostfile, &st) == 0) &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0)) {
log("Rhosts RSA authentication refused for %.100s: bad owner or modes for %.200s",
pw->pw_name, user_hostfile);
} else {
/* XXX race between stat and the following open() */
temporarily_use_uid(pw->pw_uid);
host_status = check_host_in_hostfile(user_hostfile, canonical_hostname,
client_host_key_e, client_host_key_n, ke, kn);
restore_uid();
}
xfree(user_hostfile);
}
BN_free(ke);
BN_free(kn);
/* Check if we know the host and its host key. */
ke = BN_new();
kn = BN_new();
host_status = check_host_in_hostfile(SSH_SYSTEM_HOSTFILE, canonical_hostname,
client_host_key_e, client_host_key_n,
ke, kn);
if (host_status != HOST_OK) {
/* The host key was not found. */
debug("Rhosts with RSA host authentication denied: unknown or invalid host key");
packet_send_debug("Your host key cannot be verified: unknown or invalid host key.");
return 0;
}
/* Check user host file unless ignored. */
if (host_status != HOST_OK && !options.ignore_user_known_hosts) {
struct stat st;
char *user_hostfile = tilde_expand_filename(SSH_USER_HOSTFILE, pw->pw_uid);
/* Check file permissions of SSH_USER_HOSTFILE, auth_rsa()
did already check pw->pw_dir, but there is a race XXX */
if (options.strict_modes &&
(stat(user_hostfile, &st) == 0) &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0)) {
log("Rhosts RSA authentication refused for %.100s: bad owner or modes for %.200s",
pw->pw_name, user_hostfile);
} else {
/* XXX race between stat and the following open() */
temporarily_use_uid(pw->pw_uid);
host_status = check_host_in_hostfile(user_hostfile, canonical_hostname,
client_host_key_e, client_host_key_n,
ke, kn);
restore_uid();
}
xfree(user_hostfile);
}
BN_free(ke);
BN_free(kn);
/* A matching host key was found and is known. */
/* Perform the challenge-response dialog with the client for the host key. */
if (!auth_rsa_challenge_dialog(client_host_key_e, client_host_key_n))
{
log("Client on %.800s failed to respond correctly to host authentication.",
canonical_hostname);
return 0;
}
if (host_status != HOST_OK) {
debug("Rhosts with RSA host authentication denied: unknown or invalid host key");
packet_send_debug("Your host key cannot be verified: unknown or invalid host key.");
return 0;
}
/* A matching host key was found and is known. */
/* We have authenticated the user using .rhosts or /etc/hosts.equiv, and
the host using RSA. We accept the authentication. */
log("Rhosts with RSA host authentication accepted for %.100s, %.100s on %.700s.",
pw->pw_name, client_user, canonical_hostname);
packet_send_debug("Rhosts with RSA host authentication accepted.");
return 1;
/* Perform the challenge-response dialog with the client for the host key. */
if (!auth_rsa_challenge_dialog(client_host_key_e, client_host_key_n)) {
log("Client on %.800s failed to respond correctly to host authentication.",
canonical_hostname);
return 0;
}
/* We have authenticated the user using .rhosts or /etc/hosts.equiv, and the host using RSA.
We accept the authentication. */
verbose("Rhosts with RSA host authentication accepted for %.100s, %.100s on %.700s.",
pw->pw_name, client_user, canonical_hostname);
packet_send_debug("Rhosts with RSA host authentication accepted.");
return 1;
}

Просмотреть файл

@ -1,22 +1,22 @@
/*
auth-rhosts.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Fri Mar 17 05:12:18 1995 ylo
Rhosts authentication. This file contains code to check whether to admit
the login based on rhosts authentication. This file also processes
/etc/hosts.equiv.
*/
*
* auth-rhosts.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Fri Mar 17 05:12:18 1995 ylo
*
* Rhosts authentication. This file contains code to check whether to admit
* the login based on rhosts authentication. This file also processes
* /etc/hosts.equiv.
*
*/
#include "includes.h"
RCSID("$Id: auth-rhosts.c,v 1.4 1999/11/18 21:25:48 damien Exp $");
RCSID("$Id: auth-rhosts.c,v 1.5 1999/11/24 13:26:21 damien Exp $");
#include "packet.h"
#include "ssh.h"
@ -28,256 +28,228 @@ RCSID("$Id: auth-rhosts.c,v 1.4 1999/11/18 21:25:48 damien Exp $");
/etc/hosts.equiv). This returns true if authentication can be granted
based on the file, and returns zero otherwise. */
int check_rhosts_file(const char *filename, const char *hostname,
const char *ipaddr, const char *client_user,
const char *server_user)
int
check_rhosts_file(const char *filename, const char *hostname,
const char *ipaddr, const char *client_user,
const char *server_user)
{
FILE *f;
char buf[1024]; /* Must not be larger than host, user, dummy below. */
/* Open the .rhosts file. */
f = fopen(filename, "r");
if (!f)
return 0; /* Cannot read the .rhosts - deny access. */
FILE *f;
char buf[1024]; /* Must not be larger than host, user, dummy below. */
/* Go through the file, checking every entry. */
while (fgets(buf, sizeof(buf), f))
{
/* All three must be at least as big as buf to avoid overflows. */
char hostbuf[1024], userbuf[1024], dummy[1024], *host, *user, *cp;
int negated;
for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
;
if (*cp == '#' || *cp == '\n' || !*cp)
continue;
/* Open the .rhosts file, deny if unreadable */
f = fopen(filename, "r");
if (!f)
return 0;
/* NO_PLUS is supported at least on OSF/1. We skip it (we don't ever
support the plus syntax). */
if (strncmp(cp, "NO_PLUS", 7) == 0)
continue;
/* Go through the file, checking every entry. */
while (fgets(buf, sizeof(buf), f)) {
/* All three must be at least as big as buf to avoid overflows. */
char hostbuf[1024], userbuf[1024], dummy[1024], *host, *user, *cp;
int negated;
/* This should be safe because each buffer is as big as the whole
string, and thus cannot be overwritten. */
switch (sscanf(buf, "%s %s %s", hostbuf, userbuf, dummy))
{
case 0:
packet_send_debug("Found empty line in %.100s.", filename);
continue; /* Empty line? */
case 1:
/* Host name only. */
strlcpy(userbuf, server_user, sizeof(userbuf));
break;
case 2:
/* Got both host and user name. */
break;
case 3:
packet_send_debug("Found garbage in %.100s.", filename);
continue; /* Extra garbage */
default:
continue; /* Weird... */
for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
;
if (*cp == '#' || *cp == '\n' || !*cp)
continue;
/* NO_PLUS is supported at least on OSF/1. We skip it (we
don't ever support the plus syntax). */
if (strncmp(cp, "NO_PLUS", 7) == 0)
continue;
/* This should be safe because each buffer is as big as
the whole string, and thus cannot be overwritten. */
switch (sscanf(buf, "%s %s %s", hostbuf, userbuf, dummy)) {
case 0:
packet_send_debug("Found empty line in %.100s.", filename);
continue;
case 1:
/* Host name only. */
strlcpy(userbuf, server_user, sizeof(userbuf));
break;
case 2:
/* Got both host and user name. */
break;
case 3:
packet_send_debug("Found garbage in %.100s.", filename);
continue;
default:
/* Weird... */
continue;
}
host = hostbuf;
user = userbuf;
negated = 0;
/* Process negated host names, or positive netgroups. */
if (host[0] == '-') {
negated = 1;
host++;
} else if (host[0] == '+')
host++;
if (user[0] == '-') {
negated = 1;
user++;
} else if (user[0] == '+')
user++;
/* Check for empty host/user names (particularly '+'). */
if (!host[0] || !user[0]) {
/* We come here if either was '+' or '-'. */
packet_send_debug("Ignoring wild host/user names in %.100s.",
filename);
continue;
}
/* Verify that host name matches. */
if (host[0] == '@') {
if (!innetgr(host + 1, hostname, NULL, NULL) &&
!innetgr(host + 1, ipaddr, NULL, NULL))
continue;
} else if (strcasecmp(host, hostname) && strcmp(host, ipaddr) != 0)
continue; /* Different hostname. */
/* Verify that user name matches. */
if (user[0] == '@') {
if (!innetgr(user + 1, NULL, client_user, NULL))
continue;
} else if (strcmp(user, client_user) != 0)
continue; /* Different username. */
/* Found the user and host. */
fclose(f);
/* If the entry was negated, deny access. */
if (negated) {
packet_send_debug("Matched negative entry in %.100s.",
filename);
return 0;
}
/* Accept authentication. */
return 1;
}
host = hostbuf;
user = userbuf;
negated = 0;
/* Process negated host names, or positive netgroups. */
if (host[0] == '-')
{
negated = 1;
host++;
}
else
if (host[0] == '+')
host++;
if (user[0] == '-')
{
negated = 1;
user++;
}
else
if (user[0] == '+')
user++;
/* Check for empty host/user names (particularly '+'). */
if (!host[0] || !user[0])
{
/* We come here if either was '+' or '-'. */
packet_send_debug("Ignoring wild host/user names in %.100s.",
filename);
continue;
}
/* Verify that host name matches. */
if (host[0] == '@')
{
if (!innetgr(host + 1, hostname, NULL, NULL) &&
!innetgr(host + 1, ipaddr, NULL, NULL))
continue;
}
else
if (strcasecmp(host, hostname) && strcmp(host, ipaddr) != 0)
continue; /* Different hostname. */
/* Verify that user name matches. */
if (user[0] == '@')
{
if (!innetgr(user + 1, NULL, client_user, NULL))
continue;
}
else
if (strcmp(user, client_user) != 0)
continue; /* Different username. */
/* Found the user and host. */
fclose(f);
/* If the entry was negated, deny access. */
if (negated)
{
packet_send_debug("Matched negative entry in %.100s.",
filename);
return 0;
}
/* Accept authentication. */
return 1;
}
/* Authentication using this file denied. */
fclose(f);
return 0;
/* Authentication using this file denied. */
fclose(f);
return 0;
}
/* Tries to authenticate the user using the .shosts or .rhosts file.
/* Tries to authenticate the user using the .shosts or .rhosts file.
Returns true if authentication succeeds. If ignore_rhosts is
true, only /etc/hosts.equiv will be considered (.rhosts and .shosts
are ignored). */
int auth_rhosts(struct passwd *pw, const char *client_user)
int
auth_rhosts(struct passwd *pw, const char *client_user)
{
extern ServerOptions options;
char buf[1024];
const char *hostname, *ipaddr;
struct stat st;
static const char *rhosts_files[] = { ".shosts", ".rhosts", NULL };
unsigned int rhosts_file_index;
extern ServerOptions options;
char buf[1024];
const char *hostname, *ipaddr;
struct stat st;
static const char *rhosts_files[] = {".shosts", ".rhosts", NULL};
unsigned int rhosts_file_index;
/* Quick check: if the user has no .shosts or .rhosts files, return failure
immediately without doing costly lookups from name servers. */
/* Switch to the user's uid. */
temporarily_use_uid(pw->pw_uid);
for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
rhosts_file_index++)
{
/* Check users .rhosts or .shosts. */
snprintf(buf, sizeof buf, "%.500s/%.100s",
pw->pw_dir, rhosts_files[rhosts_file_index]);
if (stat(buf, &st) >= 0)
break;
}
/* Switch back to privileged uid. */
restore_uid();
if (!rhosts_files[rhosts_file_index] && stat("/etc/hosts.equiv", &st) < 0 &&
stat(SSH_HOSTS_EQUIV, &st) < 0)
return 0; /* The user has no .shosts or .rhosts file and there are no
system-wide files. */
/* Get the name, address, and port of the remote host. */
hostname = get_canonical_hostname();
ipaddr = get_remote_ipaddr();
/* If not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */
if (pw->pw_uid != 0)
{
if (check_rhosts_file("/etc/hosts.equiv", hostname, ipaddr, client_user,
pw->pw_name))
{
packet_send_debug("Accepted for %.100s [%.100s] by /etc/hosts.equiv.",
hostname, ipaddr);
return 1;
/* Quick check: if the user has no .shosts or .rhosts files,
return failure immediately without doing costly lookups from
name servers. */
/* Switch to the user's uid. */
temporarily_use_uid(pw->pw_uid);
for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
rhosts_file_index++) {
/* Check users .rhosts or .shosts. */
snprintf(buf, sizeof buf, "%.500s/%.100s",
pw->pw_dir, rhosts_files[rhosts_file_index]);
if (stat(buf, &st) >= 0)
break;
}
if (check_rhosts_file(SSH_HOSTS_EQUIV, hostname, ipaddr, client_user,
pw->pw_name))
{
packet_send_debug("Accepted for %.100s [%.100s] by %.100s.",
hostname, ipaddr, SSH_HOSTS_EQUIV);
return 1;
/* Switch back to privileged uid. */
restore_uid();
/* Deny if The user has no .shosts or .rhosts file and there are no system-wide files. */
if (!rhosts_files[rhosts_file_index] &&
stat("/etc/hosts.equiv", &st) < 0 &&
stat(SSH_HOSTS_EQUIV, &st) < 0)
return 0;
/* Get the name, address, and port of the remote host. */
hostname = get_canonical_hostname();
ipaddr = get_remote_ipaddr();
/* If not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */
if (pw->pw_uid != 0) {
if (check_rhosts_file("/etc/hosts.equiv", hostname, ipaddr, client_user,
pw->pw_name)) {
packet_send_debug("Accepted for %.100s [%.100s] by /etc/hosts.equiv.",
hostname, ipaddr);
return 1;
}
if (check_rhosts_file(SSH_HOSTS_EQUIV, hostname, ipaddr, client_user,
pw->pw_name)) {
packet_send_debug("Accepted for %.100s [%.100s] by %.100s.",
hostname, ipaddr, SSH_HOSTS_EQUIV);
return 1;
}
}
}
/* Check that the home directory is owned by root or the user, and
is not group or world writable. */
if (stat(pw->pw_dir, &st) < 0) {
log("Rhosts authentication refused for %.100s: no home directory %.200s",
pw->pw_name, pw->pw_dir);
packet_send_debug("Rhosts authentication refused for %.100: no home directory %.200s",
pw->pw_name, pw->pw_dir);
return 0;
}
if (options.strict_modes &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0)) {
log("Rhosts authentication refused for %.100s: bad ownership or modes for home directory.",
pw->pw_name);
packet_send_debug("Rhosts authentication refused for %.100s: bad ownership or modes for home directory.",
pw->pw_name);
return 0;
}
/* Temporarily use the user's uid. */
temporarily_use_uid(pw->pw_uid);
/* Check that the home directory is owned by root or the user, and is not
group or world writable. */
if (stat(pw->pw_dir, &st) < 0)
{
log("Rhosts authentication refused for %.100s: no home directory %.200s",
pw->pw_name, pw->pw_dir);
packet_send_debug("Rhosts authentication refused for %.100: no home directory %.200s",
pw->pw_name, pw->pw_dir);
return 0;
}
if (options.strict_modes &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0))
{
log("Rhosts authentication refused for %.100s: bad ownership or modes for home directory.",
pw->pw_name);
packet_send_debug("Rhosts authentication refused for %.100s: bad ownership or modes for home directory.",
pw->pw_name);
return 0;
}
/* Check all .rhosts files (currently .shosts and .rhosts). */
/* Temporarily use the user's uid. */
temporarily_use_uid(pw->pw_uid);
for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
rhosts_file_index++)
{
/* Check users .rhosts or .shosts. */
snprintf(buf, sizeof buf, "%.500s/%.100s",
pw->pw_dir, rhosts_files[rhosts_file_index]);
if (stat(buf, &st) < 0)
continue; /* No such file. */
/* Check all .rhosts files (currently .shosts and .rhosts). */
for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
rhosts_file_index++) {
/* Check users .rhosts or .shosts. */
snprintf(buf, sizeof buf, "%.500s/%.100s",
pw->pw_dir, rhosts_files[rhosts_file_index]);
if (stat(buf, &st) < 0)
continue;
/* Make sure that the file is either owned by the user or by root,
and make sure it is not writable by anyone but the owner. This is
to help avoid novices accidentally allowing access to their account
by anyone. */
if (options.strict_modes &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0))
{
log("Rhosts authentication refused for %.100s: bad modes for %.200s",
pw->pw_name, buf);
packet_send_debug("Bad file modes for %.200s", buf);
continue;
/* Make sure that the file is either owned by the user or
by root, and make sure it is not writable by anyone but
the owner. This is to help avoid novices accidentally
allowing access to their account by anyone. */
if (options.strict_modes &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0)) {
log("Rhosts authentication refused for %.100s: bad modes for %.200s",
pw->pw_name, buf);
packet_send_debug("Bad file modes for %.200s", buf);
continue;
}
/* Check if we have been configured to ignore .rhosts and .shosts files. */
if (options.ignore_rhosts) {
packet_send_debug("Server has been configured to ignore %.100s.",
rhosts_files[rhosts_file_index]);
continue;
}
/* Check if authentication is permitted by the file. */
if (check_rhosts_file(buf, hostname, ipaddr, client_user, pw->pw_name)) {
packet_send_debug("Accepted by %.100s.",
rhosts_files[rhosts_file_index]);
/* Restore the privileged uid. */
restore_uid();
return 1;
}
}
/* Check if we have been configured to ignore .rhosts and .shosts
files. */
if (options.ignore_rhosts)
{
packet_send_debug("Server has been configured to ignore %.100s.",
rhosts_files[rhosts_file_index]);
continue;
}
/* Check if authentication is permitted by the file. */
if (check_rhosts_file(buf, hostname, ipaddr, client_user, pw->pw_name))
{
packet_send_debug("Accepted by %.100s.",
rhosts_files[rhosts_file_index]);
/* Restore the privileged uid. */
restore_uid();
return 1;
}
}
/* Rhosts authentication denied. */
/* Restore the privileged uid. */
restore_uid();
return 0;
/* Restore the privileged uid. */
restore_uid();
return 0;
}

Просмотреть файл

@ -1,22 +1,22 @@
/*
auth-rsa.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Mon Mar 27 01:46:52 1995 ylo
RSA-based authentication. This code determines whether to admit a login
based on RSA authentication. This file also contains functions to check
validity of the host key.
*/
*
* auth-rsa.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Mon Mar 27 01:46:52 1995 ylo
*
* RSA-based authentication. This code determines whether to admit a login
* based on RSA authentication. This file also contains functions to check
* validity of the host key.
*
*/
#include "includes.h"
RCSID("$Id: auth-rsa.c,v 1.8 1999/11/18 21:25:48 damien Exp $");
RCSID("$Id: auth-rsa.c,v 1.9 1999/11/24 13:26:21 damien Exp $");
#include "rsa.h"
#include "packet.h"
@ -50,7 +50,7 @@ extern unsigned char session_id[16];
/* The .ssh/authorized_keys file contains public keys, one per line, in the
following format:
options bits e n comment
where bits, e and n are decimal numbers,
where bits, e and n are decimal numbers,
and comment is any string of characters up to newline. The maximum
length of a line is 8000 characters. See the documentation for a
description of the options.
@ -63,71 +63,69 @@ extern unsigned char session_id[16];
int
auth_rsa_challenge_dialog(BIGNUM *e, BIGNUM *n)
{
BIGNUM *challenge, *encrypted_challenge, *aux;
RSA *pk;
BN_CTX *ctx = BN_CTX_new();
unsigned char buf[32], mdbuf[16], response[16];
MD5_CTX md;
unsigned int i;
int plen, len;
BIGNUM *challenge, *encrypted_challenge, *aux;
RSA *pk;
BN_CTX *ctx = BN_CTX_new();
unsigned char buf[32], mdbuf[16], response[16];
MD5_CTX md;
unsigned int i;
int plen, len;
encrypted_challenge = BN_new();
challenge = BN_new();
aux = BN_new();
encrypted_challenge = BN_new();
challenge = BN_new();
aux = BN_new();
/* Generate a random challenge. */
BN_rand(challenge, 256, 0, 0);
BN_mod(challenge, challenge, n, ctx);
/* Create the public key data structure. */
pk = RSA_new();
pk->e = BN_new();
BN_copy(pk->e, e);
pk->n = BN_new();
BN_copy(pk->n, n);
/* Generate a random challenge. */
BN_rand(challenge, 256, 0, 0);
BN_mod(challenge, challenge, n, ctx);
/* Encrypt the challenge with the public key. */
rsa_public_encrypt(encrypted_challenge, challenge, pk);
RSA_free(pk);
/* Create the public key data structure. */
pk = RSA_new();
pk->e = BN_new();
BN_copy(pk->e, e);
pk->n = BN_new();
BN_copy(pk->n, n);
/* Send the encrypted challenge to the client. */
packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
packet_put_bignum(encrypted_challenge);
packet_send();
packet_write_wait();
/* Encrypt the challenge with the public key. */
rsa_public_encrypt(encrypted_challenge, challenge, pk);
RSA_free(pk);
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
if (len <= 0 || len > 32)
fatal("auth_rsa_challenge_dialog: bad challenge length %d", len);
memset(buf, 0, 32);
BN_bn2bin(challenge, buf + 32 - len);
MD5_Init(&md);
MD5_Update(&md, buf, 32);
MD5_Update(&md, session_id, 16);
MD5_Final(mdbuf, &md);
/* Send the encrypted challenge to the client. */
packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
packet_put_bignum(encrypted_challenge);
packet_send();
packet_write_wait();
/* We will no longer need these. */
BN_clear_free(encrypted_challenge);
BN_clear_free(challenge);
BN_clear_free(aux);
BN_CTX_free(ctx);
/* Wait for a response. */
packet_read_expect(&plen, SSH_CMSG_AUTH_RSA_RESPONSE);
packet_integrity_check(plen, 16, SSH_CMSG_AUTH_RSA_RESPONSE);
for (i = 0; i < 16; i++)
response[i] = packet_get_char();
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
if (len <= 0 || len > 32)
fatal("auth_rsa_challenge_dialog: bad challenge length %d", len);
memset(buf, 0, 32);
BN_bn2bin(challenge, buf + 32 - len);
MD5_Init(&md);
MD5_Update(&md, buf, 32);
MD5_Update(&md, session_id, 16);
MD5_Final(mdbuf, &md);
/* Verify that the response is the original challenge. */
if (memcmp(response, mdbuf, 16) != 0)
{
/* Wrong answer. */
return 0;
}
/* We will no longer need these. */
BN_clear_free(encrypted_challenge);
BN_clear_free(challenge);
BN_clear_free(aux);
BN_CTX_free(ctx);
/* Correct answer. */
return 1;
/* Wait for a response. */
packet_read_expect(&plen, SSH_CMSG_AUTH_RSA_RESPONSE);
packet_integrity_check(plen, 16, SSH_CMSG_AUTH_RSA_RESPONSE);
for (i = 0; i < 16; i++)
response[i] = packet_get_char();
/* Verify that the response is the original challenge. */
if (memcmp(response, mdbuf, 16) != 0) {
/* Wrong answer. */
return 0;
}
/* Correct answer. */
return 1;
}
/* Performs the RSA authentication dialog with the client. This returns
@ -137,357 +135,324 @@ auth_rsa_challenge_dialog(BIGNUM *e, BIGNUM *n)
int
auth_rsa(struct passwd *pw, BIGNUM *client_n)
{
extern ServerOptions options;
char line[8192], file[1024];
int authenticated;
unsigned int bits;
FILE *f;
unsigned long linenum = 0;
struct stat st;
BIGNUM *e, *n;
extern ServerOptions options;
char line[8192], file[1024];
int authenticated;
unsigned int bits;
FILE *f;
unsigned long linenum = 0;
struct stat st;
BIGNUM *e, *n;
/* Temporarily use the user's uid. */
temporarily_use_uid(pw->pw_uid);
/* Temporarily use the user's uid. */
temporarily_use_uid(pw->pw_uid);
/* The authorized keys. */
snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
SSH_USER_PERMITTED_KEYS);
/* Fail quietly if file does not exist */
if (stat(file, &st) < 0)
{
/* Restore the privileged uid. */
restore_uid();
return 0;
}
/* The authorized keys. */
snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
SSH_USER_PERMITTED_KEYS);
/* Open the file containing the authorized keys. */
f = fopen(file, "r");
if (!f)
{
/* Restore the privileged uid. */
restore_uid();
packet_send_debug("Could not open %.900s for reading.", file);
packet_send_debug("If your home is on an NFS volume, it may need to be world-readable.");
return 0;
}
if (options.strict_modes) {
int fail=0;
char buf[1024];
/* Check open file in order to avoid open/stat races */
if (fstat(fileno(f), &st) < 0 ||
(st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0) {
snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
"bad ownership or modes for '%s'.", pw->pw_name, file);
fail=1;
}else{
/* Check path to SSH_USER_PERMITTED_KEYS */
int i;
static const char *check[] = {
"", SSH_USER_DIR, NULL
};
for (i=0; check[i]; i++) {
snprintf(line, sizeof line, "%.500s/%.100s", pw->pw_dir, check[i]);
if (stat(line, &st) < 0 ||
(st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0) {
snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
"bad ownership or modes for '%s'.", pw->pw_name, line);
fail=1;
break;
}
}
}
if (fail) {
log(buf);
packet_send_debug(buf);
restore_uid();
return 0;
}
}
/* Flag indicating whether authentication has succeeded. */
authenticated = 0;
/* Initialize mp-int variables. */
e = BN_new();
n = BN_new();
/* Go though the accepted keys, looking for the current key. If found,
perform a challenge-response dialog to verify that the user really has
the corresponding private key. */
while (fgets(line, sizeof(line), f))
{
char *cp;
char *options;
linenum++;
/* Skip leading whitespace. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
/* Skip empty and comment lines. */
if (!*cp || *cp == '\n' || *cp == '#')
continue;
/* Check if there are options for this key, and if so, save their
starting address and skip the option part for now. If there are no
options, set the starting address to NULL. */
if (*cp < '0' || *cp > '9')
{
int quoted = 0;
options = cp;
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++)
{
if (*cp == '\\' && cp[1] == '"')
cp++; /* Skip both */
else
if (*cp == '"')
quoted = !quoted;
}
/* Fail quietly if file does not exist */
if (stat(file, &st) < 0) {
/* Restore the privileged uid. */
restore_uid();
return 0;
}
else
options = NULL;
/* Parse the key from the line. */
if (!auth_rsa_read_key(&cp, &bits, e, n))
{
debug("%.100s, line %lu: bad key syntax",
SSH_USER_PERMITTED_KEYS, linenum);
packet_send_debug("%.100s, line %lu: bad key syntax",
SSH_USER_PERMITTED_KEYS, linenum);
continue;
/* Open the file containing the authorized keys. */
f = fopen(file, "r");
if (!f) {
/* Restore the privileged uid. */
restore_uid();
packet_send_debug("Could not open %.900s for reading.", file);
packet_send_debug("If your home is on an NFS volume, it may need to be world-readable.");
return 0;
}
/* cp now points to the comment part. */
/* check the real bits */
if (bits != BN_num_bits(n))
error("Warning: error in %s, line %ld: keysize mismatch: "
"actual size %d vs. announced %d.",
file, linenum, BN_num_bits(n), bits);
/* Check if the we have found the desired key (identified by its
modulus). */
if (BN_cmp(n, client_n) != 0)
continue; /* Wrong key. */
/* We have found the desired key. */
/* Perform the challenge-response dialog for this key. */
if (!auth_rsa_challenge_dialog(e, n))
{
/* Wrong response. */
log("Wrong response to RSA authentication challenge.");
packet_send_debug("Wrong response to RSA authentication challenge.");
continue;
}
/* Correct response. The client has been successfully authenticated.
Note that we have not yet processed the options; this will be reset
if the options cause the authentication to be rejected. */
authenticated = 1;
/* RSA part of authentication was accepted. Now process the options. */
if (options)
{
while (*options && *options != ' ' && *options != '\t')
{
cp = "no-port-forwarding";
if (strncmp(options, cp, strlen(cp)) == 0)
{
packet_send_debug("Port forwarding disabled.");
no_port_forwarding_flag = 1;
options += strlen(cp);
goto next_option;
}
cp = "no-agent-forwarding";
if (strncmp(options, cp, strlen(cp)) == 0)
{
packet_send_debug("Agent forwarding disabled.");
no_agent_forwarding_flag = 1;
options += strlen(cp);
goto next_option;
}
cp = "no-X11-forwarding";
if (strncmp(options, cp, strlen(cp)) == 0)
{
packet_send_debug("X11 forwarding disabled.");
no_x11_forwarding_flag = 1;
options += strlen(cp);
goto next_option;
}
cp = "no-pty";
if (strncmp(options, cp, strlen(cp)) == 0)
{
packet_send_debug("Pty allocation disabled.");
no_pty_flag = 1;
options += strlen(cp);
goto next_option;
}
cp = "command=\"";
if (strncmp(options, cp, strlen(cp)) == 0)
{
int i;
options += strlen(cp);
forced_command = xmalloc(strlen(options) + 1);
i = 0;
while (*options)
{
if (*options == '"')
break;
if (*options == '\\' && options[1] == '"')
{
options += 2;
forced_command[i++] = '"';
continue;
if (options.strict_modes) {
int fail = 0;
char buf[1024];
/* Check open file in order to avoid open/stat races */
if (fstat(fileno(f), &st) < 0 ||
(st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0) {
snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
"bad ownership or modes for '%s'.", pw->pw_name, file);
fail = 1;
} else {
/* Check path to SSH_USER_PERMITTED_KEYS */
int i;
static const char *check[] = {
"", SSH_USER_DIR, NULL
};
for (i = 0; check[i]; i++) {
snprintf(line, sizeof line, "%.500s/%.100s", pw->pw_dir, check[i]);
if (stat(line, &st) < 0 ||
(st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0) {
snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
"bad ownership or modes for '%s'.", pw->pw_name, line);
fail = 1;
break;
}
}
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;
if (fail) {
log(buf);
packet_send_debug(buf);
restore_uid();
return 0;
}
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);
authenticated = 0;
break;
}
xfree(patterns);
/* Host name matches. */
goto next_option;
}
bad_option:
/* Unknown 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;
}
/* Flag indicating whether authentication has succeeded. */
authenticated = 0;
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;
}
/* Initialize mp-int variables. */
e = BN_new();
n = BN_new();
/* Go though the accepted keys, looking for the current key. If
found, perform a challenge-response dialog to verify that the
user really has the corresponding private key. */
while (fgets(line, sizeof(line), f)) {
char *cp;
char *options;
linenum++;
/* Skip leading whitespace. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++);
/* Skip empty and comment lines. */
if (!*cp || *cp == '\n' || *cp == '#')
continue;
/* Check if there are options for this key, and if so,
save their starting address and skip the option part
for now. If there are no options, set the starting
address to NULL. */
if (*cp < '0' || *cp > '9') {
int quoted = 0;
options = cp;
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
if (*cp == '\\' && cp[1] == '"')
cp++; /* Skip both */
else if (*cp == '"')
quoted = !quoted;
}
} else
options = NULL;
/* Parse the key from the line. */
if (!auth_rsa_read_key(&cp, &bits, e, n)) {
debug("%.100s, line %lu: bad key syntax",
SSH_USER_PERMITTED_KEYS, linenum);
packet_send_debug("%.100s, line %lu: bad key syntax",
SSH_USER_PERMITTED_KEYS, linenum);
continue;
}
/* cp now points to the comment part. */
/* check the real bits */
if (bits != BN_num_bits(n))
error("Warning: error in %s, line %ld: keysize mismatch: "
"actual size %d vs. announced %d.",
file, linenum, BN_num_bits(n), bits);
/* Check if the we have found the desired key (identified by its modulus). */
if (BN_cmp(n, client_n) != 0)
continue; /* Wrong key. */
/* We have found the desired key. */
/* Perform the challenge-response dialog for this key. */
if (!auth_rsa_challenge_dialog(e, n)) {
/* Wrong response. */
verbose("Wrong response to RSA authentication challenge.");
packet_send_debug("Wrong response to RSA authentication challenge.");
continue;
}
/* Correct response. The client has been successfully
authenticated. Note that we have not yet processed the
options; this will be reset if the options cause the
authentication to be rejected. */
authenticated = 1;
/* RSA part of authentication was accepted. Now process the options. */
if (options) {
while (*options && *options != ' ' && *options != '\t') {
cp = "no-port-forwarding";
if (strncmp(options, cp, strlen(cp)) == 0) {
packet_send_debug("Port forwarding disabled.");
no_port_forwarding_flag = 1;
options += strlen(cp);
goto next_option;
}
cp = "no-agent-forwarding";
if (strncmp(options, cp, strlen(cp)) == 0) {
packet_send_debug("Agent forwarding disabled.");
no_agent_forwarding_flag = 1;
options += strlen(cp);
goto next_option;
}
cp = "no-X11-forwarding";
if (strncmp(options, cp, strlen(cp)) == 0) {
packet_send_debug("X11 forwarding disabled.");
no_x11_forwarding_flag = 1;
options += strlen(cp);
goto next_option;
}
cp = "no-pty";
if (strncmp(options, cp, strlen(cp)) == 0) {
packet_send_debug("Pty allocation disabled.");
no_pty_flag = 1;
options += strlen(cp);
goto next_option;
}
cp = "command=\"";
if (strncmp(options, cp, strlen(cp)) == 0) {
int i;
options += strlen(cp);
forced_command = xmalloc(strlen(options) + 1);
i = 0;
while (*options) {
if (*options == '"')
break;
if (*options == '\\' && options[1] == '"') {
options += 2;
forced_command[i++] = '"';
continue;
}
forced_command[i++] = *options++;
}
if (!*options) {
debug("%.100s, line %lu: missing end quote",
SSH_USER_PERMITTED_KEYS, linenum);
packet_send_debug("%.100s, line %lu: missing end quote",
SSH_USER_PERMITTED_KEYS, linenum);
continue;
}
forced_command[i] = 0;
packet_send_debug("Forced command: %.900s", forced_command);
options++;
goto next_option;
}
cp = "environment=\"";
if (strncmp(options, cp, strlen(cp)) == 0) {
int i;
char *s;
struct envstring *new_envstring;
options += strlen(cp);
s = xmalloc(strlen(options) + 1);
i = 0;
while (*options) {
if (*options == '"')
break;
if (*options == '\\' && options[1] == '"') {
options += 2;
s[i++] = '"';
continue;
}
s[i++] = *options++;
}
if (!*options) {
debug("%.100s, line %lu: missing end quote",
SSH_USER_PERMITTED_KEYS, linenum);
packet_send_debug("%.100s, line %lu: missing end quote",
SSH_USER_PERMITTED_KEYS, linenum);
continue;
}
s[i] = 0;
packet_send_debug("Adding to environment: %.900s", s);
debug("Adding to environment: %.900s", s);
options++;
new_envstring = xmalloc(sizeof(struct envstring));
new_envstring->s = s;
new_envstring->next = custom_environment;
custom_environment = new_envstring;
goto next_option;
}
cp = "from=\"";
if (strncmp(options, cp, strlen(cp)) == 0) {
char *patterns = xmalloc(strlen(options) + 1);
int i;
options += strlen(cp);
i = 0;
while (*options) {
if (*options == '"')
break;
if (*options == '\\' && options[1] == '"') {
options += 2;
patterns[i++] = '"';
continue;
}
patterns[i++] = *options++;
}
if (!*options) {
debug("%.100s, line %lu: missing end quote",
SSH_USER_PERMITTED_KEYS, linenum);
packet_send_debug("%.100s, line %lu: missing end quote",
SSH_USER_PERMITTED_KEYS, linenum);
continue;
}
patterns[i] = 0;
options++;
if (!match_hostname(get_canonical_hostname(), patterns,
strlen(patterns)) &&
!match_hostname(get_remote_ipaddr(), patterns,
strlen(patterns))) {
log("RSA authentication tried for %.100s with correct key but not from a permitted host (host=%.200s, ip=%.200s).",
pw->pw_name, get_canonical_hostname(),
get_remote_ipaddr());
packet_send_debug("Your host '%.200s' is not permitted to use this key for login.",
get_canonical_hostname());
xfree(patterns);
authenticated = 0;
break;
}
xfree(patterns);
/* Host name matches. */
goto next_option;
}
bad_option:
/* Unknown option. */
log("Bad options in %.100s file, line %lu: %.50s",
SSH_USER_PERMITTED_KEYS, linenum, options);
packet_send_debug("Bad options in %.100s file, line %lu: %.50s",
SSH_USER_PERMITTED_KEYS, linenum, options);
authenticated = 0;
break;
next_option:
/* Skip the comma, and move to the next option
(or break out if there are no more). */
if (!*options)
fatal("Bugs in auth-rsa.c option processing.");
if (*options == ' ' || *options == '\t')
break; /* End of options. */
if (*options != ',')
goto bad_option;
options++;
/* Process the next option. */
continue;
}
}
/* Break out of the loop if authentication was successful;
otherwise continue searching. */
if (authenticated)
break;
}
/* Break out of the loop if authentication was successful; otherwise
continue searching. */
if (authenticated)
break;
}
/* Restore the privileged uid. */
restore_uid();
/* Restore the privileged uid. */
restore_uid();
/* Close the file. */
fclose(f);
/* Close the file. */
fclose(f);
/* Clear any mp-int variables. */
BN_clear_free(n);
BN_clear_free(e);
/* Clear any mp-int variables. */
BN_clear_free(n);
BN_clear_free(e);
if (authenticated)
packet_send_debug("RSA authentication accepted.");
if (authenticated)
packet_send_debug("RSA authentication accepted.");
/* Return authentication result. */
return authenticated;
/* Return authentication result. */
return authenticated;
}

Просмотреть файл

@ -1,7 +1,8 @@
#include "includes.h"
#ifdef SKEY
#include "includes.h"
RCSID("$Id: auth-skey.c,v 1.2 1999/10/16 20:57:52 deraadt Exp $");
RCSID("$Id: auth-skey.c,v 1.3 1999/11/23 22:25:52 markus Exp $");
#include "ssh.h"
#include <sha1.h>
@ -32,6 +33,7 @@ hash_collapse(s)
return i;
}
char *
skey_fake_keyinfo(char *username)
{
@ -150,4 +152,4 @@ skey_fake_keyinfo(char *username)
return skeyprompt;
}
#endif SKEY
#endif /* SKEY */

855
authfd.c
Просмотреть файл

@ -1,20 +1,20 @@
/*
authfd.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Wed Mar 29 01:30:28 1995 ylo
Functions for connecting the local authentication agent.
*/
*
* authfd.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Wed Mar 29 01:30:28 1995 ylo
*
* Functions for connecting the local authentication agent.
*
*/
#include "includes.h"
RCSID("$Id: authfd.c,v 1.6 1999/11/18 21:25:48 damien Exp $");
RCSID("$Id: authfd.c,v 1.7 1999/11/24 13:26:21 damien Exp $");
#include "ssh.h"
#include "rsa.h"
@ -36,45 +36,42 @@ RCSID("$Id: authfd.c,v 1.6 1999/11/18 21:25:48 damien Exp $");
int
ssh_get_authentication_socket()
{
const char *authsocket;
int sock;
struct sockaddr_un sunaddr;
const char *authsocket;
int sock;
struct sockaddr_un sunaddr;
authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
if (!authsocket)
return -1;
authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
if (!authsocket)
return -1;
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
return -1;
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
/* close on exec */
if (fcntl(sock, F_SETFD, 1) == -1)
{
close(sock);
return -1;
}
if (connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0)
{
close(sock);
return -1;
}
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
return -1;
return sock;
/* close on exec */
if (fcntl(sock, F_SETFD, 1) == -1) {
close(sock);
return -1;
}
if (connect(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {
close(sock);
return -1;
}
return sock;
}
/* 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
ssh_get_authentication_socket(). */
void ssh_close_authentication_socket(int sock)
void
ssh_close_authentication_socket(int sock)
{
if (getenv(SSH_AUTHSOCKET_ENV_NAME))
close(sock);
if (getenv(SSH_AUTHSOCKET_ENV_NAME))
close(sock);
}
/* Opens and connects a private socket for communication with the
@ -83,38 +80,39 @@ void ssh_close_authentication_socket(int sock)
Returns NULL if an error occurred and the connection could not be
opened. */
AuthenticationConnection *ssh_get_authentication_connection()
AuthenticationConnection *
ssh_get_authentication_connection()
{
AuthenticationConnection *auth;
int sock;
sock = ssh_get_authentication_socket();
AuthenticationConnection *auth;
int sock;
/* Fail if we couldn't obtain a connection. This happens if we exited
due to a timeout. */
if (sock < 0)
return NULL;
sock = ssh_get_authentication_socket();
/* Applocate the connection structure and initialize it. */
auth = xmalloc(sizeof(*auth));
auth->fd = sock;
buffer_init(&auth->packet);
buffer_init(&auth->identities);
auth->howmany = 0;
/* Fail if we couldn't obtain a connection. This happens if we
exited due to a timeout. */
if (sock < 0)
return NULL;
return auth;
/* Applocate the connection structure and initialize it. */
auth = xmalloc(sizeof(*auth));
auth->fd = sock;
buffer_init(&auth->packet);
buffer_init(&auth->identities);
auth->howmany = 0;
return auth;
}
/* Closes the connection to the authentication agent and frees any associated
memory. */
void ssh_close_authentication_connection(AuthenticationConnection *ac)
void
ssh_close_authentication_connection(AuthenticationConnection *ac)
{
buffer_free(&ac->packet);
buffer_free(&ac->identities);
close(ac->fd);
/* Free the connection data structure. */
xfree(ac);
buffer_free(&ac->packet);
buffer_free(&ac->identities);
close(ac->fd);
xfree(ac);
}
/* Returns the first authentication identity held by the agent.
@ -126,67 +124,62 @@ int
ssh_get_first_identity(AuthenticationConnection *auth,
BIGNUM *e, BIGNUM *n, char **comment)
{
unsigned char msg[8192];
int len, l;
unsigned char msg[8192];
int len, l;
/* Send a message to the agent requesting for a list of the identities
it can represent. */
msg[0] = 0;
msg[1] = 0;
msg[2] = 0;
msg[3] = 1;
msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
if (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;
/* Send a message to the agent requesting for a list of the
identities it can represent. */
msg[0] = 0;
msg[1] = 0;
msg[2] = 0;
msg[3] = 1;
msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
if (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;
}
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);
/* Extract the length, and check it for sanity. (We cannot trust
authentication agents). */
len = GET_32BIT(msg);
if (len < 1 || len > 256 * 1024)
fatal("Authentication reply message too long: %d\n", len);
/* Read the packet itself. */
buffer_clear(&auth->identities);
while (len > 0)
{
l = len;
if (l > sizeof(msg))
l = sizeof(msg);
l = read(auth->fd, msg, l);
if (l <= 0)
fatal("Incomplete authentication reply.");
buffer_append(&auth->identities, (char *)msg, l);
len -= l;
}
/* Get message type, and verify that we got a proper answer. */
buffer_get(&auth->identities, (char *)msg, 1);
if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)
fatal("Bad authentication reply message type: %d", msg[0]);
/* Get the number of entries in the response and check it for sanity. */
auth->howmany = buffer_get_int(&auth->identities);
if (auth->howmany > 1024)
fatal("Too many identities in authentication reply: %d\n", auth->howmany);
/* Read the packet itself. */
buffer_clear(&auth->identities);
while (len > 0) {
l = len;
if (l > sizeof(msg))
l = sizeof(msg);
l = read(auth->fd, msg, l);
if (l <= 0)
fatal("Incomplete authentication reply.");
buffer_append(&auth->identities, (char *) msg, l);
len -= l;
}
/* Return the first entry (if any). */
return ssh_get_next_identity(auth, e, n, comment);
/* Get message type, and verify that we got a proper answer. */
buffer_get(&auth->identities, (char *) msg, 1);
if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)
fatal("Bad authentication reply message type: %d", msg[0]);
/* Get the number of entries in the response and check it for sanity. */
auth->howmany = buffer_get_int(&auth->identities);
if (auth->howmany > 1024)
fatal("Too many identities in authentication reply: %d\n", auth->howmany);
/* Return the first entry (if any). */
return ssh_get_next_identity(auth, e, n, comment);
}
/* Returns the next authentication identity for the agent. Other functions
@ -198,27 +191,27 @@ int
ssh_get_next_identity(AuthenticationConnection *auth,
BIGNUM *e, BIGNUM *n, char **comment)
{
unsigned int bits;
unsigned int bits;
/* Return failure if no more entries. */
if (auth->howmany <= 0)
return 0;
/* Return failure if no more entries. */
if (auth->howmany <= 0)
return 0;
/* Get the next entry from the packet. These will abort with a fatal
error if the packet is too short or contains corrupt data. */
bits = buffer_get_int(&auth->identities);
buffer_get_bignum(&auth->identities, e);
buffer_get_bignum(&auth->identities, n);
*comment = buffer_get_string(&auth->identities, NULL);
/* Get the next entry from the packet. These will abort with a
fatal error if the packet is too short or contains corrupt data. */
bits = buffer_get_int(&auth->identities);
buffer_get_bignum(&auth->identities, e);
buffer_get_bignum(&auth->identities, n);
*comment = buffer_get_string(&auth->identities, NULL);
if (bits != BN_num_bits(n))
error("Warning: keysize mismatch: actual %d, announced %u",
BN_num_bits(n), bits);
if (bits != BN_num_bits(n))
error("Warning: keysize mismatch: actual %d, announced %u",
BN_num_bits(n), bits);
/* Decrement the number of remaining entries. */
auth->howmany--;
/* Decrement the number of remaining entries. */
auth->howmany--;
return 1;
return 1;
}
/* Generates a random challenge, sends it to the agent, and waits for response
@ -229,355 +222,329 @@ ssh_get_next_identity(AuthenticationConnection *auth,
int
ssh_decrypt_challenge(AuthenticationConnection *auth,
BIGNUM *e, BIGNUM *n, BIGNUM *challenge,
BIGNUM* e, BIGNUM *n, BIGNUM *challenge,
unsigned char session_id[16],
unsigned int response_type,
unsigned char response[16])
{
Buffer buffer;
unsigned char buf[8192];
int len, l, i;
Buffer buffer;
unsigned char buf[8192];
int len, l, i;
/* Response type 0 is no longer supported. */
if (response_type == 0)
fatal("Compatibility with ssh protocol version 1.0 no longer supported.");
/* Response type 0 is no longer supported. */
if (response_type == 0)
fatal("Compatibility with ssh protocol version 1.0 no longer supported.");
/* Format a message to the agent. */
buf[0] = SSH_AGENTC_RSA_CHALLENGE;
buffer_init(&buffer);
buffer_append(&buffer, (char *)buf, 1);
buffer_put_int(&buffer, BN_num_bits(n));
buffer_put_bignum(&buffer, e);
buffer_put_bignum(&buffer, n);
buffer_put_bignum(&buffer, challenge);
buffer_append(&buffer, (char *)session_id, 16);
buffer_put_int(&buffer, response_type);
/* Format a message to the agent. */
buf[0] = SSH_AGENTC_RSA_CHALLENGE;
buffer_init(&buffer);
buffer_append(&buffer, (char *) buf, 1);
buffer_put_int(&buffer, BN_num_bits(n));
buffer_put_bignum(&buffer, e);
buffer_put_bignum(&buffer, n);
buffer_put_bignum(&buffer, challenge);
buffer_append(&buffer, (char *) session_id, 16);
buffer_put_int(&buffer, response_type);
/* Get the length of the message, and format it in the buffer. */
len = buffer_len(&buffer);
PUT_32BIT(buf, len);
/* Get the length of the message, and format it in the buffer. */
len = buffer_len(&buffer);
PUT_32BIT(buf, len);
/* Send the length and then the packet to the agent. */
if (write(auth->fd, buf, 4) != 4 ||
write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
buffer_len(&buffer))
{
error("Error writing to authentication socket.");
error_cleanup:
buffer_free(&buffer);
return 0;
}
/* Wait for response from the agent. First read the length of the
response packet. */
len = 4;
while (len > 0)
{
l = read(auth->fd, buf + 4 - len, len);
if (l <= 0)
{
error("Error reading response length from authentication socket.");
goto error_cleanup;
/* Send the length and then the packet to the agent. */
if (write(auth->fd, buf, 4) != 4 ||
write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
buffer_len(&buffer)) {
error("Error writing to authentication socket.");
error_cleanup:
buffer_free(&buffer);
return 0;
}
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 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;
/* 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;
}
buffer_append(&buffer, (char *)buf, l);
len -= l;
}
/* Get the type of the packet. */
buffer_get(&buffer, (char *)buf, 1);
/* Extract the length, and check it for sanity. */
len = GET_32BIT(buf);
if (len > 256 * 1024)
fatal("Authentication response too long: %d", len);
/* Check for agent failure message. */
if (buf[0] == SSH_AGENT_FAILURE)
{
log("Agent admitted failure to authenticate using the key.");
goto error_cleanup;
}
/* Now it must be an authentication response packet. */
if (buf[0] != SSH_AGENT_RSA_RESPONSE)
fatal("Bad authentication response: %d", buf[0]);
/* 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 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);
/* Get the type of the packet. */
buffer_get(&buffer, (char *) buf, 1);
/* The buffer containing the packet is no longer needed. */
buffer_free(&buffer);
/* Check for agent failure message. */
if (buf[0] == SSH_AGENT_FAILURE) {
log("Agent admitted failure to authenticate using the key.");
goto error_cleanup;
}
/* Now it must be an authentication response packet. */
if (buf[0] != SSH_AGENT_RSA_RESPONSE)
fatal("Bad authentication response: %d", buf[0]);
/* Correct answer. */
return 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);
/* The buffer containing the packet is no longer needed. */
buffer_free(&buffer);
/* Correct answer. */
return 1;
}
/* Adds an identity to the authentication server. This call is not meant to
be used by normal applications. */
int ssh_add_identity(AuthenticationConnection *auth,
RSA *key, const char *comment)
int
ssh_add_identity(AuthenticationConnection *auth,
RSA * key, const char *comment)
{
Buffer buffer;
unsigned char buf[8192];
int len, l, type;
Buffer buffer;
unsigned char buf[8192];
int len, l, type;
/* Format a message to the agent. */
buffer_init(&buffer);
buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);
buffer_put_int(&buffer, BN_num_bits(key->n));
buffer_put_bignum(&buffer, key->n);
buffer_put_bignum(&buffer, key->e);
buffer_put_bignum(&buffer, key->d);
/* To keep within the protocol: p < q for ssh. in SSL p > q */
buffer_put_bignum(&buffer, key->iqmp); /* ssh key->u */
buffer_put_bignum(&buffer, key->q); /* ssh key->p, SSL key->q */
buffer_put_bignum(&buffer, key->p); /* ssh key->q, SSL key->p */
buffer_put_string(&buffer, comment, strlen(comment));
/* Format a message to the agent. */
buffer_init(&buffer);
buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);
buffer_put_int(&buffer, BN_num_bits(key->n));
buffer_put_bignum(&buffer, key->n);
buffer_put_bignum(&buffer, key->e);
buffer_put_bignum(&buffer, key->d);
/* To keep within the protocol: p < q for ssh. in SSL p > q */
buffer_put_bignum(&buffer, key->iqmp); /* ssh key->u */
buffer_put_bignum(&buffer, key->q); /* ssh key->p, SSL key->q */
buffer_put_bignum(&buffer, key->p); /* ssh key->q, SSL key->p */
buffer_put_string(&buffer, comment, strlen(comment));
/* Get the length of the message, and format it in the buffer. */
len = buffer_len(&buffer);
PUT_32BIT(buf, len);
/* Get the length of the message, and format it in the buffer. */
len = buffer_len(&buffer);
PUT_32BIT(buf, len);
/* Send the length and then the packet to the agent. */
if (write(auth->fd, buf, 4) != 4 ||
write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
buffer_len(&buffer))
{
error("Error writing to authentication socket.");
error_cleanup:
buffer_free(&buffer);
return 0;
}
/* Wait for response from the agent. First read the length of the
response packet. */
len = 4;
while (len > 0)
{
l = read(auth->fd, buf + 4 - len, len);
if (l <= 0)
{
error("Error reading response length from authentication socket.");
goto error_cleanup;
/* Send the length and then the packet to the agent. */
if (write(auth->fd, buf, 4) != 4 ||
write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
buffer_len(&buffer)) {
error("Error writing to authentication socket.");
error_cleanup:
buffer_free(&buffer);
return 0;
}
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;
/* 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;
}
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:
fatal("Bad response to add identity from authentication agent: %d",
type);
}
/*NOTREACHED*/
return 0;
}
/* Extract the length, and check it for sanity. */
len = GET_32BIT(buf);
if (len > 256 * 1024)
fatal("Add identity response too long: %d", len);
/* Removes an identity from the authentication server. This call is not meant
/* 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:
fatal("Bad response to add identity from authentication agent: %d",
type);
}
/* NOTREACHED */
return 0;
}
/* Removes an identity from the authentication server. This call is not meant
to be used by normal applications. */
int ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
int
ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
{
Buffer buffer;
unsigned char buf[8192];
int len, l, type;
Buffer buffer;
unsigned char buf[8192];
int len, l, type;
/* Format a message to the agent. */
buffer_init(&buffer);
buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
buffer_put_int(&buffer, BN_num_bits(key->n));
buffer_put_bignum(&buffer, key->e);
buffer_put_bignum(&buffer, key->n);
/* Format a message to the agent. */
buffer_init(&buffer);
buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
buffer_put_int(&buffer, BN_num_bits(key->n));
buffer_put_bignum(&buffer, key->e);
buffer_put_bignum(&buffer, key->n);
/* Get the length of the message, and format it in the buffer. */
len = buffer_len(&buffer);
PUT_32BIT(buf, len);
/* Get the length of the message, and format it in the buffer. */
len = buffer_len(&buffer);
PUT_32BIT(buf, len);
/* Send the length and then the packet to the agent. */
if (write(auth->fd, buf, 4) != 4 ||
write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
buffer_len(&buffer))
{
error("Error writing to authentication socket.");
error_cleanup:
buffer_free(&buffer);
return 0;
}
/* Wait for response from the agent. First read the length of the
response packet. */
len = 4;
while (len > 0)
{
l = read(auth->fd, buf + 4 - len, len);
if (l <= 0)
{
error("Error reading response length from authentication socket.");
goto error_cleanup;
/* Send the length and then the packet to the agent. */
if (write(auth->fd, buf, 4) != 4 ||
write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
buffer_len(&buffer)) {
error("Error writing to authentication socket.");
error_cleanup:
buffer_free(&buffer);
return 0;
}
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;
/* 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;
}
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:
fatal("Bad response to remove identity from authentication agent: %d",
type);
}
/*NOTREACHED*/
return 0;
}
/* Extract the length, and check it for sanity. */
len = GET_32BIT(buf);
if (len > 256 * 1024)
fatal("Remove identity response too long: %d", len);
/* Removes all identities from the agent. This call is not meant
/* 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:
fatal("Bad response to remove identity from authentication agent: %d",
type);
}
/* NOTREACHED */
return 0;
}
/* Removes all identities from the agent. This call is not meant
to be used by normal applications. */
int ssh_remove_all_identities(AuthenticationConnection *auth)
int
ssh_remove_all_identities(AuthenticationConnection *auth)
{
Buffer buffer;
unsigned char buf[8192];
int len, l, type;
Buffer buffer;
unsigned char buf[8192];
int len, l, type;
/* Get the length of the message, and format it in the buffer. */
PUT_32BIT(buf, 1);
buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
/* Get the length of the message, and format it in the buffer. */
PUT_32BIT(buf, 1);
buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
/* Send the length and then the packet to the agent. */
if (write(auth->fd, buf, 5) != 5)
{
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;
/* Send the length and then the packet to the agent. */
if (write(auth->fd, buf, 5) != 5) {
error("Error writing to authentication socket.");
return 0;
}
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 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;
/* 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;
}
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:
fatal("Bad response to remove identity from authentication agent: %d",
type);
}
/*NOTREACHED*/
return 0;
}
/* Extract the length, and check it for sanity. */
len = GET_32BIT(buf);
if (len > 256 * 1024)
fatal("Remove identity response too long: %d", len);
/* Read the rest of the response into the buffer. */
buffer_init(&buffer);
while (len > 0) {
l = len;
if (l > sizeof(buf))
l = sizeof(buf);
l = read(auth->fd, buf, l);
if (l <= 0) {
error("Error reading response from authentication socket.");
buffer_free(&buffer);
return 0;
}
buffer_append(&buffer, (char *) buf, l);
len -= l;
}
/* Get the type of the packet. */
type = buffer_get_char(&buffer);
switch (type) {
case SSH_AGENT_FAILURE:
buffer_free(&buffer);
return 0;
case SSH_AGENT_SUCCESS:
buffer_free(&buffer);
return 1;
default:
fatal("Bad response to remove identity from authentication agent: %d",
type);
}
/* NOTREACHED */
return 0;
}

Просмотреть файл

@ -1,19 +1,19 @@
/*
*
* authfd.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Wed Mar 29 01:17:41 1995 ylo
*
* Functions to interface with the SSH_AUTHENTICATION_FD socket.
*
*/
authfd.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Wed Mar 29 01:17:41 1995 ylo
Functions to interface with the SSH_AUTHENTICATION_FD socket.
*/
/* RCSID("$Id: authfd.h,v 1.2 1999/11/16 02:37:16 damien Exp $"); */
/* RCSID("$Id: authfd.h,v 1.3 1999/11/24 13:26:22 damien Exp $"); */
#ifndef AUTHFD_H
#define AUTHFD_H
@ -31,72 +31,73 @@ Functions to interface with the SSH_AUTHENTICATION_FD socket.
#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8
#define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
typedef struct
{
int fd;
Buffer packet;
Buffer identities;
int howmany;
} AuthenticationConnection;
typedef struct {
int fd;
Buffer packet;
Buffer identities;
int howmany;
} AuthenticationConnection;
/* Returns the number of the authentication fd, or -1 if there is none. */
int ssh_get_authentication_socket();
int ssh_get_authentication_socket();
/* This should be called for any descriptor returned by
/* This should be called for any descriptor returned by
ssh_get_authentication_socket(). Depending on the way the descriptor was
obtained, this may close the descriptor. */
void ssh_close_authentication_socket(int authfd);
void ssh_close_authentication_socket(int authfd);
/* Opens and connects a private socket for communication with the
authentication agent. Returns NULL if an error occurred and the
authentication agent. Returns NULL if an error occurred and the
connection could not be opened. The connection should be closed by
the caller by calling ssh_close_authentication_connection(). */
AuthenticationConnection *ssh_get_authentication_connection();
/* Closes the connection to the authentication agent and frees any associated
memory. */
void ssh_close_authentication_connection(AuthenticationConnection *ac);
void ssh_close_authentication_connection(AuthenticationConnection * ac);
/* Returns the first authentication identity held by the agent.
Returns true if an identity is available, 0 otherwise.
The caller must initialize the integers before the call, and free the
comment after a successful call (before calling ssh_get_next_identity). */
int ssh_get_first_identity(AuthenticationConnection *connection,
BIGNUM *e, BIGNUM *n, char **comment);
int
ssh_get_first_identity(AuthenticationConnection * connection,
BIGNUM * e, BIGNUM * n, char **comment);
/* Returns the next authentication identity for the agent. Other functions
can be called between this and ssh_get_first_identity or two calls of this
function. This returns 0 if there are no more identities. The caller
must free comment after a successful return. */
int ssh_get_next_identity(AuthenticationConnection *connection,
BIGNUM *e, BIGNUM *n, char **comment);
int
ssh_get_next_identity(AuthenticationConnection * connection,
BIGNUM * e, BIGNUM * n, char **comment);
/* Requests the agent to decrypt the given challenge. Returns true if
the agent claims it was able to decrypt it. */
int ssh_decrypt_challenge(AuthenticationConnection *auth,
BIGNUM *e, BIGNUM *n, BIGNUM *challenge,
unsigned char session_id[16],
unsigned int response_type,
unsigned char response[16]);
int
ssh_decrypt_challenge(AuthenticationConnection * auth,
BIGNUM * e, BIGNUM * n, BIGNUM * challenge,
unsigned char session_id[16],
unsigned int response_type,
unsigned char response[16]);
/* Adds an identity to the authentication server. This call is not meant to
be used by normal applications. This returns true if the identity
was successfully added. */
int ssh_add_identity(AuthenticationConnection *connection,
RSA *key, const char *comment);
int ssh_add_identity(AuthenticationConnection * connection,
RSA * key, const char *comment);
/* Removes the identity from the authentication server. This call is
not meant to be used by normal applications. This returns true if the
identity was successfully added. */
int ssh_remove_identity(AuthenticationConnection *connection,
RSA *key);
int ssh_remove_identity(AuthenticationConnection * connection,
RSA * key);
/* Removes all identities from the authentication agent. This call is not
meant to be used by normal applications. This returns true if the
operation was successful. */
int ssh_remove_all_identities(AuthenticationConnection *connection);
int ssh_remove_all_identities(AuthenticationConnection * connection);
/* Closes the connection to the authentication agent. */
void ssh_close_authentication(AuthenticationConnection *connection);
void ssh_close_authentication(AuthenticationConnection * connection);
#endif /* AUTHFD_H */
#endif /* AUTHFD_H */

Просмотреть файл

@ -1,21 +1,21 @@
/*
authfile.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Mon Mar 27 03:52:05 1995 ylo
This file contains functions for reading and writing identity files, and
for reading the passphrase from the user.
*/
*
* authfile.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Mon Mar 27 03:52:05 1995 ylo
*
* This file contains functions for reading and writing identity files, and
* for reading the passphrase from the user.
*
*/
#include "includes.h"
RCSID("$Id: authfile.c,v 1.3 1999/11/13 02:07:45 damien Exp $");
RCSID("$Id: authfile.c,v 1.4 1999/11/24 13:26:22 damien Exp $");
#ifdef HAVE_OPENSSL
#include <openssl/bn.h>
@ -42,93 +42,93 @@ int
save_private_key(const char *filename, const char *passphrase,
RSA *key, const char *comment)
{
Buffer buffer, encrypted;
char buf[100], *cp;
int f, i;
CipherContext cipher;
int cipher_type;
u_int32_t rand;
Buffer buffer, encrypted;
char buf[100], *cp;
int f, i;
CipherContext cipher;
int cipher_type;
u_int32_t rand;
/* If the passphrase is empty, use SSH_CIPHER_NONE to ease converting to
another cipher; otherwise use SSH_AUTHFILE_CIPHER. */
if (strcmp(passphrase, "") == 0)
cipher_type = SSH_CIPHER_NONE;
else
cipher_type = SSH_AUTHFILE_CIPHER;
/* If the passphrase is empty, use SSH_CIPHER_NONE to ease
converting to another cipher; otherwise use
SSH_AUTHFILE_CIPHER. */
if (strcmp(passphrase, "") == 0)
cipher_type = SSH_CIPHER_NONE;
else
cipher_type = SSH_AUTHFILE_CIPHER;
/* This buffer is used to built the secret part of the private key. */
buffer_init(&buffer);
/* Put checkbytes for checking passphrase validity. */
rand = arc4random();
buf[0] = rand & 0xff;
buf[1] = (rand >> 8) & 0xff;
buf[2] = buf[0];
buf[3] = buf[1];
buffer_append(&buffer, buf, 4);
/* This buffer is used to built the secret part of the private key. */
buffer_init(&buffer);
/* Store the private key (n and e will not be stored because they will
be stored in plain text, and storing them also in encrypted format
would just give known plaintext). */
buffer_put_bignum(&buffer, key->d);
buffer_put_bignum(&buffer, key->iqmp);
buffer_put_bignum(&buffer, key->q); /* reverse from SSL p */
buffer_put_bignum(&buffer, key->p); /* reverse from SSL q */
/* Put checkbytes for checking passphrase validity. */
rand = arc4random();
buf[0] = rand & 0xff;
buf[1] = (rand >> 8) & 0xff;
buf[2] = buf[0];
buf[3] = buf[1];
buffer_append(&buffer, buf, 4);
/* Pad the part to be encrypted until its size is a multiple of 8. */
while (buffer_len(&buffer) % 8 != 0)
buffer_put_char(&buffer, 0);
/* Store the private key (n and e will not be stored because they
will be stored in plain text, and storing them also in
encrypted format would just give known plaintext). */
buffer_put_bignum(&buffer, key->d);
buffer_put_bignum(&buffer, key->iqmp);
buffer_put_bignum(&buffer, key->q); /* reverse from SSL p */
buffer_put_bignum(&buffer, key->p); /* reverse from SSL q */
/* This buffer will be used to contain the data in the file. */
buffer_init(&encrypted);
/* Pad the part to be encrypted until its size is a multiple of 8. */
while (buffer_len(&buffer) % 8 != 0)
buffer_put_char(&buffer, 0);
/* First store keyfile id string. */
cp = AUTHFILE_ID_STRING;
for (i = 0; cp[i]; i++)
buffer_put_char(&encrypted, cp[i]);
buffer_put_char(&encrypted, 0);
/* This buffer will be used to contain the data in the file. */
buffer_init(&encrypted);
/* Store cipher type. */
buffer_put_char(&encrypted, cipher_type);
buffer_put_int(&encrypted, 0); /* For future extension */
/* First store keyfile id string. */
cp = AUTHFILE_ID_STRING;
for (i = 0; cp[i]; i++)
buffer_put_char(&encrypted, cp[i]);
buffer_put_char(&encrypted, 0);
/* Store public key. This will be in plain text. */
buffer_put_int(&encrypted, BN_num_bits(key->n));
buffer_put_bignum(&encrypted, key->n);
buffer_put_bignum(&encrypted, key->e);
buffer_put_string(&encrypted, comment, strlen(comment));
/* Store cipher type. */
buffer_put_char(&encrypted, cipher_type);
buffer_put_int(&encrypted, 0); /* For future extension */
/* Allocate space for the private part of the key in the buffer. */
buffer_append_space(&encrypted, &cp, buffer_len(&buffer));
/* Store public key. This will be in plain text. */
buffer_put_int(&encrypted, BN_num_bits(key->n));
buffer_put_bignum(&encrypted, key->n);
buffer_put_bignum(&encrypted, key->e);
buffer_put_string(&encrypted, comment, strlen(comment));
cipher_set_key_string(&cipher, cipher_type, passphrase, 1);
cipher_encrypt(&cipher, (unsigned char *)cp,
(unsigned char *)buffer_ptr(&buffer),
buffer_len(&buffer));
memset(&cipher, 0, sizeof(cipher));
/* Allocate space for the private part of the key in the buffer. */
buffer_append_space(&encrypted, &cp, buffer_len(&buffer));
/* Destroy temporary data. */
memset(buf, 0, sizeof(buf));
buffer_free(&buffer);
cipher_set_key_string(&cipher, cipher_type, passphrase, 1);
cipher_encrypt(&cipher, (unsigned char *) cp,
(unsigned char *) buffer_ptr(&buffer),
buffer_len(&buffer));
memset(&cipher, 0, sizeof(cipher));
/* Write to a file. */
f = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0600);
if (f < 0)
return 0;
/* Destroy temporary data. */
memset(buf, 0, sizeof(buf));
buffer_free(&buffer);
if (write(f, buffer_ptr(&encrypted), buffer_len(&encrypted)) !=
buffer_len(&encrypted))
{
debug("Write to key file %.200s failed: %.100s", filename,
strerror(errno));
buffer_free(&encrypted);
close(f);
remove(filename);
return 0;
}
close(f);
buffer_free(&encrypted);
return 1;
/* Write to a file. */
f = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (f < 0)
return 0;
if (write(f, buffer_ptr(&encrypted), buffer_len(&encrypted)) !=
buffer_len(&encrypted)) {
debug("Write to key file %.200s failed: %.100s", filename,
strerror(errno));
buffer_free(&encrypted);
close(f);
remove(filename);
return 0;
}
close(f);
buffer_free(&encrypted);
return 1;
}
/* Loads the public part of the key file. Returns 0 if an error
@ -136,70 +136,65 @@ save_private_key(const char *filename, const char *passphrase,
non-zero otherwise. */
int
load_public_key(const char *filename, RSA *pub,
load_public_key(const char *filename, RSA * pub,
char **comment_return)
{
int f, i;
off_t len;
Buffer buffer;
char *cp;
int f, i;
off_t len;
Buffer buffer;
char *cp;
/* Read data from the file into the buffer. */
f = open(filename, O_RDONLY);
if (f < 0)
return 0;
/* Read data from the file into the buffer. */
f = open(filename, O_RDONLY);
if (f < 0)
return 0;
len = lseek(f, (off_t)0, SEEK_END);
lseek(f, (off_t)0, SEEK_SET);
buffer_init(&buffer);
buffer_append_space(&buffer, &cp, len);
len = lseek(f, (off_t) 0, SEEK_END);
lseek(f, (off_t) 0, SEEK_SET);
if (read(f, cp, (size_t)len) != (size_t)len)
{
debug("Read from key file %.200s failed: %.100s", filename,
strerror(errno));
buffer_free(&buffer);
close(f);
return 0;
}
close(f);
buffer_init(&buffer);
buffer_append_space(&buffer, &cp, len);
/* Check that it is at least big enought to contain the ID string. */
if (len < strlen(AUTHFILE_ID_STRING) + 1)
{
debug("Bad key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
if (read(f, cp, (size_t) len) != (size_t) len) {
debug("Read from key file %.200s failed: %.100s", filename,
strerror(errno));
buffer_free(&buffer);
close(f);
return 0;
}
close(f);
/* Check that it is at least big enought to contain the ID string. */
if (len < strlen(AUTHFILE_ID_STRING) + 1) {
debug("Bad key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
/* Make sure it begins with the id string. Consume the id string
from the buffer. */
for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)
if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) {
debug("Bad key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
/* Skip cipher type and reserved data. */
(void) buffer_get_char(&buffer); /* cipher type */
(void) buffer_get_int(&buffer); /* reserved */
/* Read the public key from the buffer. */
buffer_get_int(&buffer);
pub->n = BN_new();
buffer_get_bignum(&buffer, pub->n);
pub->e = BN_new();
buffer_get_bignum(&buffer, pub->e);
if (comment_return)
*comment_return = buffer_get_string(&buffer, NULL);
/* The encrypted private part is not parsed by this function. */
/* Make sure it begins with the id string. Consume the id string from
the buffer. */
for (i = 0; i < (unsigned int)strlen(AUTHFILE_ID_STRING) + 1; i++)
if (buffer_get_char(&buffer) != (unsigned char)AUTHFILE_ID_STRING[i])
{
debug("Bad key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
/* Skip cipher type and reserved data. */
(void)buffer_get_char(&buffer); /* cipher type */
(void)buffer_get_int(&buffer); /* reserved */
/* Read the public key from the buffer. */
buffer_get_int(&buffer);
pub->n = BN_new();
buffer_get_bignum(&buffer, pub->n);
pub->e = BN_new();
buffer_get_bignum(&buffer, pub->e);
if (comment_return)
*comment_return = buffer_get_string(&buffer, NULL);
/* The encrypted private part is not parsed by this function. */
buffer_free(&buffer);
return 1;
return 1;
}
/* Loads the private key from the file. Returns 0 if an error is encountered
@ -208,149 +203,139 @@ load_public_key(const char *filename, RSA *pub,
int
load_private_key(const char *filename, const char *passphrase,
RSA *prv, char **comment_return)
RSA * prv, char **comment_return)
{
int f, i, check1, check2, cipher_type;
off_t len;
Buffer buffer, decrypted;
char *cp;
CipherContext cipher;
BN_CTX *ctx;
BIGNUM *aux;
struct stat st;
int f, i, check1, check2, cipher_type;
off_t len;
Buffer buffer, decrypted;
char *cp;
CipherContext cipher;
BN_CTX *ctx;
BIGNUM *aux;
struct stat st;
/* Read the file into the buffer. */
f = open(filename, O_RDONLY);
if (f < 0)
return 0;
/* Read the file into the buffer. */
f = open(filename, O_RDONLY);
if (f < 0)
return 0;
/* We assume we are called under uid of the owner of the file */
if (fstat(f, &st) < 0 ||
(st.st_uid != 0 && st.st_uid != getuid()) ||
(st.st_mode & 077) != 0) {
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("Bad ownership or mode(0%3.3o) for '%s'.",
st.st_mode & 0777, filename);
error("It is recommended that your private key files are NOT accessible by others.");
return 0;
}
/* We assume we are called under uid of the owner of the file */
if (fstat(f, &st) < 0 ||
(st.st_uid != 0 && st.st_uid != getuid()) ||
(st.st_mode & 077) != 0) {
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("Bad ownership or mode(0%3.3o) for '%s'.",
st.st_mode & 0777, filename);
error("It is recommended that your private key files are NOT accessible by others.");
return 0;
}
len = lseek(f, (off_t) 0, SEEK_END);
lseek(f, (off_t) 0, SEEK_SET);
len = lseek(f, (off_t)0, SEEK_END);
lseek(f, (off_t)0, SEEK_SET);
buffer_init(&buffer);
buffer_append_space(&buffer, &cp, len);
buffer_init(&buffer);
buffer_append_space(&buffer, &cp, len);
if (read(f, cp, (size_t)len) != (size_t)len)
{
debug("Read from key file %.200s failed: %.100s", filename,
strerror(errno));
buffer_free(&buffer);
close(f);
return 0;
}
close(f);
if (read(f, cp, (size_t) len) != (size_t) len) {
debug("Read from key file %.200s failed: %.100s", filename,
strerror(errno));
buffer_free(&buffer);
close(f);
return 0;
}
close(f);
/* Check that it is at least big enought to contain the ID string. */
if (len < strlen(AUTHFILE_ID_STRING) + 1)
{
debug("Bad key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
/* Check that it is at least big enought to contain the ID string. */
if (len < strlen(AUTHFILE_ID_STRING) + 1) {
debug("Bad key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
/* Make sure it begins with the id string. Consume the id string
from the buffer. */
for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)
if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) {
debug("Bad key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
/* Read cipher type. */
cipher_type = buffer_get_char(&buffer);
(void) buffer_get_int(&buffer); /* Reserved data. */
/* Read the public key from the buffer. */
buffer_get_int(&buffer);
prv->n = BN_new();
buffer_get_bignum(&buffer, prv->n);
prv->e = BN_new();
buffer_get_bignum(&buffer, prv->e);
if (comment_return)
*comment_return = buffer_get_string(&buffer, NULL);
else
xfree(buffer_get_string(&buffer, NULL));
/* Check that it is a supported cipher. */
if (((cipher_mask() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) &
(1 << cipher_type)) == 0) {
debug("Unsupported cipher %.100s used in key file %.200s.",
cipher_name(cipher_type), filename);
buffer_free(&buffer);
goto fail;
}
/* Initialize space for decrypted data. */
buffer_init(&decrypted);
buffer_append_space(&decrypted, &cp, buffer_len(&buffer));
/* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
cipher_set_key_string(&cipher, cipher_type, passphrase, 0);
cipher_decrypt(&cipher, (unsigned char *) cp,
(unsigned char *) buffer_ptr(&buffer),
buffer_len(&buffer));
/* Make sure it begins with the id string. Consume the id string from
the buffer. */
for (i = 0; i < (unsigned int)strlen(AUTHFILE_ID_STRING) + 1; i++)
if (buffer_get_char(&buffer) != (unsigned char)AUTHFILE_ID_STRING[i])
{
debug("Bad key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
/* Read cipher type. */
cipher_type = buffer_get_char(&buffer);
(void)buffer_get_int(&buffer); /* Reserved data. */
check1 = buffer_get_char(&decrypted);
check2 = buffer_get_char(&decrypted);
if (check1 != buffer_get_char(&decrypted) ||
check2 != buffer_get_char(&decrypted)) {
if (strcmp(passphrase, "") != 0)
debug("Bad passphrase supplied for key file %.200s.", filename);
/* Bad passphrase. */
buffer_free(&decrypted);
fail:
BN_clear_free(prv->n);
BN_clear_free(prv->e);
if (comment_return)
xfree(*comment_return);
return 0;
}
/* Read the rest of the private key. */
prv->d = BN_new();
buffer_get_bignum(&decrypted, prv->d);
prv->iqmp = BN_new();
buffer_get_bignum(&decrypted, prv->iqmp); /* u */
/* in SSL and SSH p and q are exchanged */
prv->q = BN_new();
buffer_get_bignum(&decrypted, prv->q); /* p */
prv->p = BN_new();
buffer_get_bignum(&decrypted, prv->p); /* q */
/* Read the public key from the buffer. */
buffer_get_int(&buffer);
prv->n = BN_new();
buffer_get_bignum(&buffer, prv->n);
prv->e = BN_new();
buffer_get_bignum(&buffer, prv->e);
if (comment_return)
*comment_return = buffer_get_string(&buffer, NULL);
else
xfree(buffer_get_string(&buffer, NULL));
ctx = BN_CTX_new();
aux = BN_new();
/* Check that it is a supported cipher. */
if (((cipher_mask() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) &
(1 << cipher_type)) == 0)
{
debug("Unsupported cipher %.100s used in key file %.200s.",
cipher_name(cipher_type), filename);
buffer_free(&buffer);
goto fail;
}
BN_sub(aux, prv->q, BN_value_one());
prv->dmq1 = BN_new();
BN_mod(prv->dmq1, prv->d, aux, ctx);
/* Initialize space for decrypted data. */
buffer_init(&decrypted);
buffer_append_space(&decrypted, &cp, buffer_len(&buffer));
/* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
cipher_set_key_string(&cipher, cipher_type, passphrase, 0);
cipher_decrypt(&cipher, (unsigned char *)cp,
(unsigned char *)buffer_ptr(&buffer),
buffer_len(&buffer));
BN_sub(aux, prv->p, BN_value_one());
prv->dmp1 = BN_new();
BN_mod(prv->dmp1, prv->d, aux, ctx);
buffer_free(&buffer);
BN_clear_free(aux);
BN_CTX_free(ctx);
check1 = buffer_get_char(&decrypted);
check2 = buffer_get_char(&decrypted);
if (check1 != buffer_get_char(&decrypted) ||
check2 != buffer_get_char(&decrypted))
{
if (strcmp(passphrase, "") != 0)
debug("Bad passphrase supplied for key file %.200s.", filename);
/* Bad passphrase. */
buffer_free(&decrypted);
fail:
BN_clear_free(prv->n);
BN_clear_free(prv->e);
if (comment_return)
xfree(*comment_return);
return 0;
}
buffer_free(&decrypted);
/* Read the rest of the private key. */
prv->d = BN_new();
buffer_get_bignum(&decrypted, prv->d);
prv->iqmp = BN_new();
buffer_get_bignum(&decrypted, prv->iqmp); /* u */
/* in SSL and SSH p and q are exchanged */
prv->q = BN_new();
buffer_get_bignum(&decrypted, prv->q); /* p */
prv->p = BN_new();
buffer_get_bignum(&decrypted, prv->p); /* q */
ctx = BN_CTX_new();
aux = BN_new();
BN_sub(aux, prv->q, BN_value_one());
prv->dmq1 = BN_new();
BN_mod(prv->dmq1, prv->d, aux, ctx);
BN_sub(aux, prv->p, BN_value_one());
prv->dmp1 = BN_new();
BN_mod(prv->dmp1, prv->d, aux, ctx);
BN_clear_free(aux);
BN_CTX_free(ctx);
buffer_free(&decrypted);
return 1;
return 1;
}

222
bufaux.c
Просмотреть файл

@ -1,21 +1,21 @@
/*
bufaux.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Wed Mar 29 02:24:47 1995 ylo
Auxiliary functions for storing and retrieving various data types to/from
Buffers.
*/
*
* bufaux.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Wed Mar 29 02:24:47 1995 ylo
*
* Auxiliary functions for storing and retrieving various data types to/from
* Buffers.
*
*/
#include "includes.h"
RCSID("$Id: bufaux.c,v 1.5 1999/11/13 02:22:46 damien Exp $");
RCSID("$Id: bufaux.c,v 1.6 1999/11/24 13:26:22 damien Exp $");
#include "ssh.h"
@ -30,122 +30,136 @@ RCSID("$Id: bufaux.c,v 1.5 1999/11/13 02:22:46 damien Exp $");
#include "xmalloc.h"
#include "getput.h"
/* Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
by (bits+7)/8 bytes of binary data, msb first. */
/*
* Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
* by (bits+7)/8 bytes of binary data, msb first.
*/
void
buffer_put_bignum(Buffer *buffer, BIGNUM *value)
{
int bits = BN_num_bits(value);
int bin_size = (bits + 7) / 8;
char *buf = xmalloc(bin_size);
int oi;
char msg[2];
/* Get the value of in binary */
oi = BN_bn2bin(value, buf);
if (oi != bin_size)
fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d",
oi, bin_size);
int bits = BN_num_bits(value);
int bin_size = (bits + 7) / 8;
char *buf = xmalloc(bin_size);
int oi;
char msg[2];
/* Store the number of bits in the buffer in two bytes, msb first. */
PUT_16BIT(msg, bits);
buffer_append(buffer, msg, 2);
/* Store the binary data. */
buffer_append(buffer, buf, oi);
/* Clear the temporary data. */
memset(buf, 0, bin_size);
xfree(buf);
/* Get the value of in binary */
oi = BN_bn2bin(value, buf);
if (oi != bin_size)
fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d",
oi, bin_size);
/* Store the number of bits in the buffer in two bytes, msb first. */
PUT_16BIT(msg, bits);
buffer_append(buffer, msg, 2);
/* Store the binary data. */
buffer_append(buffer, buf, oi);
/* Clear the temporary data. */
memset(buf, 0, bin_size);
xfree(buf);
}
/* Retrieves an BIGNUM from the buffer. */
/*
* Retrieves an BIGNUM from the buffer.
*/
int
buffer_get_bignum(Buffer *buffer, BIGNUM *value)
{
int bits, bytes;
unsigned char buf[2], *bin;
int bits, bytes;
unsigned char buf[2], *bin;
/* Get the number for bits. */
buffer_get(buffer, (char *)buf, 2);
bits = GET_16BIT(buf);
/* Compute the number of binary bytes that follow. */
bytes = (bits + 7) / 8;
if (buffer_len(buffer) < bytes)
fatal("buffer_get_bignum: input buffer too small");
bin = buffer_ptr(buffer);
BN_bin2bn(bin, bytes, value);
buffer_consume(buffer, bytes);
/* Get the number for bits. */
buffer_get(buffer, (char *) buf, 2);
bits = GET_16BIT(buf);
/* Compute the number of binary bytes that follow. */
bytes = (bits + 7) / 8;
if (buffer_len(buffer) < bytes)
fatal("buffer_get_bignum: input buffer too small");
bin = buffer_ptr(buffer);
BN_bin2bn(bin, bytes, value);
buffer_consume(buffer, bytes);
return 2 + bytes;
return 2 + bytes;
}
/* Returns an integer from the buffer (4 bytes, msb first). */
unsigned int buffer_get_int(Buffer *buffer)
/*
* Returns an integer from the buffer (4 bytes, msb first).
*/
unsigned int
buffer_get_int(Buffer *buffer)
{
unsigned char buf[4];
buffer_get(buffer, (char *)buf, 4);
return GET_32BIT(buf);
unsigned char buf[4];
buffer_get(buffer, (char *) buf, 4);
return GET_32BIT(buf);
}
/* Stores an integer in the buffer in 4 bytes, msb first. */
void buffer_put_int(Buffer *buffer, unsigned int value)
/*
* Stores an integer in the buffer in 4 bytes, msb first.
*/
void
buffer_put_int(Buffer *buffer, unsigned int value)
{
char buf[4];
PUT_32BIT(buf, value);
buffer_append(buffer, buf, 4);
char buf[4];
PUT_32BIT(buf, value);
buffer_append(buffer, buf, 4);
}
/* Returns an arbitrary binary string from the buffer. The string cannot
be longer than 256k. The returned value points to memory allocated
with xmalloc; it is the responsibility of the calling function to free
the data. If length_ptr is non-NULL, the length of the returned data
will be stored there. A null character will be automatically appended
to the returned string, and is not counted in length. */
char *buffer_get_string(Buffer *buffer, unsigned int *length_ptr)
/*
* Returns an arbitrary binary string from the buffer. The string cannot
* be longer than 256k. The returned value points to memory allocated
* with xmalloc; it is the responsibility of the calling function to free
* the data. If length_ptr is non-NULL, the length of the returned data
* will be stored there. A null character will be automatically appended
* to the returned string, and is not counted in length.
*/
char *
buffer_get_string(Buffer *buffer, unsigned int *length_ptr)
{
unsigned int len;
char *value;
/* Get the length. */
len = buffer_get_int(buffer);
if (len > 256*1024)
fatal("Received packet with bad string length %d", len);
/* Allocate space for the string. Add one byte for a null character. */
value = xmalloc(len + 1);
/* Get the string. */
buffer_get(buffer, value, len);
/* Append a null character to make processing easier. */
value[len] = 0;
/* Optionally return the length of the string. */
if (length_ptr)
*length_ptr = len;
return value;
unsigned int len;
char *value;
/* Get the length. */
len = buffer_get_int(buffer);
if (len > 256 * 1024)
fatal("Received packet with bad string length %d", len);
/* Allocate space for the string. Add one byte for a null character. */
value = xmalloc(len + 1);
/* Get the string. */
buffer_get(buffer, value, len);
/* Append a null character to make processing easier. */
value[len] = 0;
/* Optionally return the length of the string. */
if (length_ptr)
*length_ptr = len;
return value;
}
/* Stores and arbitrary binary string in the buffer. */
void buffer_put_string(Buffer *buffer, const void *buf, unsigned int len)
/*
* Stores and arbitrary binary string in the buffer.
*/
void
buffer_put_string(Buffer *buffer, const void *buf, unsigned int len)
{
buffer_put_int(buffer, len);
buffer_append(buffer, buf, len);
buffer_put_int(buffer, len);
buffer_append(buffer, buf, len);
}
/* Returns a character from the buffer (0 - 255). */
int buffer_get_char(Buffer *buffer)
/*
* Returns a character from the buffer (0 - 255).
*/
int
buffer_get_char(Buffer *buffer)
{
char ch;
buffer_get(buffer, &ch, 1);
return (unsigned char)ch;
char ch;
buffer_get(buffer, &ch, 1);
return (unsigned char) ch;
}
/* Stores a character in the buffer. */
void buffer_put_char(Buffer *buffer, int value)
/*
* Stores a character in the buffer.
*/
void
buffer_put_char(Buffer *buffer, int value)
{
char ch = value;
buffer_append(buffer, &ch, 1);
char ch = value;
buffer_append(buffer, &ch, 1);
}

Просмотреть файл

@ -1,17 +1,17 @@
/*
*
* bufaux.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Wed Mar 29 02:18:23 1995 ylo
*
*/
bufaux.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Wed Mar 29 02:18:23 1995 ylo
*/
/* RCSID("$Id: bufaux.h,v 1.1 1999/10/27 03:42:43 damien Exp $"); */
/* RCSID("$Id: bufaux.h,v 1.2 1999/11/24 13:26:22 damien Exp $"); */
#ifndef BUFAUX_H
#define BUFAUX_H
@ -20,22 +20,22 @@ Created: Wed Mar 29 02:18:23 1995 ylo
/* Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
by (bits+7)/8 bytes of binary data, msb first. */
void buffer_put_bignum(Buffer *buffer, BIGNUM *value);
void buffer_put_bignum(Buffer * buffer, BIGNUM * value);
/* Retrieves an BIGNUM from the buffer. */
int buffer_get_bignum(Buffer *buffer, BIGNUM *value);
int buffer_get_bignum(Buffer * buffer, BIGNUM * value);
/* Returns an integer from the buffer (4 bytes, msb first). */
unsigned int buffer_get_int(Buffer *buffer);
unsigned int buffer_get_int(Buffer * buffer);
/* Stores an integer in the buffer in 4 bytes, msb first. */
void buffer_put_int(Buffer *buffer, unsigned int value);
void buffer_put_int(Buffer * buffer, unsigned int value);
/* Returns a character from the buffer (0 - 255). */
int buffer_get_char(Buffer *buffer);
int buffer_get_char(Buffer * buffer);
/* Stores a character in the buffer. */
void buffer_put_char(Buffer *buffer, int value);
void buffer_put_char(Buffer * buffer, int value);
/* Returns an arbitrary binary string from the buffer. The string cannot
be longer than 256k. The returned value points to memory allocated
@ -43,9 +43,9 @@ void buffer_put_char(Buffer *buffer, int value);
the data. If length_ptr is non-NULL, the length of the returned data
will be stored there. A null character will be automatically appended
to the returned string, and is not counted in length. */
char *buffer_get_string(Buffer *buffer, unsigned int *length_ptr);
char *buffer_get_string(Buffer * buffer, unsigned int *length_ptr);
/* Stores and arbitrary binary string in the buffer. */
void buffer_put_string(Buffer *buffer, const void *buf, unsigned int len);
void buffer_put_string(Buffer * buffer, const void *buf, unsigned int len);
#endif /* BUFAUX_H */
#endif /* BUFAUX_H */

179
buffer.c
Просмотреть файл

@ -1,20 +1,20 @@
/*
buffer.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Sat Mar 18 04:15:33 1995 ylo
Functions for manipulating fifo buffers (that can grow if needed).
*/
*
* buffer.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Sat Mar 18 04:15:33 1995 ylo
*
* Functions for manipulating fifo buffers (that can grow if needed).
*
*/
#include "includes.h"
RCSID("$Id: buffer.c,v 1.1 1999/10/27 03:42:43 damien Exp $");
RCSID("$Id: buffer.c,v 1.2 1999/11/24 13:26:22 damien Exp $");
#include "xmalloc.h"
#include "buffer.h"
@ -22,129 +22,134 @@ RCSID("$Id: buffer.c,v 1.1 1999/10/27 03:42:43 damien Exp $");
/* Initializes the buffer structure. */
void buffer_init(Buffer *buffer)
void
buffer_init(Buffer *buffer)
{
buffer->alloc = 4096;
buffer->buf = xmalloc(buffer->alloc);
buffer->offset = 0;
buffer->end = 0;
buffer->alloc = 4096;
buffer->buf = xmalloc(buffer->alloc);
buffer->offset = 0;
buffer->end = 0;
}
/* Frees any memory used for the buffer. */
void buffer_free(Buffer *buffer)
void
buffer_free(Buffer *buffer)
{
memset(buffer->buf, 0, buffer->alloc);
xfree(buffer->buf);
memset(buffer->buf, 0, buffer->alloc);
xfree(buffer->buf);
}
/* Clears any data from the buffer, making it empty. This does not actually
zero the memory. */
void buffer_clear(Buffer *buffer)
void
buffer_clear(Buffer *buffer)
{
buffer->offset = 0;
buffer->end = 0;
buffer->offset = 0;
buffer->end = 0;
}
/* Appends data to the buffer, expanding it if necessary. */
void buffer_append(Buffer *buffer, const char *data, unsigned int len)
void
buffer_append(Buffer *buffer, const char *data, unsigned int len)
{
char *cp;
buffer_append_space(buffer, &cp, len);
memcpy(cp, data, len);
char *cp;
buffer_append_space(buffer, &cp, len);
memcpy(cp, data, len);
}
/* Appends space to the buffer, expanding the buffer if necessary.
This does not actually copy the data into the buffer, but instead
returns a pointer to the allocated region. */
void buffer_append_space(Buffer *buffer, char **datap, unsigned int len)
void
buffer_append_space(Buffer *buffer, char **datap, unsigned int len)
{
/* If the buffer is empty, start using it from the beginning. */
if (buffer->offset == buffer->end)
{
buffer->offset = 0;
buffer->end = 0;
}
restart:
/* If there is enough space to store all data, store it now. */
if (buffer->end + len < buffer->alloc)
{
*datap = buffer->buf + buffer->end;
buffer->end += len;
return;
}
/* If the buffer is quite empty, but all data is at the end, move the
data to the beginning and retry. */
if (buffer->offset > buffer->alloc / 2)
{
memmove(buffer->buf, buffer->buf + buffer->offset,
buffer->end - buffer->offset);
buffer->end -= buffer->offset;
buffer->offset = 0;
goto restart;
}
/* Increase the size of the buffer and retry. */
buffer->alloc += len + 32768;
buffer->buf = xrealloc(buffer->buf, buffer->alloc);
goto restart;
/* If the buffer is empty, start using it from the beginning. */
if (buffer->offset == buffer->end) {
buffer->offset = 0;
buffer->end = 0;
}
restart:
/* If there is enough space to store all data, store it now. */
if (buffer->end + len < buffer->alloc) {
*datap = buffer->buf + buffer->end;
buffer->end += len;
return;
}
/* If the buffer is quite empty, but all data is at the end, move
the data to the beginning and retry. */
if (buffer->offset > buffer->alloc / 2) {
memmove(buffer->buf, buffer->buf + buffer->offset,
buffer->end - buffer->offset);
buffer->end -= buffer->offset;
buffer->offset = 0;
goto restart;
}
/* Increase the size of the buffer and retry. */
buffer->alloc += len + 32768;
buffer->buf = xrealloc(buffer->buf, buffer->alloc);
goto restart;
}
/* Returns the number of bytes of data in the buffer. */
unsigned int buffer_len(Buffer *buffer)
unsigned int
buffer_len(Buffer *buffer)
{
return buffer->end - buffer->offset;
return buffer->end - buffer->offset;
}
/* Gets data from the beginning of the buffer. */
void buffer_get(Buffer *buffer, char *buf, unsigned int len)
void
buffer_get(Buffer *buffer, char *buf, unsigned int len)
{
if (len > buffer->end - buffer->offset)
fatal("buffer_get trying to get more bytes than in buffer");
memcpy(buf, buffer->buf + buffer->offset, len);
buffer->offset += len;
if (len > buffer->end - buffer->offset)
fatal("buffer_get trying to get more bytes than in buffer");
memcpy(buf, buffer->buf + buffer->offset, len);
buffer->offset += len;
}
/* Consumes the given number of bytes from the beginning of the buffer. */
void buffer_consume(Buffer *buffer, unsigned int bytes)
void
buffer_consume(Buffer *buffer, unsigned int bytes)
{
if (bytes > buffer->end - buffer->offset)
fatal("buffer_get trying to get more bytes than in buffer");
buffer->offset += bytes;
}
if (bytes > buffer->end - buffer->offset)
fatal("buffer_get trying to get more bytes than in buffer");
buffer->offset += bytes;
}
/* Consumes the given number of bytes from the end of the buffer. */
void buffer_consume_end(Buffer *buffer, unsigned int bytes)
void
buffer_consume_end(Buffer *buffer, unsigned int bytes)
{
if (bytes > buffer->end - buffer->offset)
fatal("buffer_get trying to get more bytes than in buffer");
buffer->end -= bytes;
}
if (bytes > buffer->end - buffer->offset)
fatal("buffer_get trying to get more bytes than in buffer");
buffer->end -= bytes;
}
/* Returns a pointer to the first used byte in the buffer. */
char *buffer_ptr(Buffer *buffer)
char *
buffer_ptr(Buffer *buffer)
{
return buffer->buf + buffer->offset;
return buffer->buf + buffer->offset;
}
/* Dumps the contents of the buffer to stderr. */
void buffer_dump(Buffer *buffer)
void
buffer_dump(Buffer *buffer)
{
int i;
unsigned char *ucp = (unsigned char *)buffer->buf;
for (i = buffer->offset; i < buffer->end; i++)
fprintf(stderr, " %02x", ucp[i]);
fprintf(stderr, "\n");
int i;
unsigned char *ucp = (unsigned char *) buffer->buf;
for (i = buffer->offset; i < buffer->end; i++)
fprintf(stderr, " %02x", ucp[i]);
fprintf(stderr, "\n");
}

Просмотреть файл

@ -1,66 +1,64 @@
/*
*
* buffer.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Sat Mar 18 04:12:25 1995 ylo
*
* Code for manipulating FIFO buffers.
*
*/
buffer.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Sat Mar 18 04:12:25 1995 ylo
Code for manipulating FIFO buffers.
*/
/* RCSID("$Id: buffer.h,v 1.1 1999/10/27 03:42:43 damien Exp $"); */
/* RCSID("$Id: buffer.h,v 1.2 1999/11/24 13:26:22 damien Exp $"); */
#ifndef BUFFER_H
#define BUFFER_H
typedef struct
{
char *buf; /* Buffer for data. */
unsigned int alloc; /* Number of bytes allocated for data. */
unsigned int offset; /* Offset of first byte containing data. */
unsigned int end; /* Offset of last byte containing data. */
} Buffer;
typedef struct {
char *buf; /* Buffer for data. */
unsigned int alloc; /* Number of bytes allocated for data. */
unsigned int offset; /* Offset of first byte containing data. */
unsigned int end; /* Offset of last byte containing data. */
} Buffer;
/* Initializes the buffer structure. */
void buffer_init(Buffer *buffer);
void buffer_init(Buffer * buffer);
/* Frees any memory used for the buffer. */
void buffer_free(Buffer *buffer);
void buffer_free(Buffer * buffer);
/* Clears any data from the buffer, making it empty. This does not actually
zero the memory. */
void buffer_clear(Buffer *buffer);
void buffer_clear(Buffer * buffer);
/* Appends data to the buffer, expanding it if necessary. */
void buffer_append(Buffer *buffer, const char *data, unsigned int len);
void buffer_append(Buffer * buffer, const char *data, unsigned int len);
/* Appends space to the buffer, expanding the buffer if necessary.
This does not actually copy the data into the buffer, but instead
returns a pointer to the allocated region. */
void buffer_append_space(Buffer *buffer, char **datap, unsigned int len);
void buffer_append_space(Buffer * buffer, char **datap, unsigned int len);
/* Returns the number of bytes of data in the buffer. */
unsigned int buffer_len(Buffer *buffer);
unsigned int buffer_len(Buffer * buffer);
/* Gets data from the beginning of the buffer. */
void buffer_get(Buffer *buffer, char *buf, unsigned int len);
void buffer_get(Buffer * buffer, char *buf, unsigned int len);
/* Consumes the given number of bytes from the beginning of the buffer. */
void buffer_consume(Buffer *buffer, unsigned int bytes);
void buffer_consume(Buffer * buffer, unsigned int bytes);
/* Consumes the given number of bytes from the end of the buffer. */
void buffer_consume_end(Buffer *buffer, unsigned int bytes);
void buffer_consume_end(Buffer * buffer, unsigned int bytes);
/* Returns a pointer to the first used byte in the buffer. */
char *buffer_ptr(Buffer *buffer);
char *buffer_ptr(Buffer * buffer);
/* Dumps the contents of the buffer to stderr in hex. This intended for
debugging purposes only. */
void buffer_dump(Buffer *buffer);
void buffer_dump(Buffer * buffer);
#endif /* BUFFER_H */
#endif /* BUFFER_H */

Просмотреть файл

@ -1,233 +1,228 @@
/*
canohost.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Sun Jul 2 17:52:22 1995 ylo
Functions for returning the canonical host name of the remote site.
*/
*
* canohost.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Sun Jul 2 17:52:22 1995 ylo
*
* Functions for returning the canonical host name of the remote site.
*
*/
#include "includes.h"
RCSID("$Id: canohost.c,v 1.2 1999/11/15 04:25:10 damien Exp $");
RCSID("$Id: canohost.c,v 1.3 1999/11/24 13:26:22 damien Exp $");
#include "packet.h"
#include "xmalloc.h"
#include "ssh.h"
/* Return the canonical name of the host at the other end of the socket.
/* Return the canonical name of the host at the other end of the socket.
The caller should free the returned string with xfree. */
char *get_remote_hostname(int socket)
char *
get_remote_hostname(int socket)
{
struct sockaddr_in from;
int fromlen, i;
struct hostent *hp;
char name[MAXHOSTNAMELEN];
struct sockaddr_in from;
int fromlen, i;
struct hostent *hp;
char name[MAXHOSTNAMELEN];
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0)
{
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
/* Map the IP address to a host name. */
hp = gethostbyaddr((char *)&from.sin_addr, sizeof(struct in_addr),
from.sin_family);
if (hp)
{
/* Got host name, find canonic host name. */
if (strchr(hp->h_name, '.') != 0)
strlcpy(name, hp->h_name, sizeof(name));
else if (hp->h_aliases != 0
&& hp->h_aliases[0] != 0
&& strchr(hp->h_aliases[0], '.') != 0)
strlcpy(name, hp->h_aliases[0], sizeof(name));
else
strlcpy(name, hp->h_name, sizeof(name));
/* Convert it to all lowercase (which is expected by the rest of this
software). */
for (i = 0; name[i]; i++)
if (isupper(name[i]))
name[i] = tolower(name[i]);
/* Map it back to an IP address and check that the given address actually
is an address of this host. This is necessary because anyone with
access to a name server can define arbitrary names for an IP address.
Mapping from name to IP address can be trusted better (but can still
be fooled if the intruder has access to the name server of the
domain). */
hp = gethostbyname(name);
if (!hp)
{
log("reverse mapping checking gethostbyname for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);
strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
goto check_ip_options;
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
/* Look for the address from the list of addresses. */
for (i = 0; hp->h_addr_list[i]; i++)
if (memcmp(hp->h_addr_list[i], &from.sin_addr, sizeof(from.sin_addr))
== 0)
break;
/* If we reached the end of the list, the address was not there. */
if (!hp->h_addr_list[i])
{
/* Address not found for the host name. */
log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!",
inet_ntoa(from.sin_addr), name);
strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
goto check_ip_options;
/* Map the IP address to a host name. */
hp = gethostbyaddr((char *) &from.sin_addr, sizeof(struct in_addr),
from.sin_family);
if (hp) {
/* Got host name, find canonic host name. */
if (strchr(hp->h_name, '.') != 0)
strlcpy(name, hp->h_name, sizeof(name));
else if (hp->h_aliases != 0
&& hp->h_aliases[0] != 0
&& strchr(hp->h_aliases[0], '.') != 0)
strlcpy(name, hp->h_aliases[0], sizeof(name));
else
strlcpy(name, hp->h_name, sizeof(name));
/* Convert it to all lowercase (which is expected by the
rest of this software). */
for (i = 0; name[i]; i++)
if (isupper(name[i]))
name[i] = tolower(name[i]);
/* Map it back to an IP address and check that the given
address actually is an address of this host. This is
necessary because anyone with access to a name server
can define arbitrary names for an IP address. Mapping
from name to IP address can be trusted better (but can
still be fooled if the intruder has access to the name
server of the domain). */
hp = gethostbyname(name);
if (!hp) {
log("reverse mapping checking gethostbyname for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);
strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
goto check_ip_options;
}
/* Look for the address from the list of addresses. */
for (i = 0; hp->h_addr_list[i]; i++)
if (memcmp(hp->h_addr_list[i], &from.sin_addr, sizeof(from.sin_addr))
== 0)
break;
/* If we reached the end of the list, the address was not
there. */
if (!hp->h_addr_list[i]) {
/* Address not found for the host name. */
log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!",
inet_ntoa(from.sin_addr), name);
strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
goto check_ip_options;
}
/* Address was found for the host name. We accept the host name. */
} else {
/* Host name not found. Use ascii representation of the address. */
strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
log("Could not reverse map address %.100s.", name);
}
/* Address was found for the host name. We accept the host name. */
}
else
{
/* Host name not found. Use ascii representation of the address. */
strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);
log("Could not reverse map address %.100s.", name);
}
check_ip_options:
/* If IP options are supported, make sure there are none (log and disconnect
them if any are found). Basically we are worried about source routing;
it can be used to pretend you are somebody (ip-address) you are not.
That itself may be "almost acceptable" under certain circumstances,
but rhosts autentication is useless if source routing is accepted.
Notice also that if we just dropped source routing here, the other
side could use IP spoofing to do rest of the interaction and could still
bypass security. So we exit here if we detect any IP options. */
{
unsigned char options[200], *ucp;
char text[1024], *cp;
int option_size, ipproto;
struct protoent *ip;
if ((ip = getprotobyname("ip")) != NULL)
ipproto = ip->p_proto;
else
ipproto = IPPROTO_IP;
option_size = sizeof(options);
if (getsockopt(0, ipproto, IP_OPTIONS, (char *)options,
&option_size) >= 0 && option_size != 0)
{
cp = text;
/* Note: "text" buffer must be at least 3x as big as options. */
for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3)
sprintf(cp, " %2.2x", *ucp);
log("Connection from %.100s with IP options:%.800s",
inet_ntoa(from.sin_addr), text);
packet_disconnect("Connection from %.100s with IP options:%.800s",
inet_ntoa(from.sin_addr), text);
}
}
check_ip_options:
return xstrdup(name);
/* If IP options are supported, make sure there are none (log and
disconnect them if any are found). Basically we are worried
about source routing; it can be used to pretend you are
somebody (ip-address) you are not. That itself may be "almost
acceptable" under certain circumstances, but rhosts
autentication is useless if source routing is accepted. Notice
also that if we just dropped source routing here, the other
side could use IP spoofing to do rest of the interaction and
could still bypass security. So we exit here if we detect any
IP options. */
{
unsigned char options[200], *ucp;
char text[1024], *cp;
int option_size, ipproto;
struct protoent *ip;
if ((ip = getprotobyname("ip")) != NULL)
ipproto = ip->p_proto;
else
ipproto = IPPROTO_IP;
option_size = sizeof(options);
if (getsockopt(0, ipproto, IP_OPTIONS, (char *) options,
&option_size) >= 0 && option_size != 0) {
cp = text;
/* Note: "text" buffer must be at least 3x as big as options. */
for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3)
sprintf(cp, " %2.2x", *ucp);
log("Connection from %.100s with IP options:%.800s",
inet_ntoa(from.sin_addr), text);
packet_disconnect("Connection from %.100s with IP options:%.800s",
inet_ntoa(from.sin_addr), text);
}
}
return xstrdup(name);
}
static char *canonical_host_name = NULL;
static char *canonical_host_ip = NULL;
/* Return the canonical name of the host in the other side of the current
connection. The host name is cached, so it is efficient to call this
connection. The host name is cached, so it is efficient to call this
several times. */
const char *get_canonical_hostname()
const char *
get_canonical_hostname()
{
/* Check if we have previously retrieved this same name. */
if (canonical_host_name != NULL)
return canonical_host_name;
/* Check if we have previously retrieved this same name. */
if (canonical_host_name != NULL)
return canonical_host_name;
/* Get the real hostname if socket; otherwise return UNKNOWN. */
if (packet_get_connection_in() == packet_get_connection_out())
canonical_host_name = get_remote_hostname(packet_get_connection_in());
else
canonical_host_name = xstrdup("UNKNOWN");
/* Get the real hostname if socket; otherwise return UNKNOWN. */
if (packet_get_connection_in() == packet_get_connection_out())
canonical_host_name = get_remote_hostname(packet_get_connection_in());
else
canonical_host_name = xstrdup("UNKNOWN");
return canonical_host_name;
return canonical_host_name;
}
/* Returns the IP-address of the remote host as a string. The returned
string need not be freed. */
const char *get_remote_ipaddr()
const char *
get_remote_ipaddr()
{
struct sockaddr_in from;
int fromlen, socket;
struct sockaddr_in from;
int fromlen, socket;
/* Check if we have previously retrieved this same name. */
if (canonical_host_ip != NULL)
return canonical_host_ip;
/* Check if we have previously retrieved this same name. */
if (canonical_host_ip != NULL)
return canonical_host_ip;
/* If not a socket, return UNKNOWN. */
if (packet_get_connection_in() != packet_get_connection_out())
{
canonical_host_ip = xstrdup("UNKNOWN");
return canonical_host_ip;
}
/* If not a socket, return UNKNOWN. */
if (packet_get_connection_in() != packet_get_connection_out()) {
canonical_host_ip = xstrdup("UNKNOWN");
return canonical_host_ip;
}
/* Get client socket. */
socket = packet_get_connection_in();
/* Get client socket. */
socket = packet_get_connection_in();
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
/* Get the IP address in ascii. */
canonical_host_ip = xstrdup(inet_ntoa(from.sin_addr));
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0)
{
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
/* Get the IP address in ascii. */
canonical_host_ip = xstrdup(inet_ntoa(from.sin_addr));
/* Return ip address string. */
return canonical_host_ip;
/* Return ip address string. */
return canonical_host_ip;
}
/* Returns the port of the peer of the socket. */
int get_peer_port(int sock)
int
get_peer_port(int sock)
{
struct sockaddr_in from;
int fromlen;
struct sockaddr_in from;
int fromlen;
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0)
{
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
/* Return port number. */
return ntohs(from.sin_port);
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (getpeername(sock, (struct sockaddr *) & from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
/* Return port number. */
return ntohs(from.sin_port);
}
/* Returns the port number of the remote host. */
int get_remote_port()
int
get_remote_port()
{
int socket;
int socket;
/* If the connection is not a socket, return 65535. This is intentionally
chosen to be an unprivileged port number. */
if (packet_get_connection_in() != packet_get_connection_out())
return 65535;
/* If the connection is not a socket, return 65535. This is
intentionally chosen to be an unprivileged port number. */
if (packet_get_connection_in() != packet_get_connection_out())
return 65535;
/* Get client socket. */
socket = packet_get_connection_in();
/* Get client socket. */
socket = packet_get_connection_in();
/* Get and return the peer port number. */
return get_peer_port(socket);
/* Get and return the peer port number. */
return get_peer_port(socket);
}

2263
channels.c

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,40 +1,46 @@
/* RCSID("$Id: channels.h,v 1.2 1999/10/30 01:39:56 damien Exp $"); */
/* RCSID("$Id: channels.h,v 1.3 1999/11/24 13:26:22 damien Exp $"); */
#ifndef CHANNELS_H
#define CHANNELS_H
/* Definitions for channel types. */
#define SSH_CHANNEL_FREE 0 /* This channel is free (unused). */
#define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */
#define SSH_CHANNEL_PORT_LISTENER 2 /* Listening on a port. */
#define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */
#define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */
#define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */
#define SSH_CHANNEL_FREE 0 /* This channel is free
* (unused). */
#define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11
* conn. */
#define SSH_CHANNEL_PORT_LISTENER 2 /* Listening on a port. */
#define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */
#define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */
#define SSH_CHANNEL_CLOSED 5 /* waiting for close
* confirmation */
/* SSH_CHANNEL_AUTH_FD 6 authentication fd */
#define SSH_CHANNEL_AUTH_SOCKET 7 /* authentication socket */
#define SSH_CHANNEL_AUTH_SOCKET 7 /* authentication socket */
/* SSH_CHANNEL_AUTH_SOCKET_FD 8 connection to auth socket */
#define SSH_CHANNEL_X11_OPEN 9 /* reading first X11 packet */
#define SSH_CHANNEL_INPUT_DRAINING 10 /* sending remaining data to conn */
#define SSH_CHANNEL_OUTPUT_DRAINING 11 /* sending remaining data to app */
#define SSH_CHANNEL_X11_OPEN 9 /* reading first X11 packet */
#define SSH_CHANNEL_INPUT_DRAINING 10 /* sending remaining data to
* conn */
#define SSH_CHANNEL_OUTPUT_DRAINING 11 /* sending remaining data to
* app */
/* Data structure for channel data. This is iniailized in channel_allocate
and cleared in channel_free. */
typedef struct Channel
{
int type; /* channel type/state */
int self; /* my own channel identifier */
int remote_id; /* channel identifier for remote peer */
/* peer can be reached over encrypted connection, via packet-sent */
int istate; /* input from channel (state of receive half) */
int ostate; /* output to channel (state of transmit half) */
int sock; /* data socket, linked to this channel */
Buffer input; /* data read from socket, to be sent over encrypted connection */
Buffer output; /* data received over encrypted connection for send on socket */
char path[200]; /* path for unix domain sockets, or host name for forwards */
int listening_port; /* port being listened for forwards */
int host_port; /* remote port to connect for forwards */
char *remote_name; /* remote hostname */
} Channel;
typedef struct Channel {
int type; /* channel type/state */
int self; /* my own channel identifier */
int remote_id; /* channel identifier for remote peer */
/* peer can be reached over encrypted connection, via packet-sent */
int istate; /* input from channel (state of receive half) */
int ostate; /* output to channel (state of transmit half) */
int sock; /* data socket, linked to this channel */
Buffer input; /* data read from socket, to be sent over
* encrypted connection */
Buffer output; /* data received over encrypted connection for
* send on socket */
char path[200]; /* path for unix domain sockets, or host name
* for forwards */
int listening_port; /* port being listened for forwards */
int host_port; /* remote port to connect for forwards */
char *remote_name; /* remote hostname */
} Channel;
#endif

377
cipher.c
Просмотреть файл

@ -1,18 +1,18 @@
/*
cipher.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Wed Apr 19 17:41:39 1995 ylo
*/
*
* cipher.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Wed Apr 19 17:41:39 1995 ylo
*
*/
#include "includes.h"
RCSID("$Id: cipher.c,v 1.6 1999/11/16 02:37:16 damien Exp $");
RCSID("$Id: cipher.c,v 1.7 1999/11/24 13:26:22 damien Exp $");
#include "ssh.h"
#include "cipher.h"
@ -38,124 +38,124 @@ RCSID("$Id: cipher.c,v 1.6 1999/11/16 02:37:16 damien Exp $");
*/
void
SSH_3CBC_ENCRYPT(des_key_schedule ks1,
des_key_schedule ks2, des_cblock *iv2,
des_key_schedule ks3, des_cblock *iv3,
des_key_schedule ks2, des_cblock * iv2,
des_key_schedule ks3, des_cblock * iv3,
void *dest, void *src,
unsigned int len)
{
des_cblock iv1;
des_cblock iv1;
memcpy(&iv1, iv2, 8);
memcpy(&iv1, iv2, 8);
des_cbc_encrypt(src, dest, len, ks1, &iv1, DES_ENCRYPT);
memcpy(&iv1, dest + len - 8, 8);
des_cbc_encrypt(src, dest, len, ks1, &iv1, DES_ENCRYPT);
memcpy(&iv1, dest + len - 8, 8);
des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_DECRYPT);
memcpy(iv2, &iv1, 8); /* Note how iv1 == iv2 on entry and exit. */
des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_DECRYPT);
memcpy(iv2, &iv1, 8); /* Note how iv1 == iv2 on entry and exit. */
des_cbc_encrypt(dest, dest, len, ks3, iv3, DES_ENCRYPT);
memcpy(iv3, dest + len - 8, 8);
des_cbc_encrypt(dest, dest, len, ks3, iv3, DES_ENCRYPT);
memcpy(iv3, dest + len - 8, 8);
}
void
SSH_3CBC_DECRYPT(des_key_schedule ks1,
des_key_schedule ks2, des_cblock *iv2,
des_key_schedule ks3, des_cblock *iv3,
des_key_schedule ks2, des_cblock * iv2,
des_key_schedule ks3, des_cblock * iv3,
void *dest, void *src,
unsigned int len)
{
des_cblock iv1;
des_cblock iv1;
memcpy(&iv1, iv2, 8);
memcpy(&iv1, iv2, 8);
des_cbc_encrypt(src, dest, len, ks3, iv3, DES_DECRYPT);
memcpy(iv3, src + len - 8, 8);
des_cbc_encrypt(src, dest, len, ks3, iv3, DES_DECRYPT);
memcpy(iv3, src + len - 8, 8);
des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_ENCRYPT);
memcpy(iv2, dest + len - 8, 8);
des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_ENCRYPT);
memcpy(iv2, dest + len - 8, 8);
des_cbc_encrypt(dest, dest, len, ks1, &iv1, DES_DECRYPT);
/* memcpy(&iv1, iv2, 8); */ /* Note how iv1 == iv2 on entry and exit. */
des_cbc_encrypt(dest, dest, len, ks1, &iv1, DES_DECRYPT);
/* memcpy(&iv1, iv2, 8); */
/* Note how iv1 == iv2 on entry and exit. */
}
/*
* SSH uses a variation on Blowfish, all bytes must be swapped before
* and after encryption/decryption. Thus the swap_bytes stuff (yuk).
*/
static
void
static void
swap_bytes(const unsigned char *src, unsigned char *dst_, int n)
{
u_int32_t *dst = (u_int32_t *)dst_; /* dst must be properly aligned. */
union {
u_int32_t i;
char c[4];
} t;
/* dst must be properly aligned. */
u_int32_t *dst = (u_int32_t *) dst_;
union {
u_int32_t i;
char c[4];
} t;
/* Process 8 bytes every lap. */
for (n = n / 8; n > 0; n--)
{
t.c[3] = *src++;
t.c[2] = *src++;
t.c[1] = *src++;
t.c[0] = *src++;
*dst++ = t.i;
t.c[3] = *src++;
t.c[2] = *src++;
t.c[1] = *src++;
t.c[0] = *src++;
*dst++ = t.i;
}
/* Process 8 bytes every lap. */
for (n = n / 8; n > 0; n--) {
t.c[3] = *src++;
t.c[2] = *src++;
t.c[1] = *src++;
t.c[0] = *src++;
*dst++ = t.i;
t.c[3] = *src++;
t.c[2] = *src++;
t.c[1] = *src++;
t.c[0] = *src++;
*dst++ = t.i;
}
}
void (*cipher_attack_detected)(const char *fmt, ...) = fatal;
void (*cipher_attack_detected) (const char *fmt,...) = fatal;
static inline
void
static inline void
detect_cbc_attack(const unsigned char *src,
unsigned int len)
{
return;
log("CRC-32 CBC insertion attack detected");
cipher_attack_detected("CRC-32 CBC insertion attack detected");
return;
log("CRC-32 CBC insertion attack detected");
cipher_attack_detected("CRC-32 CBC insertion attack detected");
}
/* Names of all encryption algorithms. These must match the numbers defined
int cipher.h. */
static char *cipher_names[] =
{
"none",
"idea",
"des",
"3des",
"tss",
"rc4",
"blowfish"
"none",
"idea",
"des",
"3des",
"tss",
"rc4",
"blowfish"
};
/* Returns a bit mask indicating which ciphers are supported by this
implementation. The bit mask has the corresponding bit set of each
supported cipher. */
unsigned int cipher_mask()
unsigned int
cipher_mask()
{
unsigned int mask = 0;
mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
mask |= 1 << SSH_CIPHER_BLOWFISH;
return mask;
unsigned int mask = 0;
mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
mask |= 1 << SSH_CIPHER_BLOWFISH;
return mask;
}
/* Returns the name of the cipher. */
const
char *cipher_name(int cipher)
const char *
cipher_name(int cipher)
{
if (cipher < 0 || cipher >= sizeof(cipher_names) / sizeof(cipher_names[0]) ||
cipher_names[cipher] == NULL)
fatal("cipher_name: bad cipher number: %d", cipher);
return cipher_names[cipher];
if (cipher < 0 || cipher >= sizeof(cipher_names) / sizeof(cipher_names[0]) ||
cipher_names[cipher] == NULL)
fatal("cipher_name: bad cipher number: %d", cipher);
return cipher_names[cipher];
}
/* Parses the name of the cipher. Returns the number of the corresponding
@ -164,146 +164,151 @@ char *cipher_name(int cipher)
int
cipher_number(const char *name)
{
int i;
for (i = 0; i < sizeof(cipher_names) / sizeof(cipher_names[0]); i++)
if (strcmp(cipher_names[i], name) == 0 &&
(cipher_mask() & (1 << i)))
return i;
return -1;
int i;
for (i = 0; i < sizeof(cipher_names) / sizeof(cipher_names[0]); i++)
if (strcmp(cipher_names[i], name) == 0 &&
(cipher_mask() & (1 << i)))
return i;
return -1;
}
/* Selects the cipher, and keys if by computing the MD5 checksum of the
passphrase and using the resulting 16 bytes as the key. */
void cipher_set_key_string(CipherContext *context, int cipher,
const char *passphrase, int for_encryption)
void
cipher_set_key_string(CipherContext *context, int cipher,
const char *passphrase, int for_encryption)
{
MD5_CTX md;
unsigned char digest[16];
MD5_Init(&md);
MD5_Update(&md, (const unsigned char *)passphrase, strlen(passphrase));
MD5_Final(digest, &md);
MD5_CTX md;
unsigned char digest[16];
cipher_set_key(context, cipher, digest, 16, for_encryption);
memset(digest, 0, sizeof(digest));
memset(&md, 0, sizeof(md));
MD5_Init(&md);
MD5_Update(&md, (const unsigned char *) passphrase, strlen(passphrase));
MD5_Final(digest, &md);
cipher_set_key(context, cipher, digest, 16, for_encryption);
memset(digest, 0, sizeof(digest));
memset(&md, 0, sizeof(md));
}
/* Selects the cipher to use and sets the key. */
void cipher_set_key(CipherContext *context, int cipher,
const unsigned char *key, int keylen, int for_encryption)
void
cipher_set_key(CipherContext *context, int cipher,
const unsigned char *key, int keylen, int for_encryption)
{
unsigned char padded[32];
unsigned char padded[32];
/* Set cipher type. */
context->type = cipher;
/* Set cipher type. */
context->type = cipher;
/* Get 32 bytes of key data. Pad if necessary. (So that code below does
not need to worry about key size). */
memset(padded, 0, sizeof(padded));
memcpy(padded, key, keylen < sizeof(padded) ? keylen : sizeof(padded));
/* Get 32 bytes of key data. Pad if necessary. (So that code
below does not need to worry about key size). */
memset(padded, 0, sizeof(padded));
memcpy(padded, key, keylen < sizeof(padded) ? keylen : sizeof(padded));
/* Initialize the initialization vector. */
switch (cipher)
{
case SSH_CIPHER_NONE:
/* Has to stay for authfile saving of private key with no passphrase */
break;
/* Initialize the initialization vector. */
switch (cipher) {
case SSH_CIPHER_NONE:
/* Has to stay for authfile saving of private key with
no passphrase */
break;
case SSH_CIPHER_3DES:
/* Note: the least significant bit of each byte of key is parity,
and must be ignored by the implementation. 16 bytes of key are
used (first and last keys are the same). */
if (keylen < 16)
error("Key length %d is insufficient for 3DES.", keylen);
des_set_key((void*)padded, context->u.des3.key1);
des_set_key((void*)(padded + 8), context->u.des3.key2);
if (keylen <= 16)
des_set_key((void*)padded, context->u.des3.key3);
else
des_set_key((void*)(padded + 16), context->u.des3.key3);
memset(context->u.des3.iv2, 0, sizeof(context->u.des3.iv2));
memset(context->u.des3.iv3, 0, sizeof(context->u.des3.iv3));
break;
case SSH_CIPHER_3DES:
/* Note: the least significant bit of each byte of key is
parity, and must be ignored by the implementation. 16
bytes of key are used (first and last keys are the
same). */
if (keylen < 16)
error("Key length %d is insufficient for 3DES.", keylen);
des_set_key((void *) padded, context->u.des3.key1);
des_set_key((void *) (padded + 8), context->u.des3.key2);
if (keylen <= 16)
des_set_key((void *) padded, context->u.des3.key3);
else
des_set_key((void *) (padded + 16), context->u.des3.key3);
memset(context->u.des3.iv2, 0, sizeof(context->u.des3.iv2));
memset(context->u.des3.iv3, 0, sizeof(context->u.des3.iv3));
break;
case SSH_CIPHER_BLOWFISH:
BF_set_key(&context->u.bf.key, keylen, padded);
memset(context->u.bf.iv, 0, 8);
break;
case SSH_CIPHER_BLOWFISH:
BF_set_key(&context->u.bf.key, keylen, padded);
memset(context->u.bf.iv, 0, 8);
break;
default:
fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher));
}
memset(padded, 0, sizeof(padded));
default:
fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher));
}
memset(padded, 0, sizeof(padded));
}
/* Encrypts data using the cipher. */
void cipher_encrypt(CipherContext *context, unsigned char *dest,
const unsigned char *src, unsigned int len)
void
cipher_encrypt(CipherContext *context, unsigned char *dest,
const unsigned char *src, unsigned int len)
{
if ((len & 7) != 0)
fatal("cipher_encrypt: bad plaintext length %d", len);
if ((len & 7) != 0)
fatal("cipher_encrypt: bad plaintext length %d", len);
switch (context->type)
{
case SSH_CIPHER_NONE:
memcpy(dest, src, len);
break;
switch (context->type) {
case SSH_CIPHER_NONE:
memcpy(dest, src, len);
break;
case SSH_CIPHER_3DES:
SSH_3CBC_ENCRYPT(context->u.des3.key1,
context->u.des3.key2, &context->u.des3.iv2,
context->u.des3.key3, &context->u.des3.iv3,
dest, (void*)src, len);
break;
case SSH_CIPHER_3DES:
SSH_3CBC_ENCRYPT(context->u.des3.key1,
context->u.des3.key2, &context->u.des3.iv2,
context->u.des3.key3, &context->u.des3.iv3,
dest, (void *) src, len);
break;
case SSH_CIPHER_BLOWFISH:
swap_bytes(src, dest, len);
BF_cbc_encrypt(dest, dest, len,
&context->u.bf.key, context->u.bf.iv, BF_ENCRYPT);
swap_bytes(dest, dest, len);
break;
case SSH_CIPHER_BLOWFISH:
swap_bytes(src, dest, len);
BF_cbc_encrypt(dest, dest, len,
&context->u.bf.key, context->u.bf.iv,
BF_ENCRYPT);
swap_bytes(dest, dest, len);
break;
default:
fatal("cipher_encrypt: unknown cipher: %d", context->type);
}
default:
fatal("cipher_encrypt: unknown cipher: %s", cipher_name(context->type));
}
}
/* Decrypts data using the cipher. */
void cipher_decrypt(CipherContext *context, unsigned char *dest,
const unsigned char *src, unsigned int len)
void
cipher_decrypt(CipherContext *context, unsigned char *dest,
const unsigned char *src, unsigned int len)
{
if ((len & 7) != 0)
fatal("cipher_decrypt: bad ciphertext length %d", len);
if ((len & 7) != 0)
fatal("cipher_decrypt: bad ciphertext length %d", len);
switch (context->type)
{
case SSH_CIPHER_NONE:
memcpy(dest, src, len);
break;
switch (context->type) {
case SSH_CIPHER_NONE:
memcpy(dest, src, len);
break;
case SSH_CIPHER_3DES:
/* CRC-32 attack? */
SSH_3CBC_DECRYPT(context->u.des3.key1,
context->u.des3.key2, &context->u.des3.iv2,
context->u.des3.key3, &context->u.des3.iv3,
dest, (void*)src, len);
break;
case SSH_CIPHER_3DES:
/* CRC-32 attack? */
SSH_3CBC_DECRYPT(context->u.des3.key1,
context->u.des3.key2, &context->u.des3.iv2,
context->u.des3.key3, &context->u.des3.iv3,
dest, (void *) src, len);
break;
case SSH_CIPHER_BLOWFISH:
detect_cbc_attack(src, len);
swap_bytes(src, dest, len);
BF_cbc_encrypt((void*)dest, dest, len,
&context->u.bf.key, context->u.bf.iv, BF_DECRYPT);
swap_bytes(dest, dest, len);
break;
case SSH_CIPHER_BLOWFISH:
detect_cbc_attack(src, len);
swap_bytes(src, dest, len);
BF_cbc_encrypt((void *) dest, dest, len,
&context->u.bf.key, context->u.bf.iv,
BF_DECRYPT);
swap_bytes(dest, dest, len);
break;
default:
fatal("cipher_decrypt: unknown cipher: %d", context->type);
}
default:
fatal("cipher_decrypt: unknown cipher: %s", cipher_name(context->type));
}
}

Просмотреть файл

@ -1,17 +1,17 @@
/*
*
* cipher.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Wed Apr 19 16:50:42 1995 ylo
*
*/
cipher.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Wed Apr 19 16:50:42 1995 ylo
*/
/* RCSID("$Id: cipher.h,v 1.3 1999/11/16 02:37:16 damien Exp $"); */
/* RCSID("$Id: cipher.h,v 1.4 1999/11/24 13:26:22 damien Exp $"); */
#ifndef CIPHER_H
#define CIPHER_H
@ -29,32 +29,31 @@ Created: Wed Apr 19 16:50:42 1995 ylo
/* Cipher types. New types can be added, but old types should not be removed
for compatibility. The maximum allowed value is 31. */
#define SSH_CIPHER_NOT_SET -1 /* None selected (invalid number). */
#define SSH_CIPHER_NONE 0 /* no encryption */
#define SSH_CIPHER_IDEA 1 /* IDEA CFB */
#define SSH_CIPHER_DES 2 /* DES CBC */
#define SSH_CIPHER_3DES 3 /* 3DES CBC */
#define SSH_CIPHER_BROKEN_TSS 4 /* TRI's Simple Stream encryption CBC */
#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */
#define SSH_CIPHER_NOT_SET -1 /* None selected (invalid number). */
#define SSH_CIPHER_NONE 0 /* no encryption */
#define SSH_CIPHER_IDEA 1 /* IDEA CFB */
#define SSH_CIPHER_DES 2 /* DES CBC */
#define SSH_CIPHER_3DES 3 /* 3DES CBC */
#define SSH_CIPHER_BROKEN_TSS 4 /* TRI's Simple Stream encryption CBC */
#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */
#define SSH_CIPHER_BLOWFISH 6
typedef struct {
unsigned int type;
union {
struct {
des_key_schedule key1;
des_key_schedule key2;
des_cblock iv2;
des_key_schedule key3;
des_cblock iv3;
} des3;
struct {
struct bf_key_st key;
unsigned char iv[8];
} bf;
} u;
} CipherContext;
unsigned int type;
union {
struct {
des_key_schedule key1;
des_key_schedule key2;
des_cblock iv2;
des_key_schedule key3;
des_cblock iv3;
} des3;
struct {
struct bf_key_st key;
unsigned char iv[8];
} bf;
} u;
} CipherContext;
/* Returns a bit mask indicating which ciphers are supported by this
implementation. The bit mask has the corresponding bit set of each
supported cipher. */
@ -65,28 +64,32 @@ const char *cipher_name(int cipher);
/* Parses the name of the cipher. Returns the number of the corresponding
cipher, or -1 on error. */
int cipher_number(const char *name);
int cipher_number(const char *name);
/* Selects the cipher to use and sets the key. If for_encryption is true,
the key is setup for encryption; otherwise it is setup for decryption. */
void cipher_set_key(CipherContext *context, int cipher,
const unsigned char *key, int keylen, int for_encryption);
void
cipher_set_key(CipherContext * context, int cipher,
const unsigned char *key, int keylen, int for_encryption);
/* Sets key for the cipher by computing the MD5 checksum of the passphrase,
and using the resulting 16 bytes as the key. */
void cipher_set_key_string(CipherContext *context, int cipher,
const char *passphrase, int for_encryption);
void
cipher_set_key_string(CipherContext * context, int cipher,
const char *passphrase, int for_encryption);
/* Encrypts data using the cipher. */
void cipher_encrypt(CipherContext *context, unsigned char *dest,
const unsigned char *src, unsigned int len);
void
cipher_encrypt(CipherContext * context, unsigned char *dest,
const unsigned char *src, unsigned int len);
/* Decrypts data using the cipher. */
void cipher_decrypt(CipherContext *context, unsigned char *dest,
const unsigned char *src, unsigned int len);
void
cipher_decrypt(CipherContext * context, unsigned char *dest,
const unsigned char *src, unsigned int len);
/* If and CRC-32 attack is detected this function is called. Defaults
* to fatal, changed to packet_disconnect in sshd and ssh. */
extern void (*cipher_attack_detected)(const char *fmt, ...);
extern void (*cipher_attack_detected) (const char *fmt,...);
#endif /* CIPHER_H */
#endif /* CIPHER_H */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,10 +1,13 @@
#include "includes.h"
RCSID("$Id: compat.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
RCSID("$Id: compat.c,v 1.2 1999/11/24 13:26:22 damien Exp $");
#include "ssh.h"
int compat13=0;
void enable_compat13(void){
log("Enabling compatibility mode for protocol 1.3");
compat13=1;
int compat13 = 0;
void
enable_compat13(void)
{
verbose("Enabling compatibility mode for protocol 1.3");
compat13 = 1;
}

Просмотреть файл

@ -1,7 +1,7 @@
/* RCSID("$Id: compat.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
/* RCSID("$Id: compat.h,v 1.2 1999/11/24 13:26:22 damien Exp $"); */
#ifndef COMPAT_H
#define COMPAT_H
void enable_compat13(void);
void enable_compat13(void);
extern int compat13;
#endif

Просмотреть файл

@ -1,20 +1,20 @@
/*
compress.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Wed Oct 25 22:12:46 1995 ylo
Interface to packet compression for ssh.
*/
*
* compress.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Wed Oct 25 22:12:46 1995 ylo
*
* Interface to packet compression for ssh.
*
*/
#include "includes.h"
RCSID("$Id: compress.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
RCSID("$Id: compress.c,v 1.2 1999/11/24 13:26:22 damien Exp $");
#include "ssh.h"
#include "buffer.h"
@ -23,32 +23,34 @@ RCSID("$Id: compress.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
static z_stream incoming_stream;
static z_stream outgoing_stream;
/* Initializes compression; level is compression level from 1 to 9 (as in
gzip). */
/* Initializes compression; level is compression level from 1 to 9
(as in gzip). */
void buffer_compress_init(int level)
void
buffer_compress_init(int level)
{
debug("Enabling compression at level %d.", level);
if (level < 1 || level > 9)
fatal("Bad compression level %d.", level);
inflateInit(&incoming_stream);
deflateInit(&outgoing_stream, level);
debug("Enabling compression at level %d.", level);
if (level < 1 || level > 9)
fatal("Bad compression level %d.", level);
inflateInit(&incoming_stream);
deflateInit(&outgoing_stream, level);
}
/* Frees any data structures allocated for compression. */
void buffer_compress_uninit()
void
buffer_compress_uninit()
{
debug("compress outgoing: raw data %lu, compressed %lu, factor %.2f",
outgoing_stream.total_in, outgoing_stream.total_out,
outgoing_stream.total_in == 0 ? 0.0 :
(double)outgoing_stream.total_out / outgoing_stream.total_in);
debug("compress incoming: raw data %lu, compressed %lu, factor %.2f",
incoming_stream.total_out, incoming_stream.total_in,
incoming_stream.total_out == 0 ? 0.0 :
(double)incoming_stream.total_in / incoming_stream.total_out);
inflateEnd(&incoming_stream);
deflateEnd(&outgoing_stream);
debug("compress outgoing: raw data %lu, compressed %lu, factor %.2f",
outgoing_stream.total_in, outgoing_stream.total_out,
outgoing_stream.total_in == 0 ? 0.0 :
(double) outgoing_stream.total_out / outgoing_stream.total_in);
debug("compress incoming: raw data %lu, compressed %lu, factor %.2f",
incoming_stream.total_out, incoming_stream.total_in,
incoming_stream.total_out == 0 ? 0.0 :
(double) incoming_stream.total_in / incoming_stream.total_out);
inflateEnd(&incoming_stream);
deflateEnd(&outgoing_stream);
}
/* Compresses the contents of input_buffer into output_buffer. All
@ -59,50 +61,49 @@ void buffer_compress_uninit()
form a single compression stream) by the receiver. This appends
the compressed data to the output buffer. */
void buffer_compress(Buffer *input_buffer, Buffer *output_buffer)
void
buffer_compress(Buffer * input_buffer, Buffer * output_buffer)
{
char buf[4096];
int status;
char buf[4096];
int status;
/* This case is not handled below. */
if (buffer_len(input_buffer) == 0)
return;
/* This case is not handled below. */
if (buffer_len(input_buffer) == 0)
return;
/* Input is the contents of the input buffer. */
outgoing_stream.next_in = buffer_ptr(input_buffer);
outgoing_stream.avail_in = buffer_len(input_buffer);
/* Input is the contents of the input buffer. */
outgoing_stream.next_in = buffer_ptr(input_buffer);
outgoing_stream.avail_in = buffer_len(input_buffer);
/* Loop compressing until deflate() returns with avail_out != 0. */
do
{
/* Set up fixed-size output buffer. */
outgoing_stream.next_out = buf;
outgoing_stream.avail_out = sizeof(buf);
/* Loop compressing until deflate() returns with avail_out != 0. */
do {
/* Set up fixed-size output buffer. */
outgoing_stream.next_out = buf;
outgoing_stream.avail_out = sizeof(buf);
/* Compress as much data into the buffer as possible. */
status = deflate(&outgoing_stream, Z_PARTIAL_FLUSH);
switch (status)
{
case Z_OK:
/* Append compressed data to output_buffer. */
buffer_append(output_buffer, buf,
sizeof(buf) - outgoing_stream.avail_out);
break;
case Z_STREAM_END:
fatal("buffer_compress: deflate returned Z_STREAM_END");
/*NOTREACHED*/
case Z_STREAM_ERROR:
fatal("buffer_compress: deflate returned Z_STREAM_ERROR");
/*NOTREACHED*/
case Z_BUF_ERROR:
fatal("buffer_compress: deflate returned Z_BUF_ERROR");
/*NOTREACHED*/
default:
fatal("buffer_compress: deflate returned %d", status);
/*NOTREACHED*/
/* Compress as much data into the buffer as possible. */
status = deflate(&outgoing_stream, Z_PARTIAL_FLUSH);
switch (status) {
case Z_OK:
/* Append compressed data to output_buffer. */
buffer_append(output_buffer, buf,
sizeof(buf) - outgoing_stream.avail_out);
break;
case Z_STREAM_END:
fatal("buffer_compress: deflate returned Z_STREAM_END");
/* NOTREACHED */
case Z_STREAM_ERROR:
fatal("buffer_compress: deflate returned Z_STREAM_ERROR");
/* NOTREACHED */
case Z_BUF_ERROR:
fatal("buffer_compress: deflate returned Z_BUF_ERROR");
/* NOTREACHED */
default:
fatal("buffer_compress: deflate returned %d", status);
/* NOTREACHED */
}
}
}
while (outgoing_stream.avail_out == 0);
while (outgoing_stream.avail_out == 0);
}
/* Uncompresses the contents of input_buffer into output_buffer. All
@ -113,48 +114,46 @@ void buffer_compress(Buffer *input_buffer, Buffer *output_buffer)
same order that buffers compressed with that. This appends the
uncompressed data to the output buffer. */
void buffer_uncompress(Buffer *input_buffer, Buffer *output_buffer)
void
buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer)
{
char buf[4096];
int status;
char buf[4096];
int status;
incoming_stream.next_in = buffer_ptr(input_buffer);
incoming_stream.avail_in = buffer_len(input_buffer);
incoming_stream.next_in = buffer_ptr(input_buffer);
incoming_stream.avail_in = buffer_len(input_buffer);
incoming_stream.next_out = buf;
incoming_stream.avail_out = sizeof(buf);
incoming_stream.next_out = buf;
incoming_stream.avail_out = sizeof(buf);
for (;;)
{
status = inflate(&incoming_stream, Z_PARTIAL_FLUSH);
switch (status)
{
case Z_OK:
buffer_append(output_buffer, buf,
sizeof(buf) - incoming_stream.avail_out);
incoming_stream.next_out = buf;
incoming_stream.avail_out = sizeof(buf);
break;
case Z_STREAM_END:
fatal("buffer_uncompress: inflate returned Z_STREAM_END");
/*NOTREACHED*/
case Z_DATA_ERROR:
fatal("buffer_uncompress: inflate returned Z_DATA_ERROR");
/*NOTREACHED*/
case Z_STREAM_ERROR:
fatal("buffer_uncompress: inflate returned Z_STREAM_ERROR");
/*NOTREACHED*/
case Z_BUF_ERROR:
/* Comments in zlib.h say that we should keep calling inflate()
until we get an error. This appears to be the error that we
get. */
return;
case Z_MEM_ERROR:
fatal("buffer_uncompress: inflate returned Z_MEM_ERROR");
/*NOTREACHED*/
default:
fatal("buffer_uncompress: inflate returned %d", status);
for (;;) {
status = inflate(&incoming_stream, Z_PARTIAL_FLUSH);
switch (status) {
case Z_OK:
buffer_append(output_buffer, buf,
sizeof(buf) - incoming_stream.avail_out);
incoming_stream.next_out = buf;
incoming_stream.avail_out = sizeof(buf);
break;
case Z_STREAM_END:
fatal("buffer_uncompress: inflate returned Z_STREAM_END");
/* NOTREACHED */
case Z_DATA_ERROR:
fatal("buffer_uncompress: inflate returned Z_DATA_ERROR");
/* NOTREACHED */
case Z_STREAM_ERROR:
fatal("buffer_uncompress: inflate returned Z_STREAM_ERROR");
/* NOTREACHED */
case Z_BUF_ERROR:
/* Comments in zlib.h say that we should keep
calling inflate() until we get an error. This
appears to be the error that we get. */
return;
case Z_MEM_ERROR:
fatal("buffer_uncompress: inflate returned Z_MEM_ERROR");
/* NOTREACHED */
default:
fatal("buffer_uncompress: inflate returned %d", status);
}
}
}
}

Просмотреть файл

@ -1,29 +1,29 @@
/*
*
* compress.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Wed Oct 25 22:12:46 1995 ylo
*
* Interface to packet compression for ssh.
*
*/
compress.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Wed Oct 25 22:12:46 1995 ylo
Interface to packet compression for ssh.
*/
/* RCSID("$Id: compress.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
/* RCSID("$Id: compress.h,v 1.2 1999/11/24 13:26:22 damien Exp $"); */
#ifndef COMPRESS_H
#define COMPRESS_H
/* Initializes compression; level is compression level from 1 to 9 (as in
gzip). */
void buffer_compress_init(int level);
void buffer_compress_init(int level);
/* Frees any data structures allocated by buffer_compress_init. */
void buffer_compress_uninit();
void buffer_compress_uninit();
/* Compresses the contents of input_buffer into output_buffer. All
packets compressed using this function will form a single
@ -32,7 +32,7 @@ void buffer_compress_uninit();
independently (but in the appropriate order since they together
form a single compression stream) by the receiver. This appends
the compressed data to the output buffer. */
void buffer_compress(Buffer *input_buffer, Buffer *output_buffer);
void buffer_compress(Buffer * input_buffer, Buffer * output_buffer);
/* Uncompresses the contents of input_buffer into output_buffer. All
packets uncompressed using this function will form a single
@ -41,6 +41,6 @@ void buffer_compress(Buffer *input_buffer, Buffer *output_buffer);
same size units that the buffer_compress was called, and in the
same order that buffers compressed with that. This appends the
uncompressed data to the output buffer. */
void buffer_uncompress(Buffer *input_buffer, Buffer *output_buffer);
void buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer);
#endif /* COMPRESS_H */
#endif /* COMPRESS_H */

Просмотреть файл

@ -55,7 +55,7 @@ AC_CHECK_LIB(dl, dlopen, , )
AC_CHECK_LIB(pam, pam_authenticate, , )
dnl Checks for header files.
AC_CHECK_HEADERS(pty.h endian.h paths.h lastlog.h shadow.h netgroup.h maillock.h utmp.h sys/select.h sys/time.h)
AC_CHECK_HEADERS(pty.h endian.h paths.h lastlog.h shadow.h netgroup.h maillock.h utmp.h util.h sys/select.h sys/time.h)
dnl Checks for library functions.
AC_CHECK_FUNCS(openpty strlcpy strlcat mkdtemp arc4random setproctitle setlogin setenv)

139
crc32.c
Просмотреть файл

@ -1,9 +1,12 @@
/* The implementation here was originally done by Gary S. Brown. I have
borrowed the tables directly, and made some minor changes to the
crc32-function (including changing the interface). //ylo */
/*
* The implementation here was originally done by Gary S. Brown.
* I have borrowed the tables directly, and made some minor changes
* to the crc32-function (including changing the interface).
* //ylo
*/
#include "includes.h"
RCSID("$Id: crc32.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
RCSID("$Id: crc32.c,v 1.2 1999/11/24 13:26:22 damien Exp $");
#include "crc32.h"
@ -48,73 +51,71 @@ RCSID("$Id: crc32.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
/* -------------------------------------------------------------------- */
static unsigned int crc32_tab[] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
/* Return a 32-bit CRC of the contents of the buffer. */
unsigned int crc32(const unsigned char *s, unsigned int len)
unsigned int
crc32(const unsigned char *s, unsigned int len)
{
unsigned int i;
unsigned int crc32val;
crc32val = 0;
for (i = 0; i < len; i ++)
{
crc32val =
crc32_tab[(crc32val ^ s[i]) & 0xff] ^
(crc32val >> 8);
}
return crc32val;
unsigned int i;
unsigned int crc32val;
crc32val = 0;
for (i = 0; i < len; i ++) {
crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8);
}
return crc32val;
}

30
crc32.h
Просмотреть файл

@ -1,19 +1,19 @@
/*
*
* crc32.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1992 Tatu Ylonen, Espoo, Finland
* All rights reserved
*
* Created: Tue Feb 11 14:37:27 1992 ylo
*
* Functions for computing 32-bit CRC.
*
*/
crc32.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1992 Tatu Ylonen, Espoo, Finland
All rights reserved
Created: Tue Feb 11 14:37:27 1992 ylo
Functions for computing 32-bit CRC.
*/
/* RCSID("$Id: crc32.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
/* RCSID("$Id: crc32.h,v 1.2 1999/11/24 13:26:22 damien Exp $"); */
#ifndef CRC32_H
#define CRC32_H
@ -22,4 +22,4 @@ Functions for computing 32-bit CRC.
CRC. The polynomial used is 0xedb88320. */
unsigned int crc32(const unsigned char *buf, unsigned int len);
#endif /* CRC32_H */
#endif /* CRC32_H */

Просмотреть файл

@ -1,5 +1,5 @@
/*
* $Id: deattack.c,v 1.2 1999/11/08 05:15:55 damien Exp $
* $Id: deattack.c,v 1.3 1999/11/24 13:26:22 damien Exp $
* Cryptographic attack detector for ssh - source code
*
* Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
@ -15,7 +15,8 @@
* SOFTWARE.
*
* Ariel Futoransky <futo@core-sdi.com>
* <http://www.core-sdi.com> */
* <http://www.core-sdi.com>
*/
#include "includes.h"
#include "deattack.h"
@ -25,157 +26,130 @@
#include "xmalloc.h"
/* SSH Constants */
#define SSH_MAXBLOCKS (32 * 1024)
#define SSH_BLOCKSIZE (8)
#define SSH_MAXBLOCKS (32 * 1024)
#define SSH_BLOCKSIZE (8)
/* Hashing constants */
#define HASH_MINSIZE (8 * 1024)
#define HASH_ENTRYSIZE (2)
#define HASH_FACTOR(x) ((x)*3/2)
#define HASH_UNUSEDCHAR (0xff)
#define HASH_UNUSED (0xffff)
#define HASH_IV (0xfffe)
#define HASH_MINSIZE (8 * 1024)
#define HASH_ENTRYSIZE (2)
#define HASH_FACTOR(x) ((x)*3/2)
#define HASH_UNUSEDCHAR (0xff)
#define HASH_UNUSED (0xffff)
#define HASH_IV (0xfffe)
#define HASH_MINBLOCKS (7*SSH_BLOCKSIZE)
#define HASH_MINBLOCKS (7*SSH_BLOCKSIZE)
/* Hash function (Input keys are cipher results) */
#define HASH(x) GET_32BIT(x)
#define HASH(x) GET_32BIT(x)
#define CMP(a,b) (memcmp(a, b, SSH_BLOCKSIZE))
#define CMP(a,b) (memcmp(a, b, SSH_BLOCKSIZE))
void
crc_update(u_int32_t * a, u_int32_t b)
crc_update(u_int32_t *a, u_int32_t b)
{
b ^= *a;
*a = crc32((unsigned char *) &b, sizeof(b));
b ^= *a;
*a = crc32((unsigned char *) &b, sizeof(b));
}
/*
check_crc
detects if a block is used in a particular pattern
*/
/* detect if a block is used in a particular pattern */
int
check_crc(unsigned char *S, unsigned char *buf, u_int32_t len, unsigned char *IV)
check_crc(unsigned char *S, unsigned char *buf, u_int32_t len,
unsigned char *IV)
{
u_int32_t crc;
unsigned char *c;
u_int32_t crc;
unsigned char *c;
crc = 0;
if (IV && !CMP(S, IV))
{
crc_update(&crc, 1);
crc_update(&crc, 0);
}
for (c = buf; c < buf + len; c += SSH_BLOCKSIZE)
{
if (!CMP(S, c))
{
crc_update(&crc, 1);
crc_update(&crc, 0);
} else
{
crc_update(&crc, 0);
crc_update(&crc, 0);
}
}
return (crc == 0);
crc = 0;
if (IV && !CMP(S, IV)) {
crc_update(&crc, 1);
crc_update(&crc, 0);
}
for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
if (!CMP(S, c)) {
crc_update(&crc, 1);
crc_update(&crc, 0);
} else {
crc_update(&crc, 0);
crc_update(&crc, 0);
}
}
return (crc == 0);
}
/*
detect_attack
Detects a crc32 compensation attack on a packet
*/
/* Detect a crc32 compensation attack on a packet */
int
detect_attack(unsigned char *buf, u_int32_t len, unsigned char *IV)
{
static u_int16_t *h = (u_int16_t *) NULL;
static u_int16_t n = HASH_MINSIZE / HASH_ENTRYSIZE;
register u_int32_t i, j;
u_int32_t l;
register unsigned char *c;
unsigned char *d;
static u_int16_t *h = (u_int16_t *) NULL;
static u_int16_t n = HASH_MINSIZE / HASH_ENTRYSIZE;
register u_int32_t i, j;
u_int32_t l;
register unsigned char *c;
unsigned char *d;
if (len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) ||
len % SSH_BLOCKSIZE != 0) {
fatal("detect_attack: bad length %d", len);
}
for (l = n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2);
if (h == NULL)
{
debug("Installing crc compensation attack detector.");
n = l;
h = (u_int16_t *) xmalloc(n * HASH_ENTRYSIZE);
} else
{
if (l > n)
{
n = l;
h = (u_int16_t *) xrealloc(h, n * HASH_ENTRYSIZE);
}
}
if (len <= HASH_MINBLOCKS)
{
for (c = buf; c < buf + len; c += SSH_BLOCKSIZE)
{
if (IV && (!CMP(c, IV)))
{
if ((check_crc(c, buf, len, IV)))
return (DEATTACK_DETECTED);
else
break;
}
for (d = buf; d < c; d += SSH_BLOCKSIZE)
{
if (!CMP(c, d))
{
if ((check_crc(c, buf, len, IV)))
return (DEATTACK_DETECTED);
else
break;
if (len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) ||
len % SSH_BLOCKSIZE != 0) {
fatal("detect_attack: bad length %d", len);
}
}
}
return (DEATTACK_OK);
}
memset(h, HASH_UNUSEDCHAR, n * HASH_ENTRYSIZE);
for (l = n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2)
;
if (IV)
h[HASH(IV) & (n - 1)] = HASH_IV;
for (c = buf, j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++)
{
for (i = HASH(c) & (n - 1); h[i] != HASH_UNUSED;
i = (i + 1) & (n - 1))
{
if (h[i] == HASH_IV)
{
if (!CMP(c, IV))
{
if (check_crc(c, buf, len, IV))
return (DEATTACK_DETECTED);
else
break;
if (h == NULL) {
debug("Installing crc compensation attack detector.");
n = l;
h = (u_int16_t *) xmalloc(n * HASH_ENTRYSIZE);
} else {
if (l > n) {
n = l;
h = (u_int16_t *) xrealloc(h, n * HASH_ENTRYSIZE);
}
}
} else if (!CMP(c, buf + h[i] * SSH_BLOCKSIZE))
{
if (check_crc(c, buf, len, IV))
return (DEATTACK_DETECTED);
else
break;
}
}
h[i] = j;
}
return (DEATTACK_OK);
if (len <= HASH_MINBLOCKS) {
for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
if (IV && (!CMP(c, IV))) {
if ((check_crc(c, buf, len, IV)))
return (DEATTACK_DETECTED);
else
break;
}
for (d = buf; d < c; d += SSH_BLOCKSIZE) {
if (!CMP(c, d)) {
if ((check_crc(c, buf, len, IV)))
return (DEATTACK_DETECTED);
else
break;
}
}
}
return (DEATTACK_OK);
}
memset(h, HASH_UNUSEDCHAR, n * HASH_ENTRYSIZE);
if (IV)
h[HASH(IV) & (n - 1)] = HASH_IV;
for (c = buf, j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) {
for (i = HASH(c) & (n - 1); h[i] != HASH_UNUSED;
i = (i + 1) & (n - 1)) {
if (h[i] == HASH_IV) {
if (!CMP(c, IV)) {
if (check_crc(c, buf, len, IV))
return (DEATTACK_DETECTED);
else
break;
}
} else if (!CMP(c, buf + h[i] * SSH_BLOCKSIZE)) {
if (check_crc(c, buf, len, IV))
return (DEATTACK_DETECTED);
else
break;
}
}
h[i] = j;
}
return (DEATTACK_OK);
}

Просмотреть файл

@ -1,4 +1,4 @@
/* $Id: deattack.h,v 1.1 1999/10/27 03:42:44 damien Exp $
/*
* Cryptographic attack detector for ssh - Header file
*
* Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
@ -14,7 +14,8 @@
* SOFTWARE.
*
* Ariel Futoransky <futo@core-sdi.com>
* <http://www.core-sdi.com> */
* <http://www.core-sdi.com>
*/
#ifndef _DEATTACK_H
#define _DEATTACK_H
@ -23,5 +24,5 @@
#define DEATTACK_OK 0
#define DEATTACK_DETECTED 1
int detect_attack(unsigned char *buf, u_int32_t len, unsigned char IV[8]);
int detect_attack(unsigned char *buf, u_int32_t len, unsigned char IV[8]);
#endif

Просмотреть файл

@ -1,5 +1,5 @@
#include "includes.h"
RCSID("$Id: fingerprint.c,v 1.1 1999/11/17 06:29:08 damien Exp $");
RCSID("$Id: fingerprint.c,v 1.3 1999/11/24 00:26:01 deraadt Exp $");
#include "ssh.h"
#include "xmalloc.h"
@ -13,17 +13,18 @@ RCSID("$Id: fingerprint.c,v 1.1 1999/11/17 06:29:08 damien Exp $");
#define FPRINT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
/* Generate key fingerprint in ascii format.
Based on ideas and code from Bjoern Groenvall <bg@sics.se> */
/*
* Generate key fingerprint in ascii format.
* Based on ideas and code from Bjoern Groenvall <bg@sics.se>
*/
char *
fingerprint(BIGNUM *e, BIGNUM *n)
{
static char retval[80];
MD5_CTX md;
unsigned char d[16];
char *buf;
int nlen, elen;
static char retval[80];
MD5_CTX md;
unsigned char d[16];
char *buf;
int nlen, elen;
nlen = BN_num_bytes(n);
elen = BN_num_bytes(e);
@ -37,8 +38,8 @@ fingerprint(BIGNUM *e, BIGNUM *n)
MD5_Update(&md, buf, nlen + elen);
MD5_Final(d, &md);
snprintf(retval, sizeof(retval), FPRINT,
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
memset(buf, 0, nlen + elen);
xfree(buf);
return retval;

Просмотреть файл

@ -1,6 +1,6 @@
/* RCSID("$Id: fingerprint.h,v 1.1 1999/11/16 22:49:28 markus Exp $"); */
/* RCSID("$Id: fingerprint.h,v 1.2 1999/11/24 00:26:02 deraadt Exp $"); */
#ifndef FINGERPRINT_H
#define FINGERPRINT_H
char * fingerprint(BIGNUM *e, BIGNUM *n);
char *fingerprint(BIGNUM * e, BIGNUM * n);
#endif

Просмотреть файл

@ -1,19 +1,19 @@
/*
*
* getput.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Wed Jun 28 22:36:30 1995 ylo
*
* Macros for storing and retrieving data in msb first and lsb first order.
*
*/
getput.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Wed Jun 28 22:36:30 1995 ylo
Macros for storing and retrieving data in msb first and lsb first order.
*/
/* RCSID("$Id: getput.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
/* RCSID("$Id: getput.h,v 1.2 1999/11/24 13:26:22 damien Exp $"); */
#ifndef GETPUT_H
#define GETPUT_H
@ -60,5 +60,4 @@ Macros for storing and retrieving data in msb first and lsb first order.
(cp)[0] = (value); \
(cp)[1] = (value) >> 8; } while (0)
#endif /* GETPUT_H */
#endif /* GETPUT_H */

Просмотреть файл

@ -1,20 +1,20 @@
/*
hostfile.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Thu Jun 29 07:10:56 1995 ylo
Functions for manipulating the known hosts files.
*/
*
* hostfile.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Thu Jun 29 07:10:56 1995 ylo
*
* Functions for manipulating the known hosts files.
*
*/
#include "includes.h"
RCSID("$Id: hostfile.c,v 1.4 1999/11/17 06:29:08 damien Exp $");
RCSID("$Id: hostfile.c,v 1.5 1999/11/24 13:26:22 damien Exp $");
#include "packet.h"
#include "ssh.h"
@ -26,140 +26,136 @@ RCSID("$Id: hostfile.c,v 1.4 1999/11/17 06:29:08 damien Exp $");
modify the buffer containing the number. */
int
auth_rsa_read_bignum(char **cpp, BIGNUM *value)
auth_rsa_read_bignum(char **cpp, BIGNUM * value)
{
char *cp = *cpp;
int len, old;
char *cp = *cpp;
int len, old;
/* Skip any leading whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
/* Skip any leading whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++);
/* Check that it begins with a hex digit. */
if (*cp < '0' || *cp > '9')
return 0;
/* Check that it begins with a hex digit. */
if (*cp < '0' || *cp > '9')
return 0;
/* Save starting position. */
*cpp = cp;
/* Save starting position. */
*cpp = cp;
/* Move forward until all hex digits skipped. */
for (; *cp >= '0' && *cp <= '9'; cp++)
;
/* Move forward until all hex digits skipped. */
for (; *cp >= '0' && *cp <= '9'; cp++);
/* Compute the length of the hex number. */
len = cp - *cpp;
/* Compute the length of the hex number. */
len = cp - *cpp;
/* Save the old terminating character, and replace it by \0. */
old = *cp;
*cp = 0;
/* Save the old terminating character, and replace it by \0. */
old = *cp;
*cp = 0;
/* Parse the number. */
if (BN_dec2bn(&value, *cpp) == 0)
return 0;
/* Restore old terminating character. */
*cp = old;
/* Parse the number. */
if (BN_dec2bn(&value, *cpp) == 0)
return 0;
/* Move beyond the number and return success. */
*cpp = cp;
return 1;
/* Restore old terminating character. */
*cp = old;
/* Move beyond the number and return success. */
*cpp = cp;
return 1;
}
/* Parses an RSA key (number of bits, e, n) from a string. Moves the pointer
over the key. Skips any whitespace at the beginning and at end. */
int
auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM *e, BIGNUM *n)
auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
{
unsigned int bits;
char *cp;
unsigned int bits;
char *cp;
/* Skip leading whitespace. */
for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
;
/* Skip leading whitespace. */
for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++);
/* Get number of bits. */
if (*cp < '0' || *cp > '9')
return 0; /* Bad bit count... */
for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
bits = 10 * bits + *cp - '0';
/* Get number of bits. */
if (*cp < '0' || *cp > '9')
return 0; /* Bad bit count... */
for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
bits = 10 * bits + *cp - '0';
/* Get public exponent. */
if (!auth_rsa_read_bignum(&cp, e))
return 0;
/* Get public exponent. */
if (!auth_rsa_read_bignum(&cp, e))
return 0;
/* Get public modulus. */
if (!auth_rsa_read_bignum(&cp, n))
return 0;
/* Get public modulus. */
if (!auth_rsa_read_bignum(&cp, n))
return 0;
/* Skip trailing whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
/* Return results. */
*cpp = cp;
*bitsp = bits;
return 1;
/* Skip trailing whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++);
/* Return results. */
*cpp = cp;
*bitsp = bits;
return 1;
}
/* Tries to match the host name (which must be in all lowercase) against the
comma-separated sequence of subpatterns (each possibly preceded by ! to
comma-separated sequence of subpatterns (each possibly preceded by ! to
indicate negation). Returns true if there is a positive match; zero
otherwise. */
int
match_hostname(const char *host, const char *pattern, unsigned int len)
{
char sub[1024];
int negated;
int got_positive;
unsigned int i, subi;
char sub[1024];
int negated;
int got_positive;
unsigned int i, subi;
got_positive = 0;
for (i = 0; i < len;)
{
/* Check if the subpattern is negated. */
if (pattern[i] == '!')
{
negated = 1;
i++;
got_positive = 0;
for (i = 0; i < len;) {
/* Check if the subpattern is negated. */
if (pattern[i] == '!') {
negated = 1;
i++;
} else
negated = 0;
/* Extract the subpattern up to a comma or end. Convert
the subpattern to lowercase. */
for (subi = 0;
i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';
subi++, i++)
sub[subi] = isupper(pattern[i]) ? tolower(pattern[i]) : pattern[i];
/* If subpattern too long, return failure (no match). */
if (subi >= sizeof(sub) - 1)
return 0;
/* If the subpattern was terminated by a comma, skip the
comma. */
if (i < len && pattern[i] == ',')
i++;
/* Null-terminate the subpattern. */
sub[subi] = '\0';
/* Try to match the subpattern against the host name. */
if (match_pattern(host, sub)) {
if (negated)
return 0; /* Fail if host matches
any negated subpattern. */
else
got_positive = 1;
}
}
else
negated = 0;
/* Extract the subpattern up to a comma or end. Convert the subpattern
to lowercase. */
for (subi = 0;
i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';
subi++, i++)
sub[subi] = isupper(pattern[i]) ? tolower(pattern[i]) : pattern[i];
/* If subpattern too long, return failure (no match). */
if (subi >= sizeof(sub) - 1)
return 0;
/* If the subpattern was terminated by a comma, skip the comma. */
if (i < len && pattern[i] == ',')
i++;
/* Null-terminate the subpattern. */
sub[subi] = '\0';
/* Try to match the subpattern against the host name. */
if (match_pattern(host, sub)) {
if (negated)
return 0; /* Fail if host matches any negated subpattern. */
else
got_positive = 1;
}
}
/* Return success if got a positive match. If there was a negative match,
we have already returned zero and never get here. */
return got_positive;
/* Return success if got a positive match. If there was a
negative match, we have already returned zero and never get
here. */
return got_positive;
}
/* Checks whether the given host (which must be in all lowercase) is
/* Checks whether the given host (which must be in all lowercase) is
already in the list of our known hosts.
Returns HOST_OK if the host is known and has the specified key,
HOST_NEW if the host is not known, and HOST_CHANGED if the host is known
@ -167,87 +163,82 @@ match_hostname(const char *host, const char *pattern, unsigned int len)
HostStatus
check_host_in_hostfile(const char *filename, const char *host,
BIGNUM *e, BIGNUM *n, BIGNUM *ke, BIGNUM *kn)
BIGNUM * e, BIGNUM * n, BIGNUM * ke, BIGNUM * kn)
{
FILE *f;
char line[8192];
int linenum = 0;
unsigned int bits, kbits, hostlen;
char *cp, *cp2;
HostStatus end_return;
FILE *f;
char line[8192];
int linenum = 0;
unsigned int bits, kbits, hostlen;
char *cp, *cp2;
HostStatus end_return;
/* Open the file containing the list of known hosts. */
f = fopen(filename, "r");
if (!f)
return HOST_NEW;
/* Open the file containing the list of known hosts. */
f = fopen(filename, "r");
if (!f)
return HOST_NEW;
/* Cache the length of the host name. */
hostlen = strlen(host);
/* Return value when the loop terminates. This is set to HOST_CHANGED if
we have seen a different key for the host and have not found the proper
one. */
end_return = HOST_NEW;
/* Cache the length of the host name. */
hostlen = strlen(host);
/* size of modulus 'n' */
bits = BN_num_bits(n);
/* Return value when the loop terminates. This is set to
HOST_CHANGED if we have seen a different key for the host and
have not found the proper one. */
end_return = HOST_NEW;
/* Go trough the file. */
while (fgets(line, sizeof(line), f))
{
cp = line;
linenum++;
/* size of modulus 'n' */
bits = BN_num_bits(n);
/* Skip any leading whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
/* Go trough the file. */
while (fgets(line, sizeof(line), f)) {
cp = line;
linenum++;
/* Ignore comment lines and empty lines. */
if (!*cp || *cp == '#' || *cp == '\n')
continue;
/* Find the end of the host name portion. */
for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++)
;
/* Skip any leading whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++);
/* Check if the host name matches. */
if (!match_hostname(host, cp, (unsigned int)(cp2 - cp)))
continue;
/* Got a match. Skip host name. */
cp = cp2;
/* Extract the key from the line. This will skip any leading
whitespace. Ignore badly formatted lines. */
if (!auth_rsa_read_key(&cp, &kbits, ke, kn))
continue;
/* Ignore comment lines and empty lines. */
if (!*cp || *cp == '#' || *cp == '\n')
continue;
if (kbits != BN_num_bits(kn)) {
error("Warning: error in %s, line %d: keysize mismatch for host %s: "
"actual size %d vs. announced %d.",
filename, linenum, host, BN_num_bits(kn), kbits);
error("Warning: replace %d with %d in %s, line %d.",
kbits, BN_num_bits(kn), filename, linenum);
}
/* Find the end of the host name portion. */
for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++);
/* Check if the current key is the same as the given key. */
if (BN_cmp(ke, e) == 0 && BN_cmp(kn, n) == 0)
{
/* Ok, they match. */
fclose(f);
return HOST_OK;
/* Check if the host name matches. */
if (!match_hostname(host, cp, (unsigned int) (cp2 - cp)))
continue;
/* Got a match. Skip host name. */
cp = cp2;
/* Extract the key from the line. This will skip any
leading whitespace. Ignore badly formatted lines. */
if (!auth_rsa_read_key(&cp, &kbits, ke, kn))
continue;
if (kbits != BN_num_bits(kn)) {
error("Warning: error in %s, line %d: keysize mismatch for host %s: "
"actual size %d vs. announced %d.",
filename, linenum, host, BN_num_bits(kn), kbits);
error("Warning: replace %d with %d in %s, line %d.",
kbits, BN_num_bits(kn), filename, linenum);
}
/* Check if the current key is the same as the given key. */
if (BN_cmp(ke, e) == 0 && BN_cmp(kn, n) == 0) {
/* Ok, they match. */
fclose(f);
return HOST_OK;
}
/* They do not match. We will continue to go through the
file; however, we note that we will not return that it
is new. */
end_return = HOST_CHANGED;
}
/* They do not match. We will continue to go through the file; however,
we note that we will not return that it is new. */
end_return = HOST_CHANGED;
}
/* Clear variables and close the file. */
fclose(f);
/* Clear variables and close the file. */
fclose(f);
/* Return either HOST_NEW or HOST_CHANGED, depending on whether we saw a
different key for the host. */
return end_return;
/* Return either HOST_NEW or HOST_CHANGED, depending on whether we
saw a different key for the host. */
return end_return;
}
/* Appends an entry to the host file. Returns false if the entry
@ -255,40 +246,40 @@ check_host_in_hostfile(const char *filename, const char *host,
int
add_host_to_hostfile(const char *filename, const char *host,
BIGNUM *e, BIGNUM *n)
BIGNUM * e, BIGNUM * n)
{
FILE *f;
char *buf;
unsigned int bits;
/* Open the file for appending. */
f = fopen(filename, "a");
if (!f)
return 0;
FILE *f;
char *buf;
unsigned int bits;
/* size of modulus 'n' */
bits = BN_num_bits(n);
/* Open the file for appending. */
f = fopen(filename, "a");
if (!f)
return 0;
/* Print the host name and key to the file. */
fprintf(f, "%s %u ", host, bits);
buf = BN_bn2dec(e);
if (buf == NULL) {
error("add_host_to_hostfile: BN_bn2dec(e) failed");
fclose(f);
return 0;
}
fprintf(f, "%s ", buf);
free (buf);
buf = BN_bn2dec(n);
if (buf == NULL) {
error("add_host_to_hostfile: BN_bn2dec(n) failed");
fclose(f);
return 0;
}
fprintf(f, "%s\n", buf);
free (buf);
/* size of modulus 'n' */
bits = BN_num_bits(n);
/* Close the file. */
fclose(f);
return 1;
/* Print the host name and key to the file. */
fprintf(f, "%s %u ", host, bits);
buf = BN_bn2dec(e);
if (buf == NULL) {
error("add_host_to_hostfile: BN_bn2dec(e) failed");
fclose(f);
return 0;
}
fprintf(f, "%s ", buf);
free(buf);
buf = BN_bn2dec(n);
if (buf == NULL) {
error("add_host_to_hostfile: BN_bn2dec(n) failed");
fclose(f);
return 0;
}
fprintf(f, "%s\n", buf);
free(buf);
/* Close the file. */
fclose(f);
return 1;
}

Просмотреть файл

@ -1,17 +1,17 @@
/*
includes.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Thu Mar 23 16:29:37 1995 ylo
This file includes most of the needed system headers.
*/
*
* includes.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Thu Mar 23 16:29:37 1995 ylo
*
* This file includes most of the needed system headers.
*
*/
#ifndef INCLUDES_H
#define INCLUDES_H
@ -91,4 +91,4 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
client program. Socketpairs do not seem to work on all systems. */
#define USE_PIPES 1
#endif /* INCLUDES_H */
#endif /* INCLUDES_H */

Просмотреть файл

@ -1,21 +1,21 @@
/*
log-client.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Mon Mar 20 21:13:40 1995 ylo
Client-side versions of debug(), log(), etc. These print to stderr.
This is a stripped down version of log-server.c.
*/
*
* log-client.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Mon Mar 20 21:13:40 1995 ylo
*
* Client-side versions of debug(), log(), etc. These print to stderr.
* This is a stripped down version of log-server.c.
*
*/
#include "includes.h"
RCSID("$Id: log-client.c,v 1.2 1999/11/11 06:57:39 damien Exp $");
RCSID("$Id: log-client.c,v 1.3 1999/11/24 13:26:22 damien Exp $");
#include "xmalloc.h"
#include "ssh.h"
@ -23,27 +23,26 @@ RCSID("$Id: log-client.c,v 1.2 1999/11/11 06:57:39 damien Exp $");
static LogLevel log_level = SYSLOG_LEVEL_INFO;
/* Initialize the log.
av0 program name (should be argv[0])
level logging level
*/
* av0 program name (should be argv[0])
* level logging level
*/
void
log_init(char *av0, LogLevel level, SyslogFacility ignored1, int ignored2)
{
switch (level)
{
case SYSLOG_LEVEL_QUIET:
case SYSLOG_LEVEL_ERROR:
case SYSLOG_LEVEL_FATAL:
case SYSLOG_LEVEL_INFO:
case SYSLOG_LEVEL_CHAT:
case SYSLOG_LEVEL_DEBUG:
log_level = level;
break;
default:
/* unchanged */
break;
}
switch (level) {
case SYSLOG_LEVEL_QUIET:
case SYSLOG_LEVEL_ERROR:
case SYSLOG_LEVEL_FATAL:
case SYSLOG_LEVEL_INFO:
case SYSLOG_LEVEL_VERBOSE:
case SYSLOG_LEVEL_DEBUG:
log_level = level;
break;
default:
/* unchanged */
break;
}
}
#define MSGBUFSIZE 1024
@ -51,13 +50,13 @@ log_init(char *av0, LogLevel level, SyslogFacility ignored1, int ignored2)
void
do_log(LogLevel level, const char *fmt, va_list args)
{
char msgbuf[MSGBUFSIZE];
char msgbuf[MSGBUFSIZE];
if (level > log_level)
return;
if (level == SYSLOG_LEVEL_DEBUG)
fprintf(stderr, "debug: ");
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
fprintf(stderr, "%s", msgbuf);
fprintf(stderr, "\r\n");
if (level > log_level)
return;
if (level == SYSLOG_LEVEL_DEBUG)
fprintf(stderr, "debug: ");
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
fprintf(stderr, "%s", msgbuf);
fprintf(stderr, "\r\n");
}

Просмотреть файл

@ -1,21 +1,21 @@
/*
log-server.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Mon Mar 20 21:19:30 1995 ylo
Server-side versions of debug(), log(), etc. These normally send the output
to the system log.
*/
*
* log-server.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Mon Mar 20 21:19:30 1995 ylo
*
* Server-side versions of debug(), log(), etc. These normally send the output
* to the system log.
*
*/
#include "includes.h"
RCSID("$Id: log-server.c,v 1.4 1999/11/15 06:10:57 damien Exp $");
RCSID("$Id: log-server.c,v 1.5 1999/11/24 13:26:22 damien Exp $");
#include <syslog.h>
#include "packet.h"
@ -33,72 +33,68 @@ static int log_on_stderr = 0;
static int log_facility = LOG_AUTH;
/* Initialize the log.
av0 program name (should be argv[0])
on_stderr print also on stderr
level logging level
*/
* av0 program name (should be argv[0])
* on_stderr print also on stderr
* level logging level
*/
void log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
void
log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
{
switch (level)
{
case SYSLOG_LEVEL_QUIET:
case SYSLOG_LEVEL_ERROR:
case SYSLOG_LEVEL_FATAL:
case SYSLOG_LEVEL_INFO:
case SYSLOG_LEVEL_CHAT:
case SYSLOG_LEVEL_DEBUG:
log_level = level;
break;
default:
fprintf(stderr, "Unrecognized internal syslog level code %d\n",
(int)level);
exit(1);
}
switch (facility)
{
case SYSLOG_FACILITY_DAEMON:
log_facility = LOG_DAEMON;
break;
case SYSLOG_FACILITY_USER:
log_facility = LOG_USER;
break;
case SYSLOG_FACILITY_AUTH:
log_facility = LOG_AUTH;
break;
case SYSLOG_FACILITY_LOCAL0:
log_facility = LOG_LOCAL0;
break;
case SYSLOG_FACILITY_LOCAL1:
log_facility = LOG_LOCAL1;
break;
case SYSLOG_FACILITY_LOCAL2:
log_facility = LOG_LOCAL2;
break;
case SYSLOG_FACILITY_LOCAL3:
log_facility = LOG_LOCAL3;
break;
case SYSLOG_FACILITY_LOCAL4:
log_facility = LOG_LOCAL4;
break;
case SYSLOG_FACILITY_LOCAL5:
log_facility = LOG_LOCAL5;
break;
case SYSLOG_FACILITY_LOCAL6:
log_facility = LOG_LOCAL6;
break;
case SYSLOG_FACILITY_LOCAL7:
log_facility = LOG_LOCAL7;
break;
default:
fprintf(stderr, "Unrecognized internal syslog facility code %d\n",
(int)facility);
exit(1);
}
log_on_stderr = on_stderr;
switch (level) {
case SYSLOG_LEVEL_QUIET:
case SYSLOG_LEVEL_ERROR:
case SYSLOG_LEVEL_FATAL:
case SYSLOG_LEVEL_INFO:
case SYSLOG_LEVEL_VERBOSE:
case SYSLOG_LEVEL_DEBUG:
log_level = level;
break;
default:
fprintf(stderr, "Unrecognized internal syslog level code %d\n",
(int) level);
exit(1);
}
switch (facility) {
case SYSLOG_FACILITY_DAEMON:
log_facility = LOG_DAEMON;
break;
case SYSLOG_FACILITY_USER:
log_facility = LOG_USER;
break;
case SYSLOG_FACILITY_AUTH:
log_facility = LOG_AUTH;
break;
case SYSLOG_FACILITY_LOCAL0:
log_facility = LOG_LOCAL0;
break;
case SYSLOG_FACILITY_LOCAL1:
log_facility = LOG_LOCAL1;
break;
case SYSLOG_FACILITY_LOCAL2:
log_facility = LOG_LOCAL2;
break;
case SYSLOG_FACILITY_LOCAL3:
log_facility = LOG_LOCAL3;
break;
case SYSLOG_FACILITY_LOCAL4:
log_facility = LOG_LOCAL4;
break;
case SYSLOG_FACILITY_LOCAL5:
log_facility = LOG_LOCAL5;
break;
case SYSLOG_FACILITY_LOCAL6:
log_facility = LOG_LOCAL6;
break;
case SYSLOG_FACILITY_LOCAL7:
log_facility = LOG_LOCAL7;
break;
default:
fprintf(stderr, "Unrecognized internal syslog facility code %d\n",
(int) facility);
exit(1);
}
log_on_stderr = on_stderr;
}
#define MSGBUFSIZE 1024
@ -106,48 +102,44 @@ void log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
void
do_log(LogLevel level, const char *fmt, va_list args)
{
char msgbuf[MSGBUFSIZE];
char fmtbuf[MSGBUFSIZE];
char *txt = NULL;
int pri = LOG_INFO;
char msgbuf[MSGBUFSIZE];
char fmtbuf[MSGBUFSIZE];
char *txt = NULL;
int pri = LOG_INFO;
if (level > log_level)
return;
switch (level)
{
case SYSLOG_LEVEL_ERROR:
txt = "error";
pri = LOG_ERR;
break;
case SYSLOG_LEVEL_FATAL:
txt = "fatal";
pri = LOG_ERR;
break;
case SYSLOG_LEVEL_INFO:
pri = LOG_INFO;
break;
case SYSLOG_LEVEL_CHAT:
pri = LOG_INFO;
break;
case SYSLOG_LEVEL_DEBUG:
txt = "debug";
pri = LOG_DEBUG;
break;
default:
txt = "internal error";
pri = LOG_ERR;
break;
}
if (txt != NULL) {
snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt);
vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args);
}else{
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
}
if (log_on_stderr)
fprintf(stderr, "%s\n", msgbuf);
openlog(__progname, LOG_PID, log_facility);
syslog(pri, "%.500s", msgbuf);
closelog();
if (level > log_level)
return;
switch (level) {
case SYSLOG_LEVEL_ERROR:
txt = "error";
pri = LOG_ERR;
break;
case SYSLOG_LEVEL_FATAL:
txt = "fatal";
pri = LOG_ERR;
break;
case SYSLOG_LEVEL_INFO:
case SYSLOG_LEVEL_VERBOSE:
pri = LOG_INFO;
break;
case SYSLOG_LEVEL_DEBUG:
txt = "debug";
pri = LOG_DEBUG;
break;
default:
txt = "internal error";
pri = LOG_ERR;
break;
}
if (txt != NULL) {
snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt);
vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args);
} else {
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
}
if (log_on_stderr)
fprintf(stderr, "%s\n", msgbuf);
openlog(__progname, LOG_PID, log_facility);
syslog(pri, "%.500s", msgbuf);
closelog();
}

217
log.c
Просмотреть файл

@ -1,11 +1,11 @@
/*
Shared versions of debug(), log(), etc.
*
* Shared versions of debug(), log(), etc.
*
*/
#include "includes.h"
RCSID("$OpenBSD: log.c,v 1.2 1999/11/19 16:04:17 markus Exp $");
RCSID("$OpenBSD: log.c,v 1.5 1999/11/24 00:26:02 deraadt Exp $");
#include "ssh.h"
#include "xmalloc.h"
@ -13,66 +13,65 @@ RCSID("$OpenBSD: log.c,v 1.2 1999/11/19 16:04:17 markus Exp $");
/* Fatal messages. This function never returns. */
void
fatal(const char *fmt, ...)
fatal(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_FATAL, fmt, args);
va_end(args);
fatal_cleanup();
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_FATAL, fmt, args);
va_end(args);
fatal_cleanup();
}
/* Error messages that should be logged. */
void
error(const char *fmt, ...)
error(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_ERROR, fmt, args);
va_end(args);
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_ERROR, fmt, args);
va_end(args);
}
/* Log this message (information that usually should go to the log). */
void
log(const char *fmt, ...)
log(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_INFO, fmt, args);
va_end(args);
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_INFO, fmt, args);
va_end(args);
}
/* More detailed messages (information that does not need to go to the log). */
void
chat(const char *fmt, ...)
verbose(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_CHAT, fmt, args);
va_end(args);
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_VERBOSE, fmt, args);
va_end(args);
}
/* Debugging messages that should not be logged during normal operation. */
void
debug(const char *fmt, ...)
debug(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_DEBUG, fmt, args);
va_end(args);
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_DEBUG, fmt, args);
va_end(args);
}
/* Fatal cleanup */
struct fatal_cleanup
{
struct fatal_cleanup *next;
void (*proc)(void *);
void *context;
struct fatal_cleanup {
struct fatal_cleanup *next;
void (*proc) (void *);
void *context;
};
static struct fatal_cleanup *fatal_cleanups = NULL;
@ -80,116 +79,108 @@ static struct fatal_cleanup *fatal_cleanups = NULL;
/* Registers a cleanup function to be called by fatal() before exiting. */
void
fatal_add_cleanup(void (*proc)(void *), void *context)
fatal_add_cleanup(void (*proc) (void *), void *context)
{
struct fatal_cleanup *cu;
struct fatal_cleanup *cu;
cu = xmalloc(sizeof(*cu));
cu->proc = proc;
cu->context = context;
cu->next = fatal_cleanups;
fatal_cleanups = cu;
cu = xmalloc(sizeof(*cu));
cu->proc = proc;
cu->context = context;
cu->next = fatal_cleanups;
fatal_cleanups = cu;
}
/* Removes a cleanup frunction to be called at fatal(). */
void
fatal_remove_cleanup(void (*proc)(void *context), void *context)
fatal_remove_cleanup(void (*proc) (void *context), void *context)
{
struct fatal_cleanup **cup, *cu;
for (cup = &fatal_cleanups; *cup; cup = &cu->next)
{
cu = *cup;
if (cu->proc == proc && cu->context == context)
{
*cup = cu->next;
xfree(cu);
return;
struct fatal_cleanup **cup, *cu;
for (cup = &fatal_cleanups; *cup; cup = &cu->next) {
cu = *cup;
if (cu->proc == proc && cu->context == context) {
*cup = cu->next;
xfree(cu);
return;
}
}
}
fatal("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx\n",
(unsigned long)proc, (unsigned long)context);
fatal("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx\n",
(unsigned long) proc, (unsigned long) context);
}
/* Cleanup and exit */
void
fatal_cleanup(void)
{
struct fatal_cleanup *cu, *next_cu;
static int called = 0;
if (called)
exit(255);
called = 1;
struct fatal_cleanup *cu, *next_cu;
static int called = 0;
/* Call cleanup functions. */
for (cu = fatal_cleanups; cu; cu = next_cu)
{
next_cu = cu->next;
debug("Calling cleanup 0x%lx(0x%lx)",
(unsigned long)cu->proc, (unsigned long)cu->context);
(*cu->proc)(cu->context);
}
exit(255);
if (called)
exit(255);
called = 1;
/* Call cleanup functions. */
for (cu = fatal_cleanups; cu; cu = next_cu) {
next_cu = cu->next;
debug("Calling cleanup 0x%lx(0x%lx)",
(unsigned long) cu->proc, (unsigned long) cu->context);
(*cu->proc) (cu->context);
}
exit(255);
}
/* textual representation of log-facilities/levels */
static struct
{
const char *name;
SyslogFacility val;
} log_facilities[] =
{
{ "DAEMON", SYSLOG_FACILITY_DAEMON },
{ "USER", SYSLOG_FACILITY_USER },
{ "AUTH", SYSLOG_FACILITY_AUTH },
{ "LOCAL0", SYSLOG_FACILITY_LOCAL0 },
{ "LOCAL1", SYSLOG_FACILITY_LOCAL1 },
{ "LOCAL2", SYSLOG_FACILITY_LOCAL2 },
{ "LOCAL3", SYSLOG_FACILITY_LOCAL3 },
{ "LOCAL4", SYSLOG_FACILITY_LOCAL4 },
{ "LOCAL5", SYSLOG_FACILITY_LOCAL5 },
{ "LOCAL6", SYSLOG_FACILITY_LOCAL6 },
{ "LOCAL7", SYSLOG_FACILITY_LOCAL7 },
{ NULL, 0 }
static struct {
const char *name;
SyslogFacility val;
} log_facilities[] = {
{ "DAEMON", SYSLOG_FACILITY_DAEMON },
{ "USER", SYSLOG_FACILITY_USER },
{ "AUTH", SYSLOG_FACILITY_AUTH },
{ "LOCAL0", SYSLOG_FACILITY_LOCAL0 },
{ "LOCAL1", SYSLOG_FACILITY_LOCAL1 },
{ "LOCAL2", SYSLOG_FACILITY_LOCAL2 },
{ "LOCAL3", SYSLOG_FACILITY_LOCAL3 },
{ "LOCAL4", SYSLOG_FACILITY_LOCAL4 },
{ "LOCAL5", SYSLOG_FACILITY_LOCAL5 },
{ "LOCAL6", SYSLOG_FACILITY_LOCAL6 },
{ "LOCAL7", SYSLOG_FACILITY_LOCAL7 },
{ NULL, 0 }
};
static struct
{
const char *name;
LogLevel val;
static struct {
const char *name;
LogLevel val;
} log_levels[] =
{
{ "QUIET", SYSLOG_LEVEL_QUIET },
{ "FATAL", SYSLOG_LEVEL_FATAL },
{ "ERROR", SYSLOG_LEVEL_ERROR },
{ "INFO", SYSLOG_LEVEL_INFO },
{ "CHAT", SYSLOG_LEVEL_CHAT },
{ "DEBUG", SYSLOG_LEVEL_DEBUG },
{ NULL, 0 }
{ "QUIET", SYSLOG_LEVEL_QUIET },
{ "FATAL", SYSLOG_LEVEL_FATAL },
{ "ERROR", SYSLOG_LEVEL_ERROR },
{ "INFO", SYSLOG_LEVEL_INFO },
{ "VERBOSE", SYSLOG_LEVEL_VERBOSE },
{ "DEBUG", SYSLOG_LEVEL_DEBUG },
{ NULL, 0 }
};
SyslogFacility
log_facility_number(char *name)
{
int i;
if (name != NULL)
for (i = 0; log_facilities[i].name; i++)
if (strcasecmp(log_facilities[i].name, name) == 0)
return log_facilities[i].val;
return (SyslogFacility)-1;
int i;
if (name != NULL)
for (i = 0; log_facilities[i].name; i++)
if (strcasecmp(log_facilities[i].name, name) == 0)
return log_facilities[i].val;
return (SyslogFacility) - 1;
}
LogLevel
log_level_number(char *name)
{
int i;
if (name != NULL)
for (i = 0; log_levels[i].name; i++)
if (strcasecmp(log_levels[i].name, name) == 0)
return log_levels[i].val;
return (LogLevel)-1;
int i;
if (name != NULL)
for (i = 0; log_levels[i].name; i++)
if (strcasecmp(log_levels[i].name, name) == 0)
return log_levels[i].val;
return (LogLevel) - 1;
}

181
login.c
Просмотреть файл

@ -1,128 +1,129 @@
/*
login.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Fri Mar 24 14:51:08 1995 ylo
This file performs some of the things login(1) normally does. We cannot
easily use something like login -p -h host -f user, because there are
several different logins around, and it is hard to determined what kind of
login the current system has. Also, we want to be able to execute commands
on a tty.
*/
*
* login.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Fri Mar 24 14:51:08 1995 ylo
*
* This file performs some of the things login(1) normally does. We cannot
* easily use something like login -p -h host -f user, because there are
* several different logins around, and it is hard to determined what kind of
* login the current system has. Also, we want to be able to execute commands
* on a tty.
*
*/
#include "includes.h"
RCSID("$Id: login.c,v 1.2 1999/11/10 23:40:23 damien Exp $");
RCSID("$Id: login.c,v 1.3 1999/11/24 13:26:22 damien Exp $");
#include <utmp.h>
#include "ssh.h"
#ifdef HAVE_UTIL_H
# include <util.h>
#endif
#ifdef HAVE_LASTLOG_H
# include <lastlog.h>
#endif
#include "ssh.h"
/* Returns the time when the user last logged in. Returns 0 if the
information is not available. This must be called before record_login.
/* Returns the time when the user last logged in. Returns 0 if the
information is not available. This must be called before record_login.
The host the user logged in from will be returned in buf. */
/* Returns the time when the user last logged in (or 0 if no previous login
is found). The name of the host used last time is returned in buf. */
unsigned long get_last_login_time(uid_t uid, const char *logname,
char *buf, unsigned int bufsize)
unsigned long
get_last_login_time(uid_t uid, const char *logname,
char *buf, unsigned int bufsize)
{
struct lastlog ll;
char *lastlog;
int fd;
struct lastlog ll;
char *lastlog;
int fd;
lastlog = _PATH_LASTLOG;
lastlog = _PATH_LASTLOG;
buf[0] = '\0';
buf[0] = '\0';
fd = open(lastlog, O_RDONLY);
if (fd < 0)
return 0;
lseek(fd, (off_t)((long)uid * sizeof(ll)), SEEK_SET);
if (read(fd, &ll, sizeof(ll)) != sizeof(ll))
{
close(fd);
return 0;
}
close(fd);
if (bufsize > sizeof(ll.ll_host) + 1)
bufsize = sizeof(ll.ll_host) + 1;
strncpy(buf, ll.ll_host, bufsize - 1);
buf[bufsize - 1] = 0;
return ll.ll_time;
fd = open(lastlog, O_RDONLY);
if (fd < 0)
return 0;
lseek(fd, (off_t) ((long) uid * sizeof(ll)), SEEK_SET);
if (read(fd, &ll, sizeof(ll)) != sizeof(ll)) {
close(fd);
return 0;
}
close(fd);
if (bufsize > sizeof(ll.ll_host) + 1)
bufsize = sizeof(ll.ll_host) + 1;
strncpy(buf, ll.ll_host, bufsize - 1);
buf[bufsize - 1] = 0;
return ll.ll_time;
}
/* Records that the user has logged in. I these parts of operating systems
were more standardized. */
void record_login(int pid, const char *ttyname, const char *user, uid_t uid,
const char *host, struct sockaddr_in *addr)
void
record_login(int pid, const char *ttyname, const char *user, uid_t uid,
const char *host, struct sockaddr_in * addr)
{
int fd;
struct lastlog ll;
char *lastlog;
int fd;
struct lastlog ll;
char *lastlog;
struct utmp u;
const char *utmp, *wtmp;
struct utmp u;
const char *utmp, *wtmp;
/* Construct an utmp/wtmp entry. */
memset(&u, 0, sizeof(u));
strncpy(u.ut_line, ttyname + 5, sizeof(u.ut_line));
u.ut_time = time(NULL);
strncpy(u.ut_name, user, sizeof(u.ut_name));
/* Construct an utmp/wtmp entry. */
memset(&u, 0, sizeof(u));
strncpy(u.ut_line, ttyname + 5, sizeof(u.ut_line));
u.ut_time = time(NULL);
strncpy(u.ut_name, user, sizeof(u.ut_name));
#ifdef HAVE_HOST_IN_UTMP
strncpy(u.ut_host, host, sizeof(u.ut_host));
strncpy(u.ut_host, host, sizeof(u.ut_host));
#endif
/* Figure out the file names. */
utmp = _PATH_UTMP;
wtmp = _PATH_WTMP;
login(&u);
/* Figure out the file names. */
utmp = _PATH_UTMP;
wtmp = _PATH_WTMP;
lastlog = _PATH_LASTLOG;
login(&u);
lastlog = _PATH_LASTLOG;
/* Update lastlog unless actually recording a logout. */
if (strcmp(user, "") != 0)
{
/* It is safer to bzero the lastlog structure first because some
systems might have some extra fields in it (e.g. SGI) */
memset(&ll, 0, sizeof(ll));
/* Update lastlog unless actually recording a logout. */
if (strcmp(user, "") != 0) {
/* It is safer to bzero the lastlog structure first
because some systems might have some extra fields in it
(e.g. SGI) */
memset(&ll, 0, sizeof(ll));
/* Update lastlog. */
ll.ll_time = time(NULL);
strncpy(ll.ll_line, ttyname + 5, sizeof(ll.ll_line));
strncpy(ll.ll_host, host, sizeof(ll.ll_host));
fd = open(lastlog, O_RDWR);
if (fd >= 0)
{
lseek(fd, (off_t)((long)uid * sizeof(ll)), SEEK_SET);
if (write(fd, &ll, sizeof(ll)) != sizeof(ll))
log("Could not write %.100s: %.100s", lastlog, strerror(errno));
close(fd);
/* Update lastlog. */
ll.ll_time = time(NULL);
strncpy(ll.ll_line, ttyname + 5, sizeof(ll.ll_line));
strncpy(ll.ll_host, host, sizeof(ll.ll_host));
fd = open(lastlog, O_RDWR);
if (fd >= 0) {
lseek(fd, (off_t) ((long) uid * sizeof(ll)), SEEK_SET);
if (write(fd, &ll, sizeof(ll)) != sizeof(ll))
log("Could not write %.100s: %.100s", lastlog, strerror(errno));
close(fd);
}
}
}
}
void record_logout(int pid, const char *ttyname)
/* Records that the user has logged out. */
void
record_logout(int pid, const char *ttyname)
{
#ifdef HAVE_LIBUTIL_LOGIN
const char *line = ttyname + 5; /* /dev/ttyq8 -> ttyq8 */
if (logout(line))
logwtmp(line, "", "");
const char *line = ttyname + 5; /* /dev/ttyq8 -> ttyq8 */
if (logout(line))
logwtmp(line, "", "");
#else /* HAVE_LIBUTIL_LOGIN */
record_login(pid, ttyname, "", -1, "", NULL);
record_login(pid, ttyname, "", -1, "", NULL);
#endif /* HAVE_LIBUTIL_LOGIN */
}

125
match.c
Просмотреть файл

@ -1,78 +1,77 @@
/*
match.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Thu Jun 22 01:17:50 1995 ylo
Simple pattern matching, with '*' and '?' as wildcards.
*/
*
* match.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Thu Jun 22 01:17:50 1995 ylo
*
* Simple pattern matching, with '*' and '?' as wildcards.
*
*/
#include "includes.h"
RCSID("$Id: match.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
RCSID("$Id: match.c,v 1.2 1999/11/24 13:26:22 damien Exp $");
#include "ssh.h"
/* Returns true if the given string matches the pattern (which may contain
? and * as wildcards), and zero if it does not match. */
int match_pattern(const char *s, const char *pattern)
int
match_pattern(const char *s, const char *pattern)
{
while (1)
{
/* If at end of pattern, accept if also at end of string. */
if (!*pattern)
return !*s;
for (;;) {
/* If at end of pattern, accept if also at end of string. */
if (!*pattern)
return !*s;
/* Process '*'. */
if (*pattern == '*')
{
/* Skip the asterisk. */
pattern++;
/* Process '*'. */
if (*pattern == '*') {
/* Skip the asterisk. */
pattern++;
/* If at end of pattern, accept immediately. */
if (!*pattern)
return 1;
/* If at end of pattern, accept immediately. */
if (!*pattern)
return 1;
/* If next character in pattern is known, optimize. */
if (*pattern != '?' && *pattern != '*')
{
/* Look instances of the next character in pattern, and try
to match starting from those. */
for (; *s; s++)
if (*s == *pattern &&
match_pattern(s + 1, pattern + 1))
return 1;
/* Failed. */
return 0;
}
/* If next character in pattern is known, optimize. */
if (*pattern != '?' && *pattern != '*') {
/* Look instances of the next character in
pattern, and try to match starting from
those. */
for (; *s; s++)
if (*s == *pattern &&
match_pattern(s + 1, pattern + 1))
return 1;
/* Failed. */
return 0;
}
/* Move ahead one character at a time and try to
match at each position. */
for (; *s; s++)
if (match_pattern(s, pattern))
return 1;
/* Failed. */
return 0;
}
/* There must be at least one more character in the
string. If we are at the end, fail. */
if (!*s)
return 0;
/* Move ahead one character at a time and try to match at each
position. */
for (; *s; s++)
if (match_pattern(s, pattern))
return 1;
/* Failed. */
return 0;
}
/* Check if the next character of the string is
acceptable. */
if (*pattern != '?' && *pattern != *s)
return 0;
/* There must be at least one more character in the string. If we are
at the end, fail. */
if (!*s)
return 0;
/* Check if the next character of the string is acceptable. */
if (*pattern != '?' && *pattern != *s)
return 0;
/* Move to the next character, both in string and in pattern. */
s++;
pattern++;
}
/*NOTREACHED*/
/* Move to the next character, both in string and in
pattern. */
s++;
pattern++;
}
/* NOTREACHED */
}

66
mpaux.c
Просмотреть файл

@ -1,21 +1,24 @@
/*
mpaux.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Sun Jul 16 04:29:30 1995 ylo
This file contains various auxiliary functions related to multiple
precision integers.
*
* mpaux.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Sun Jul 16 04:29:30 1995 ylo
*
* This file contains various auxiliary functions related to multiple
* precision integers.
*
*/
#include "includes.h"
RCSID("$Id: mpaux.c,v 1.6 1999/11/16 02:37:16 damien Exp $");
RCSID("$Id: mpaux.c,v 1.7 1999/11/24 13:26:22 damien Exp $");
#include "getput.h"
#include "xmalloc.h"
#ifdef HAVE_OPENSSL
#include <openssl/bn.h>
@ -26,29 +29,24 @@ RCSID("$Id: mpaux.c,v 1.6 1999/11/16 02:37:16 damien Exp $");
#include <ssl/md5.h>
#endif
#include "getput.h"
#include "xmalloc.h"
void
compute_session_id(unsigned char session_id[16],
unsigned char cookie[8],
BIGNUM *host_key_n,
BIGNUM *session_key_n)
BIGNUM* host_key_n,
BIGNUM* session_key_n)
{
unsigned int host_key_bits = BN_num_bits(host_key_n);
unsigned int session_key_bits = BN_num_bits(session_key_n);
unsigned int bytes = (host_key_bits + 7) / 8 + (session_key_bits + 7) / 8 + 8;
unsigned char *buf = xmalloc(bytes);
MD5_CTX md;
unsigned int host_key_bits = BN_num_bits(host_key_n);
unsigned int session_key_bits = BN_num_bits(session_key_n);
unsigned int bytes = (host_key_bits + 7) / 8 + (session_key_bits + 7) / 8 + 8;
unsigned char *buf = xmalloc(bytes);
MD5_CTX md;
BN_bn2bin(host_key_n, buf);
BN_bn2bin(session_key_n, buf + (host_key_bits + 7 ) / 8);
memcpy(buf + (host_key_bits + 7) / 8 + (session_key_bits + 7) / 8,
cookie, 8);
MD5_Init(&md);
MD5_Update(&md, buf, bytes);
MD5_Final(session_id, &md);
memset(buf, 0, bytes);
xfree(buf);
BN_bn2bin(host_key_n, buf);
BN_bn2bin(session_key_n, buf + (host_key_bits + 7) / 8);
memcpy(buf + (host_key_bits + 7) / 8 + (session_key_bits + 7) / 8, cookie, 8);
MD5_Init(&md);
MD5_Update(&md, buf, bytes);
MD5_Final(session_id, &md);
memset(buf, 0, bytes);
xfree(buf);
}

40
mpaux.h
Просмотреть файл

@ -1,20 +1,19 @@
/*
*
* mpaux.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Sun Jul 16 04:29:30 1995 ylo
*
* This file contains various auxiliary functions related to multiple
* precision integers.
*/
mpaux.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Sun Jul 16 04:29:30 1995 ylo
This file contains various auxiliary functions related to multiple
precision integers.
*/
/* RCSID("$Id: mpaux.h,v 1.2 1999/11/16 02:37:16 damien Exp $"); */
/* RCSID("$Id: mpaux.h,v 1.3 1999/11/24 13:26:22 damien Exp $"); */
#ifndef MPAUX_H
#define MPAUX_H
@ -22,9 +21,10 @@ precision integers.
/* Computes a 16-byte session id in the global variable session_id.
The session id is computed by concatenating the linearized, msb
first representations of host_key_n, session_key_n, and the cookie. */
void compute_session_id(unsigned char session_id[16],
unsigned char cookie[8],
BIGNUM *host_key_n,
BIGNUM *session_key_n);
void
compute_session_id(unsigned char session_id[16],
unsigned char cookie[8],
BIGNUM * host_key_n,
BIGNUM * session_key_n);
#endif /* MPAUX_H */
#endif /* MPAUX_H */

119
nchan.c
Просмотреть файл

@ -1,5 +1,5 @@
#include "includes.h"
RCSID("$Id: nchan.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
RCSID("$Id: nchan.c,v 1.2 1999/11/24 13:26:22 damien Exp $");
#include "ssh.h"
@ -15,122 +15,131 @@ static void chan_shutdown_read(Channel *c);
static void chan_delele_if_full_closed(Channel *c);
/*
* EVENTS: update channel input/output states
* execute ACTIONS
* EVENTS update channel input/output states execute ACTIONS
*/
/* events concerning the INPUT from socket for channel (istate) */
void
chan_rcvd_oclose(Channel *c){
switch(c->istate){
chan_rcvd_oclose(Channel *c)
{
switch (c->istate) {
case CHAN_INPUT_WAIT_OCLOSE:
debug("channel %d: INPUT_WAIT_OCLOSE -> INPUT_CLOSED [rcvd OCLOSE]", c->self);
c->istate=CHAN_INPUT_CLOSED;
c->istate = CHAN_INPUT_CLOSED;
chan_delele_if_full_closed(c);
break;
case CHAN_INPUT_OPEN:
debug("channel %d: INPUT_OPEN -> INPUT_CLOSED [rvcd OCLOSE, send IEOF]", c->self);
chan_shutdown_read(c);
chan_send_ieof(c);
c->istate=CHAN_INPUT_CLOSED;
c->istate = CHAN_INPUT_CLOSED;
chan_delele_if_full_closed(c);
break;
default:
debug("protocol error: chan_rcvd_oclose %d for istate %d",c->self,c->istate);
debug("protocol error: chan_rcvd_oclose %d for istate %d", c->self, c->istate);
break;
}
}
void
chan_read_failed(Channel *c){
switch(c->istate){
chan_read_failed(Channel *c)
{
switch (c->istate) {
case CHAN_INPUT_OPEN:
debug("channel %d: INPUT_OPEN -> INPUT_WAIT_DRAIN [read failed]", c->self);
chan_shutdown_read(c);
c->istate=CHAN_INPUT_WAIT_DRAIN;
c->istate = CHAN_INPUT_WAIT_DRAIN;
break;
default:
debug("internal error: we do not read, but chan_read_failed %d for istate %d",
c->self,c->istate);
c->self, c->istate);
break;
}
}
void
chan_ibuf_empty(Channel *c){
if(buffer_len(&c->input)){
debug("internal error: chan_ibuf_empty %d for non empty buffer",c->self);
chan_ibuf_empty(Channel *c)
{
if (buffer_len(&c->input)) {
debug("internal error: chan_ibuf_empty %d for non empty buffer", c->self);
return;
}
switch(c->istate){
switch (c->istate) {
case CHAN_INPUT_WAIT_DRAIN:
debug("channel %d: INPUT_WAIT_DRAIN -> INPUT_WAIT_OCLOSE [inbuf empty, send IEOF]", c->self);
chan_send_ieof(c);
c->istate=CHAN_INPUT_WAIT_OCLOSE;
c->istate = CHAN_INPUT_WAIT_OCLOSE;
break;
default:
debug("internal error: chan_ibuf_empty %d for istate %d",c->self,c->istate);
debug("internal error: chan_ibuf_empty %d for istate %d", c->self, c->istate);
break;
}
}
/* events concerning the OUTPUT from channel for socket (ostate) */
void
chan_rcvd_ieof(Channel *c){
switch(c->ostate){
chan_rcvd_ieof(Channel *c)
{
switch (c->ostate) {
case CHAN_OUTPUT_OPEN:
debug("channel %d: OUTPUT_OPEN -> OUTPUT_WAIT_DRAIN [rvcd IEOF]", c->self);
c->ostate=CHAN_OUTPUT_WAIT_DRAIN;
c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
break;
case CHAN_OUTPUT_WAIT_IEOF:
debug("channel %d: OUTPUT_WAIT_IEOF -> OUTPUT_CLOSED [rvcd IEOF]", c->self);
c->ostate=CHAN_OUTPUT_CLOSED;
c->ostate = CHAN_OUTPUT_CLOSED;
chan_delele_if_full_closed(c);
break;
default:
debug("protocol error: chan_rcvd_ieof %d for ostate %d", c->self,c->ostate);
debug("protocol error: chan_rcvd_ieof %d for ostate %d", c->self, c->ostate);
break;
}
}
void
chan_write_failed(Channel *c){
switch(c->ostate){
chan_write_failed(Channel *c)
{
switch (c->ostate) {
case CHAN_OUTPUT_OPEN:
debug("channel %d: OUTPUT_OPEN -> OUTPUT_WAIT_IEOF [write failed]", c->self);
chan_send_oclose(c);
c->ostate=CHAN_OUTPUT_WAIT_IEOF;
c->ostate = CHAN_OUTPUT_WAIT_IEOF;
break;
case CHAN_OUTPUT_WAIT_DRAIN:
debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [write failed]", c->self);
chan_send_oclose(c);
c->ostate=CHAN_OUTPUT_CLOSED;
c->ostate = CHAN_OUTPUT_CLOSED;
chan_delele_if_full_closed(c);
break;
default:
debug("internal error: chan_write_failed %d for ostate %d",c->self,c->ostate);
debug("internal error: chan_write_failed %d for ostate %d", c->self, c->ostate);
break;
}
}
void
chan_obuf_empty(Channel *c){
if(buffer_len(&c->output)){
debug("internal error: chan_obuf_empty %d for non empty buffer",c->self);
chan_obuf_empty(Channel *c)
{
if (buffer_len(&c->output)) {
debug("internal error: chan_obuf_empty %d for non empty buffer", c->self);
return;
}
switch(c->ostate){
switch (c->ostate) {
case CHAN_OUTPUT_WAIT_DRAIN:
debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [obuf empty, send OCLOSE]", c->self);
chan_send_oclose(c);
c->ostate=CHAN_OUTPUT_CLOSED;
c->ostate = CHAN_OUTPUT_CLOSED;
chan_delele_if_full_closed(c);
break;
default:
debug("internal error: chan_obuf_empty %d for ostate %d",c->self,c->ostate);
debug("internal error: chan_obuf_empty %d for ostate %d", c->self, c->ostate);
break;
}
}
/*
* ACTIONS: should never update c->istate or c->ostate
* ACTIONS: should never update the channel states: c->istate or c->ostate
*/
static void
chan_send_ieof(Channel *c){
switch(c->istate){
chan_send_ieof(Channel *c)
{
switch (c->istate) {
case CHAN_INPUT_OPEN:
case CHAN_INPUT_WAIT_DRAIN:
packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
@ -138,13 +147,14 @@ chan_send_ieof(Channel *c){
packet_send();
break;
default:
debug("internal error: channel %d: cannot send IEOF for istate %d",c->self,c->istate);
debug("internal error: channel %d: cannot send IEOF for istate %d", c->self, c->istate);
break;
}
}
static void
chan_send_oclose(Channel *c){
switch(c->ostate){
chan_send_oclose(Channel *c)
{
switch (c->ostate) {
case CHAN_OUTPUT_OPEN:
case CHAN_OUTPUT_WAIT_DRAIN:
chan_shutdown_write(c);
@ -154,34 +164,39 @@ chan_send_oclose(Channel *c){
packet_send();
break;
default:
debug("internal error: channel %d: cannot send OCLOSE for ostate %d",c->self,c->istate);
debug("internal error: channel %d: cannot send OCLOSE for ostate %d", c->self, c->istate);
break;
}
}
/* helper */
static void
chan_shutdown_write(Channel *c){
chan_shutdown_write(Channel *c)
{
debug("channel %d: shutdown_write", c->self);
if(shutdown(c->sock, SHUT_WR)<0)
if (shutdown(c->sock, SHUT_WR) < 0)
error("chan_shutdown_write failed for #%d/fd%d: %.100s",
c->self, c->sock, strerror(errno));
c->self, c->sock, strerror(errno));
}
static void
chan_shutdown_read(Channel *c){
chan_shutdown_read(Channel *c)
{
debug("channel %d: shutdown_read", c->self);
if(shutdown(c->sock, SHUT_RD)<0)
if (shutdown(c->sock, SHUT_RD) < 0)
error("chan_shutdown_read failed for #%d/fd%d: %.100s",
c->self, c->sock, strerror(errno));
c->self, c->sock, strerror(errno));
}
static void
chan_delele_if_full_closed(Channel *c){
if(c->istate==CHAN_INPUT_CLOSED && c->ostate==CHAN_OUTPUT_CLOSED){
chan_delele_if_full_closed(Channel *c)
{
if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
debug("channel %d: closing", c->self);
channel_free(c->self);
}
}
void
chan_init_iostates(Channel *c){
c->ostate=CHAN_OUTPUT_OPEN;
c->istate=CHAN_INPUT_OPEN;
chan_init_iostates(Channel *c)
{
c->ostate = CHAN_OUTPUT_OPEN;
c->istate = CHAN_INPUT_OPEN;
}

26
nchan.h
Просмотреть файл

@ -1,4 +1,4 @@
/* RCSID("$Id: nchan.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
/* RCSID("$Id: nchan.h,v 1.2 1999/11/24 13:26:22 damien Exp $"); */
#ifndef NCHAN_H
#define NCHAN_H
@ -7,24 +7,24 @@
* SSH Protocol 1.5 aka New Channel Protocol
* Thanks to Martina, Axel and everyone who left Erlangen, leaving me bored.
* Written by Markus Friedl in October 1999
*
*
* Protocol versions 1.3 and 1.5 differ in the handshake protocol used for the
* tear down of channels:
*
*
* 1.3: strict request-ack-protocol:
* CLOSE ->
* <- CLOSE_CONFIRM
*
*
* 1.5: uses variations of:
* IEOF ->
* <- OCLOSE
* <- IEOF
* OCLOSE ->
* i.e. both sides have to close the channel
*
*
* See the debugging output from 'ssh -v' and 'sshd -d' of
* ssh-1.2.27 as an example.
*
*
*/
/* ssh-proto-1.5 overloads prot-1.3-message-types */
@ -44,14 +44,14 @@
#define CHAN_OUTPUT_CLOSED 0x80
/* EVENTS for the input state */
void chan_rcvd_oclose(Channel *c);
void chan_read_failed(Channel *c);
void chan_ibuf_empty(Channel *c);
void chan_rcvd_oclose(Channel * c);
void chan_read_failed(Channel * c);
void chan_ibuf_empty(Channel * c);
/* EVENTS for the output state */
void chan_rcvd_ieof(Channel *c);
void chan_write_failed(Channel *c);
void chan_obuf_empty(Channel *c);
void chan_rcvd_ieof(Channel * c);
void chan_write_failed(Channel * c);
void chan_obuf_empty(Channel * c);
void chan_init_iostates(Channel *c);
void chan_init_iostates(Channel * c);
#endif

803
packet.c

Разница между файлами не показана из-за своего большого размера Загрузить разницу

101
packet.h
Просмотреть файл

@ -1,19 +1,19 @@
/*
*
* packet.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Sat Mar 18 02:02:14 1995 ylo
*
* Interface for the packet protocol functions.
*
*/
packet.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Sat Mar 18 02:02:14 1995 ylo
Interface for the packet protocol functions.
*/
/* RCSID("$Id: packet.h,v 1.5 1999/11/21 02:23:53 damien Exp $"); */
/* RCSID("$Id: packet.h,v 1.6 1999/11/24 13:26:22 damien Exp $"); */
#ifndef PACKET_H
#define PACKET_H
@ -31,83 +31,84 @@ Interface for the packet protocol functions.
packet_set_encryption_key is called. It is permissible that fd_in
and fd_out are the same descriptor; in that case it is assumed to
be a socket. */
void packet_set_connection(int fd_in, int fd_out);
void packet_set_connection(int fd_in, int fd_out);
/* Puts the connection file descriptors into non-blocking mode. */
void packet_set_nonblocking(void);
void packet_set_nonblocking(void);
/* Returns the file descriptor used for input. */
int packet_get_connection_in(void);
int packet_get_connection_in(void);
/* Returns the file descriptor used for output. */
int packet_get_connection_out(void);
int packet_get_connection_out(void);
/* Closes the connection (both descriptors) and clears and frees
internal data structures. */
void packet_close(void);
internal data structures. */
void packet_close(void);
/* Causes any further packets to be encrypted using the given key. The same
key is used for both sending and reception. However, both directions
are encrypted independently of each other. Cipher types are
defined in ssh.h. */
void packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
int cipher_type);
void
packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
int cipher_type);
/* Sets remote side protocol flags for the current connection. This can
be called at any time. */
void packet_set_protocol_flags(unsigned int flags);
void packet_set_protocol_flags(unsigned int flags);
/* Returns the remote protocol flags set earlier by the above function. */
unsigned int packet_get_protocol_flags(void);
/* Enables compression in both directions starting from the next packet. */
void packet_start_compression(int level);
void packet_start_compression(int level);
/* Informs that the current session is interactive. Sets IP flags for optimal
performance in interactive use. */
void packet_set_interactive(int interactive, int keepalives);
void packet_set_interactive(int interactive, int keepalives);
/* Returns true if the current connection is interactive. */
int packet_is_interactive(void);
int packet_is_interactive(void);
/* Starts constructing a packet to send. */
void packet_start(int type);
void packet_start(int type);
/* Appends a character to the packet data. */
void packet_put_char(int ch);
void packet_put_char(int ch);
/* Appends an integer to the packet data. */
void packet_put_int(unsigned int value);
void packet_put_int(unsigned int value);
/* Appends an arbitrary precision integer to packet data. */
void packet_put_bignum(BIGNUM *value);
void packet_put_bignum(BIGNUM * value);
/* Appends a string to packet data. */
void packet_put_string(const char *buf, unsigned int len);
void packet_put_string(const char *buf, unsigned int len);
/* Finalizes and sends the packet. If the encryption key has been set,
encrypts the packet before sending. */
void packet_send(void);
void packet_send(void);
/* Waits until a packet has been received, and returns its type. */
int packet_read(int *payload_len_ptr);
int packet_read(int *payload_len_ptr);
/* Waits until a packet has been received, verifies that its type matches
that given, and gives a fatal error and exits if there is a mismatch. */
void packet_read_expect(int *payload_len_ptr, int type);
void packet_read_expect(int *payload_len_ptr, int type);
/* Checks if a full packet is available in the data received so far via
packet_process_incoming. If so, reads the packet; otherwise returns
SSH_MSG_NONE. This does not wait for data from the connection.
SSH_MSG_NONE. This does not wait for data from the connection.
SSH_MSG_DISCONNECT is handled specially here. Also,
SSH_MSG_IGNORE messages are skipped by this function and are never returned
to higher levels. */
int packet_read_poll(int *packet_len_ptr);
int packet_read_poll(int *packet_len_ptr);
/* Buffers the given amount of input characters. This is intended to be
used together with packet_read_poll. */
void packet_process_incoming(const char *buf, unsigned int len);
void packet_process_incoming(const char *buf, unsigned int len);
/* Returns a character (0-255) from the packet data. */
unsigned int packet_get_char(void);
@ -117,19 +118,19 @@ unsigned int packet_get_int(void);
/* Returns an arbitrary precision integer from the packet data. The integer
must have been initialized before this call. */
void packet_get_bignum(BIGNUM *value, int *length_ptr);
void packet_get_bignum(BIGNUM * value, int *length_ptr);
/* Returns a string from the packet data. The string is allocated using
xmalloc; it is the responsibility of the calling program to free it when
no longer needed. The length_ptr argument may be NULL, or point to an
integer into which the length of the string is stored. */
char *packet_get_string(unsigned int *length_ptr);
char *packet_get_string(unsigned int *length_ptr);
/* Logs the error in syslog using LOG_INFO, constructs and sends a disconnect
packet, closes the connection, and exits. This function never returns.
The error message should not contain a newline. The total length of the
message must not exceed 1024 bytes. */
void packet_disconnect(const char *fmt, ...);
void packet_disconnect(const char *fmt,...);
/* Sends a diagnostic message to the other side. This message
can be sent at any time (but not while constructing another message).
@ -139,31 +140,31 @@ void packet_disconnect(const char *fmt, ...);
must not exceed 1024 bytes. This will automatically call
packet_write_wait. If the remote side protocol flags do not indicate
that it supports SSH_MSG_DEBUG, this will do nothing. */
void packet_send_debug(const char *fmt, ...);
void packet_send_debug(const char *fmt,...);
/* Checks if there is any buffered output, and tries to write some of the
output. */
void packet_write_poll(void);
void packet_write_poll(void);
/* Waits until all pending output data has been written. */
void packet_write_wait(void);
void packet_write_wait(void);
/* Returns true if there is buffered data to write to the connection. */
int packet_have_data_to_write(void);
int packet_have_data_to_write(void);
/* Returns true if there is not too much data to write to the connection. */
int packet_not_very_much_data_to_write(void);
int packet_not_very_much_data_to_write(void);
/* maximum packet size, requested by client with SSH_CMSG_MAX_PACKET_SIZE */
extern int max_packet_size;
int packet_set_maxsize(int s);
int packet_set_maxsize(int s);
#define packet_get_maxsize() max_packet_size
/* Stores tty modes from the fd into current packet. */
void tty_make_modes(int fd);
void tty_make_modes(int fd);
/* Parses tty modes for the fd from the current packet. */
void tty_parse_modes(int fd, int *n_bytes_ptr);
void tty_parse_modes(int fd, int *n_bytes_ptr);
#define packet_integrity_check(payload_len, expected_len, type) \
do { \
@ -175,4 +176,4 @@ do { \
} \
} while (0)
#endif /* PACKET_H */
#endif /* PACKET_H */

390
pty.c
Просмотреть файл

@ -1,28 +1,28 @@
/*
pty.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Fri Mar 17 04:37:25 1995 ylo
Allocating a pseudo-terminal, and making it the controlling tty.
*/
*
* pty.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Fri Mar 17 04:37:25 1995 ylo
*
* Allocating a pseudo-terminal, and making it the controlling tty.
*
*/
#include "includes.h"
RCSID("$Id: pty.c,v 1.3 1999/11/15 04:40:55 damien Exp $");
RCSID("$Id: pty.c,v 1.4 1999/11/24 13:26:22 damien Exp $");
#include "pty.h"
#include "ssh.h"
#ifdef HAVE_PTY_H
#include <pty.h>
#endif /* HAVE_PTY_H */
#include "pty.h"
#include "ssh.h"
/* Pty allocated with _getpty gets broken if we do I_PUSH:es to it. */
#if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY)
#undef HAVE_DEV_PTMX
@ -34,235 +34,211 @@ RCSID("$Id: pty.c,v 1.3 1999/11/15 04:40:55 damien Exp $");
/* Allocates and opens a pty. Returns 0 if no pty could be allocated,
or nonzero if a pty was successfully allocated. On success, open file
descriptors for the pty and tty sides and the name of the tty side are
descriptors for the pty and tty sides and the name of the tty side are
returned (the buffer must be able to hold at least 64 characters). */
int pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
int
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
{
#ifdef HAVE_OPENPTY
/* openpty(3) exists in OSF/1 and some other os'es */
int i;
/* openpty(3) exists in OSF/1 and some other os'es */
int i;
i = openpty(ptyfd, ttyfd, namebuf, NULL, NULL);
if (i < 0)
{
error("openpty: %.100s", strerror(errno));
return 0;
}
return 1;
i = openpty(ptyfd, ttyfd, namebuf, NULL, NULL);
if (i < 0) {
error("openpty: %.100s", strerror(errno));
return 0;
}
return 1;
#else /* HAVE_OPENPTY */
#ifdef HAVE__GETPTY
/* _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates
more pty's automagically when needed */
char *slave;
/* _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
pty's automagically when needed */
char *slave;
slave = _getpty(ptyfd, O_RDWR, 0622, 0);
if (slave == NULL)
{
error("_getpty: %.100s", strerror(errno));
return 0;
}
strcpy(namebuf, slave);
/* Open the slave side. */
*ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
if (*ttyfd < 0)
{
error("%.200s: %.100s", namebuf, strerror(errno));
close(*ptyfd);
return 0;
}
return 1;
slave = _getpty(ptyfd, O_RDWR, 0622, 0);
if (slave == NULL) {
error("_getpty: %.100s", strerror(errno));
return 0;
}
strcpy(namebuf, slave);
/* Open the slave side. */
*ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
if (*ttyfd < 0) {
error("%.200s: %.100s", namebuf, strerror(errno));
close(*ptyfd);
return 0;
}
return 1;
#else /* HAVE__GETPTY */
#ifdef HAVE_DEV_PTMX
/* This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 also has
bsd-style ptys, but they simply do not work.) */
/* This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3
also has bsd-style ptys, but they simply do not work.) */
int ptm;
char *pts;
int ptm;
char *pts;
ptm = open("/dev/ptmx", O_RDWR|O_NOCTTY);
if (ptm < 0)
{
error("/dev/ptmx: %.100s", strerror(errno));
return 0;
}
if (grantpt(ptm) < 0)
{
error("grantpt: %.100s", strerror(errno));
return 0;
}
if (unlockpt(ptm) < 0)
{
error("unlockpt: %.100s", strerror(errno));
return 0;
}
pts = ptsname(ptm);
if (pts == NULL)
error("Slave pty side name could not be obtained.");
strcpy(namebuf, pts);
*ptyfd = ptm;
/* Open the slave side. */
*ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
if (*ttyfd < 0)
{
error("%.100s: %.100s", namebuf, strerror(errno));
close(*ptyfd);
return 0;
}
/* Push the appropriate streams modules, as described in Solaris pts(7). */
if (ioctl(*ttyfd, I_PUSH, "ptem") < 0)
error("ioctl I_PUSH ptem: %.100s", strerror(errno));
if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0)
error("ioctl I_PUSH ldterm: %.100s", strerror(errno));
if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0)
error("ioctl I_PUSH ttcompat: %.100s", strerror(errno));
return 1;
ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY);
if (ptm < 0) {
error("/dev/ptmx: %.100s", strerror(errno));
return 0;
}
if (grantpt(ptm) < 0) {
error("grantpt: %.100s", strerror(errno));
return 0;
}
if (unlockpt(ptm) < 0) {
error("unlockpt: %.100s", strerror(errno));
return 0;
}
pts = ptsname(ptm);
if (pts == NULL)
error("Slave pty side name could not be obtained.");
strcpy(namebuf, pts);
*ptyfd = ptm;
/* Open the slave side. */
*ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
if (*ttyfd < 0) {
error("%.100s: %.100s", namebuf, strerror(errno));
close(*ptyfd);
return 0;
}
/* Push the appropriate streams modules, as described in Solaris
pts(7). */
if (ioctl(*ttyfd, I_PUSH, "ptem") < 0)
error("ioctl I_PUSH ptem: %.100s", strerror(errno));
if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0)
error("ioctl I_PUSH ldterm: %.100s", strerror(errno));
if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0)
error("ioctl I_PUSH ttcompat: %.100s", strerror(errno));
return 1;
#else /* HAVE_DEV_PTMX */
#ifdef HAVE_DEV_PTS_AND_PTC
/* AIX-style pty code. */
const char *name;
/* AIX-style pty code. */
const char *name;
*ptyfd = open("/dev/ptc", O_RDWR|O_NOCTTY);
if (*ptyfd < 0)
{
error("Could not open /dev/ptc: %.100s", strerror(errno));
return 0;
}
name = ttyname(*ptyfd);
if (!name)
fatal("Open of /dev/ptc returns device for which ttyname fails.");
strcpy(namebuf, name);
*ttyfd = open(name, O_RDWR|O_NOCTTY);
if (*ttyfd < 0)
{
error("Could not open pty slave side %.100s: %.100s",
name, strerror(errno));
close(*ptyfd);
return 0;
}
return 1;
#else /* HAVE_DEV_PTS_AND_PTC */
/* BSD-style pty code. */
char buf[64];
int i;
const char *ptymajors =
"pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
const char *ptyminors = "0123456789abcdef";
int num_minors = strlen(ptyminors);
int num_ptys = strlen(ptymajors) * num_minors;
for (i = 0; i < num_ptys; i++)
{
snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors],
ptyminors[i % num_minors]);
*ptyfd = open(buf, O_RDWR|O_NOCTTY);
if (*ptyfd < 0)
continue;
snprintf(namebuf, sizeof buf, "/dev/tty%c%c", ptymajors[i / num_minors],
ptyminors[i % num_minors]);
/* Open the slave side. */
*ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
if (*ttyfd < 0)
{
error("%.100s: %.100s", namebuf, strerror(errno));
close(*ptyfd);
return 0;
*ptyfd = open("/dev/ptc", O_RDWR | O_NOCTTY);
if (*ptyfd < 0) {
error("Could not open /dev/ptc: %.100s", strerror(errno));
return 0;
}
return 1;
}
return 0;
name = ttyname(*ptyfd);
if (!name)
fatal("Open of /dev/ptc returns device for which ttyname fails.");
strcpy(namebuf, name);
*ttyfd = open(name, O_RDWR | O_NOCTTY);
if (*ttyfd < 0) {
error("Could not open pty slave side %.100s: %.100s",
name, strerror(errno));
close(*ptyfd);
return 0;
}
return 1;
#else /* HAVE_DEV_PTS_AND_PTC */
/* BSD-style pty code. */
char buf[64];
int i;
const char *ptymajors =
"pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
const char *ptyminors = "0123456789abcdef";
int num_minors = strlen(ptyminors);
int num_ptys = strlen(ptymajors) * num_minors;
for (i = 0; i < num_ptys; i++) {
snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors],
ptyminors[i % num_minors]);
*ptyfd = open(buf, O_RDWR | O_NOCTTY);
if (*ptyfd < 0)
continue;
snprintf(namebuf, sizeof buf, "/dev/tty%c%c", ptymajors[i / num_minors],
ptyminors[i % num_minors]);
/* Open the slave side. */
*ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
if (*ttyfd < 0) {
error("%.100s: %.100s", namebuf, strerror(errno));
close(*ptyfd);
return 0;
}
return 1;
}
return 0;
#endif /* HAVE_DEV_PTS_AND_PTC */
#endif /* HAVE_DEV_PTMX */
#endif /* HAVE__GETPTY */
#endif /* HAVE_OPENPTY */
}
/* Releases the tty. Its ownership is returned to root, and permissions to
0666. */
/* Releases the tty. Its ownership is returned to root, and permissions to 0666. */
void pty_release(const char *ttyname)
void
pty_release(const char *ttyname)
{
if (chown(ttyname, (uid_t)0, (gid_t)0) < 0)
debug("chown %.100s 0 0 failed: %.100s", ttyname, strerror(errno));
if (chmod(ttyname, (mode_t)0666) < 0)
debug("chmod %.100s 0666 failed: %.100s", ttyname, strerror(errno));
if (chown(ttyname, (uid_t) 0, (gid_t) 0) < 0)
debug("chown %.100s 0 0 failed: %.100s", ttyname, strerror(errno));
if (chmod(ttyname, (mode_t) 0666) < 0)
debug("chmod %.100s 0666 failed: %.100s", ttyname, strerror(errno));
}
/* Makes the tty the processes controlling tty and sets it to sane modes. */
void pty_make_controlling_tty(int *ttyfd, const char *ttyname)
void
pty_make_controlling_tty(int *ttyfd, const char *ttyname)
{
int fd;
int fd;
/* First disconnect from the old controlling tty. */
/* First disconnect from the old controlling tty. */
#ifdef TIOCNOTTY
fd = open("/dev/tty", O_RDWR|O_NOCTTY);
if (fd >= 0)
{
(void)ioctl(fd, TIOCNOTTY, NULL);
close(fd);
}
fd = open("/dev/tty", O_RDWR | O_NOCTTY);
if (fd >= 0) {
(void) ioctl(fd, TIOCNOTTY, NULL);
close(fd);
}
#endif /* TIOCNOTTY */
if (setsid() < 0)
error("setsid: %.100s", strerror(errno));
/* Verify that we are successfully disconnected from the controlling tty. */
fd = open("/dev/tty", O_RDWR|O_NOCTTY);
if (fd >= 0)
{
error("Failed to disconnect from controlling tty.");
close(fd);
}
if (setsid() < 0)
error("setsid: %.100s", strerror(errno));
/* Make it our controlling tty. */
/* Verify that we are successfully disconnected from the
controlling tty. */
fd = open("/dev/tty", O_RDWR | O_NOCTTY);
if (fd >= 0) {
error("Failed to disconnect from controlling tty.");
close(fd);
}
/* Make it our controlling tty. */
#ifdef TIOCSCTTY
debug("Setting controlling tty using TIOCSCTTY.");
/* We ignore errors from this, because HPSUX defines TIOCSCTTY, but returns
EINVAL with these arguments, and there is absolutely no documentation. */
ioctl(*ttyfd, TIOCSCTTY, NULL);
debug("Setting controlling tty using TIOCSCTTY.");
/* We ignore errors from this, because HPSUX defines TIOCSCTTY,
but returns EINVAL with these arguments, and there is
absolutely no documentation. */
ioctl(*ttyfd, TIOCSCTTY, NULL);
#endif /* TIOCSCTTY */
fd = open(ttyname, O_RDWR);
if (fd < 0)
error("%.100s: %.100s", ttyname, strerror(errno));
else
close(fd);
fd = open(ttyname, O_RDWR);
if (fd < 0)
error("%.100s: %.100s", ttyname, strerror(errno));
else
close(fd);
/* Verify that we now have a controlling tty. */
fd = open("/dev/tty", O_WRONLY);
if (fd < 0)
error("open /dev/tty failed - could not set controlling tty: %.100s",
strerror(errno));
else
{
close(fd);
}
/* Verify that we now have a controlling tty. */
fd = open("/dev/tty", O_WRONLY);
if (fd < 0)
error("open /dev/tty failed - could not set controlling tty: %.100s",
strerror(errno));
else {
close(fd);
}
}
/* Changes the window size associated with the pty. */
void pty_change_window_size(int ptyfd, int row, int col,
int xpixel, int ypixel)
void
pty_change_window_size(int ptyfd, int row, int col,
int xpixel, int ypixel)
{
struct winsize w;
w.ws_row = row;
w.ws_col = col;
w.ws_xpixel = xpixel;
w.ws_ypixel = ypixel;
(void)ioctl(ptyfd, TIOCSWINSZ, &w);
struct winsize w;
w.ws_row = row;
w.ws_col = col;
w.ws_xpixel = xpixel;
w.ws_ypixel = ypixel;
(void) ioctl(ptyfd, TIOCSWINSZ, &w);
}

46
pty.h
Просмотреть файл

@ -1,40 +1,40 @@
/*
*
* pty.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Fri Mar 17 05:03:28 1995 ylo
*
* Functions for allocating a pseudo-terminal and making it the controlling
* tty.
*/
pty.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Fri Mar 17 05:03:28 1995 ylo
Functions for allocating a pseudo-terminal and making it the controlling
tty.
*/
/* RCSID("$Id: pty.h,v 1.1 1999/10/27 03:42:44 damien Exp $"); */
/* RCSID("$Id: pty.h,v 1.2 1999/11/24 13:26:22 damien Exp $"); */
#ifndef PTY_H
#define PTY_H
/* Allocates and opens a pty. Returns 0 if no pty could be allocated,
or nonzero if a pty was successfully allocated. On success, open file
descriptors for the pty and tty sides and the name of the tty side are
descriptors for the pty and tty sides and the name of the tty side are
returned (the buffer must be able to hold at least 64 characters). */
int pty_allocate(int *ptyfd, int *ttyfd, char *ttyname);
int pty_allocate(int *ptyfd, int *ttyfd, char *ttyname);
/* Releases the tty. Its ownership is returned to root, and permissions to
0666. */
void pty_release(const char *ttyname);
void pty_release(const char *ttyname);
/* Makes the tty the processes controlling tty and sets it to sane modes.
/* Makes the tty the processes controlling tty and sets it to sane modes.
This may need to reopen the tty to get rid of possible eavesdroppers. */
void pty_make_controlling_tty(int *ttyfd, const char *ttyname);
void pty_make_controlling_tty(int *ttyfd, const char *ttyname);
/* Changes the window size associated with the pty. */
void pty_change_window_size(int ptyfd, int row, int col,
int xpixel, int ypixel);
void
pty_change_window_size(int ptyfd, int row, int col,
int xpixel, int ypixel);
#endif /* PTY_H */
#endif /* PTY_H */

353
radix.c
Просмотреть файл

@ -1,101 +1,105 @@
/*
radix.c
* radix.c
*
* base-64 encoding pinched from lynx2-7-2, who pinched it from rpem.
* Originally written by Mark Riordan 12 August 1990 and 17 Feb 1991
* and placed in the public domain.
*
* Dug Song <dugsong@UMICH.EDU>
*/
base-64 encoding pinched from lynx2-7-2, who pinched it from rpem.
Originally written by Mark Riordan 12 August 1990 and 17 Feb 1991
and placed in the public domain.
Dug Song <dugsong@UMICH.EDU>
*/
#include "includes.h"
#ifdef AFS
#include <krb.h>
char six2pr[64] = {
'A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9','+','/'
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
unsigned char pr2six[256];
int uuencode(unsigned char *bufin, unsigned int nbytes, char *bufcoded)
int
uuencode(unsigned char *bufin, unsigned int nbytes, char *bufcoded)
{
/* ENC is the basic 1 character encoding function to make a char printing */
/* ENC is the basic 1 character encoding function to make a char printing */
#define ENC(c) six2pr[c]
register char *outptr = bufcoded;
unsigned int i;
for (i=0; i<nbytes; i += 3) {
*(outptr++) = ENC(*bufin >> 2); /* c1 */
*(outptr++) = ENC(((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)); /*c2*/
*(outptr++) = ENC(((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03));/*c3*/
*(outptr++) = ENC(bufin[2] & 077); /* c4 */
bufin += 3;
}
if (i == nbytes+1) {
outptr[-1] = '=';
} else if (i == nbytes+2) {
outptr[-1] = '=';
outptr[-2] = '=';
}
*outptr = '\0';
return(outptr - bufcoded);
register char *outptr = bufcoded;
unsigned int i;
for (i = 0; i < nbytes; i += 3) {
*(outptr++) = ENC(*bufin >> 2); /* c1 */
*(outptr++) = ENC(((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)); /* c2 */
*(outptr++) = ENC(((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03)); /* c3 */
*(outptr++) = ENC(bufin[2] & 077); /* c4 */
bufin += 3;
}
if (i == nbytes + 1) {
outptr[-1] = '=';
} else if (i == nbytes + 2) {
outptr[-1] = '=';
outptr[-2] = '=';
}
*outptr = '\0';
return (outptr - bufcoded);
}
int uudecode(const char *bufcoded, unsigned char *bufplain, int outbufsize)
int
uudecode(const char *bufcoded, unsigned char *bufplain, int outbufsize)
{
/* single character decode */
/* single character decode */
#define DEC(c) pr2six[(unsigned char)c]
#define MAXVAL 63
static int first = 1;
int nbytesdecoded, j;
const char *bufin = bufcoded;
register unsigned char *bufout = bufplain;
register int nprbytes;
/* If this is the first call, initialize the mapping table. */
if (first) {
first = 0;
for(j=0; j<256; j++) pr2six[j] = MAXVAL+1;
for(j=0; j<64; j++) pr2six[(unsigned char)six2pr[j]] = (unsigned char)j;
}
/* Strip leading whitespace. */
while (*bufcoded==' ' || *bufcoded == '\t') bufcoded++;
/* Figure out how many characters are in the input buffer.
If this would decode into more bytes than would fit into
the output buffer, adjust the number of input bytes downwards. */
bufin = bufcoded;
while (DEC(*(bufin++)) <= MAXVAL);
nprbytes = bufin - bufcoded - 1;
nbytesdecoded = ((nprbytes+3)/4) * 3;
if (nbytesdecoded > outbufsize)
nprbytes = (outbufsize*4)/3;
bufin = bufcoded;
while (nprbytes > 0) {
*(bufout++) = (unsigned char) (DEC(*bufin) << 2 | DEC(bufin[1]) >> 4);
*(bufout++) = (unsigned char) (DEC(bufin[1]) << 4 | DEC(bufin[2]) >> 2);
*(bufout++) = (unsigned char) (DEC(bufin[2]) << 6 | DEC(bufin[3]));
bufin += 4;
nprbytes -= 4;
}
if (nprbytes & 03) {
if (DEC(bufin[-2]) > MAXVAL)
nbytesdecoded -= 2;
else
nbytesdecoded -= 1;
}
return(nbytesdecoded);
static int first = 1;
int nbytesdecoded, j;
const char *bufin = bufcoded;
register unsigned char *bufout = bufplain;
register int nprbytes;
/* If this is the first call, initialize the mapping table. */
if (first) {
first = 0;
for (j = 0; j < 256; j++)
pr2six[j] = MAXVAL + 1;
for (j = 0; j < 64; j++)
pr2six[(unsigned char) six2pr[j]] = (unsigned char) j;
}
/* Strip leading whitespace. */
while (*bufcoded == ' ' || *bufcoded == '\t')
bufcoded++;
/* Figure out how many characters are in the input buffer. If this
would decode into more bytes than would fit into the output
buffer, adjust the number of input bytes downwards. */
bufin = bufcoded;
while (DEC(*(bufin++)) <= MAXVAL);
nprbytes = bufin - bufcoded - 1;
nbytesdecoded = ((nprbytes + 3) / 4) * 3;
if (nbytesdecoded > outbufsize)
nprbytes = (outbufsize * 4) / 3;
bufin = bufcoded;
while (nprbytes > 0) {
*(bufout++) = (unsigned char) (DEC(*bufin) << 2 | DEC(bufin[1]) >> 4);
*(bufout++) = (unsigned char) (DEC(bufin[1]) << 4 | DEC(bufin[2]) >> 2);
*(bufout++) = (unsigned char) (DEC(bufin[2]) << 6 | DEC(bufin[3]));
bufin += 4;
nprbytes -= 4;
}
if (nprbytes & 03) {
if (DEC(bufin[-2]) > MAXVAL)
nbytesdecoded -= 2;
else
nbytesdecoded -= 1;
}
return (nbytesdecoded);
}
typedef unsigned char my_u_char;
@ -156,103 +160,124 @@ typedef unsigned short my_u_short;
}
int creds_to_radix(CREDENTIALS *creds, unsigned char *buf)
int
creds_to_radix(CREDENTIALS *creds, unsigned char *buf)
{
char *p, *s;
int len;
char temp[2048];
p = temp;
*p++ = 1; /* version */
s = creds->service; while (*s) *p++ = *s++; *p++ = *s;
s = creds->instance; while (*s) *p++ = *s++; *p++ = *s;
s = creds->realm; while (*s) *p++ = *s++; *p++ = *s;
char *p, *s;
int len;
char temp[2048];
s = creds->pname; while (*s) *p++ = *s++; *p++ = *s;
s = creds->pinst; while (*s) *p++ = *s++; *p++ = *s;
/* Null string to repeat the realm. */
*p++ = '\0';
p = temp;
*p++ = 1; /* version */
s = creds->service;
while (*s)
*p++ = *s++;
*p++ = *s;
s = creds->instance;
while (*s)
*p++ = *s++;
*p++ = *s;
s = creds->realm;
while (*s)
*p++ = *s++;
*p++ = *s;
PUTLONG(creds->issue_date,p);
{
unsigned int endTime ;
endTime = (unsigned int)krb_life_to_time(creds->issue_date,
creds->lifetime);
PUTLONG(endTime,p);
}
s = creds->pname;
while (*s)
*p++ = *s++;
*p++ = *s;
s = creds->pinst;
while (*s)
*p++ = *s++;
*p++ = *s;
/* Null string to repeat the realm. */
*p++ = '\0';
memcpy(p,&creds->session, sizeof(creds->session));
p += sizeof(creds->session);
PUTSHORT(creds->kvno,p);
PUTLONG(creds->ticket_st.length,p);
memcpy(p,creds->ticket_st.dat, creds->ticket_st.length);
p += creds->ticket_st.length;
len = p - temp;
PUTLONG(creds->issue_date, p);
{
unsigned int endTime;
endTime = (unsigned int) krb_life_to_time(creds->issue_date,
creds->lifetime);
PUTLONG(endTime, p);
}
return(uuencode(temp, len, buf));
memcpy(p, &creds->session, sizeof(creds->session));
p += sizeof(creds->session);
PUTSHORT(creds->kvno, p);
PUTLONG(creds->ticket_st.length, p);
memcpy(p, creds->ticket_st.dat, creds->ticket_st.length);
p += creds->ticket_st.length;
len = p - temp;
return (uuencode(temp, len, buf));
}
int radix_to_creds(const char *buf, CREDENTIALS *creds)
int
radix_to_creds(const char *buf, CREDENTIALS *creds)
{
char *p;
int len, tl;
char version;
char temp[2048];
if (!(len = uudecode(buf, temp, sizeof(temp))))
return 0;
p = temp;
char *p;
int len, tl;
char version;
char temp[2048];
/* check version and length! */
if (len < 1) return 0;
version = *p; p++; len--;
if (!(len = uudecode(buf, temp, sizeof(temp))))
return 0;
GETSTRING(creds->service, p, len);
GETSTRING(creds->instance, p, len);
GETSTRING(creds->realm, p, len);
GETSTRING(creds->pname, p, len);
GETSTRING(creds->pinst, p, len);
/* Ignore possibly different realm. */
while (*p && len) p++, len--;
if (len == 0) return 0;
p++, len--;
/* Enough space for remaining fixed-length parts? */
if (len < (4 + 4 + sizeof(creds->session) + 2 + 4))
return 0;
GETLONG(creds->issue_date,p);
len -= 4;
{
unsigned int endTime;
GETLONG(endTime,p);
len -= 4;
creds->lifetime = krb_time_to_life(creds->issue_date, endTime);
}
p = temp;
memcpy(&creds->session, p, sizeof(creds->session));
p += sizeof(creds->session);
len -= sizeof(creds->session);
GETSHORT(creds->kvno,p);
len -= 2;
GETLONG(creds->ticket_st.length,p);
len -= 4;
/* check version and length! */
if (len < 1)
return 0;
version = *p;
p++;
len--;
tl = creds->ticket_st.length;
if (tl < 0 || tl > len || tl > sizeof(creds->ticket_st.dat))
return 0;
memcpy(creds->ticket_st.dat, p, tl);
p += tl;
len -= tl;
return 1;
GETSTRING(creds->service, p, len);
GETSTRING(creds->instance, p, len);
GETSTRING(creds->realm, p, len);
GETSTRING(creds->pname, p, len);
GETSTRING(creds->pinst, p, len);
/* Ignore possibly different realm. */
while (*p && len)
p++, len--;
if (len == 0)
return 0;
p++, len--;
/* Enough space for remaining fixed-length parts? */
if (len < (4 + 4 + sizeof(creds->session) + 2 + 4))
return 0;
GETLONG(creds->issue_date, p);
len -= 4;
{
unsigned int endTime;
GETLONG(endTime, p);
len -= 4;
creds->lifetime = krb_time_to_life(creds->issue_date, endTime);
}
memcpy(&creds->session, p, sizeof(creds->session));
p += sizeof(creds->session);
len -= sizeof(creds->session);
GETSHORT(creds->kvno, p);
len -= 2;
GETLONG(creds->ticket_st.length, p);
len -= 4;
tl = creds->ticket_st.length;
if (tl < 0 || tl > len || tl > sizeof(creds->ticket_st.dat))
return 0;
memcpy(creds->ticket_st.dat, p, tl);
p += tl;
len -= tl;
return 1;
}
#endif /* AFS */

1059
readconf.c

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,118 +1,126 @@
/*
*
* readconf.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Sat Apr 22 00:25:29 1995 ylo
*
* Functions for reading the configuration file.
*
*/
readconf.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Sat Apr 22 00:25:29 1995 ylo
Functions for reading the configuration file.
*/
/* RCSID("$Id: readconf.h,v 1.3 1999/11/15 04:25:10 damien Exp $"); */
/* RCSID("$Id: readconf.h,v 1.4 1999/11/24 13:26:22 damien Exp $"); */
#ifndef READCONF_H
#define READCONF_H
/* Data structure for representing a forwarding request. */
typedef struct
{
int port; /* Port to forward. */
char *host; /* Host to connect. */
int host_port; /* Port to connect on host. */
} Forward;
typedef struct {
int port; /* Port to forward. */
char *host; /* Host to connect. */
int host_port; /* Port to connect on host. */
} Forward;
/* Data structure for representing option data. */
typedef struct
{
int forward_agent; /* Forward authentication agent. */
int forward_x11; /* Forward X11 display. */
int gateway_ports; /* Allow remote connects to forwarded ports. */
int use_privileged_port; /* Don't use privileged port if false. */
int rhosts_authentication; /* Try rhosts authentication. */
int rhosts_rsa_authentication;/* Try rhosts with RSA authentication. */
int rsa_authentication; /* Try RSA authentication. */
typedef struct {
int forward_agent; /* Forward authentication agent. */
int forward_x11; /* Forward X11 display. */
int gateway_ports; /* Allow remote connects to forwarded ports. */
int use_privileged_port; /* Don't use privileged port if false. */
int rhosts_authentication; /* Try rhosts authentication. */
int rhosts_rsa_authentication; /* Try rhosts with RSA
* authentication. */
int rsa_authentication; /* Try RSA authentication. */
int skey_authentication; /* Try S/Key or TIS authentication. */
#ifdef KRB4
int kerberos_authentication; /* Try Kerberos authentication. */
int kerberos_authentication; /* Try Kerberos
* authentication. */
#endif
#ifdef AFS
int kerberos_tgt_passing; /* Try Kerberos tgt passing. */
int afs_token_passing; /* Try AFS token passing. */
int kerberos_tgt_passing; /* Try Kerberos tgt passing. */
int afs_token_passing; /* Try AFS token passing. */
#endif
int password_authentication; /* Try password authentication. */
int fallback_to_rsh; /* Use rsh if cannot connect with ssh. */
int use_rsh; /* Always use rsh (don\'t try ssh). */
int batch_mode; /* Batch mode: do not ask for passwords. */
int check_host_ip; /* Also keep track of keys for IP address */
int strict_host_key_checking; /* Strict host key checking. */
int compression; /* Compress packets in both directions. */
int compression_level; /* Compression level 1 (fast) to 9 (best). */
int keepalives; /* Set SO_KEEPALIVE. */
LogLevel log_level; /* Level for logging. */
int password_authentication; /* Try password
* authentication. */
int fallback_to_rsh;/* Use rsh if cannot connect with ssh. */
int use_rsh; /* Always use rsh (don\'t try ssh). */
int batch_mode; /* Batch mode: do not ask for passwords. */
int check_host_ip; /* Also keep track of keys for IP address */
int strict_host_key_checking; /* Strict host key checking. */
int compression; /* Compress packets in both directions. */
int compression_level; /* Compression level 1 (fast) to 9
* (best). */
int keepalives; /* Set SO_KEEPALIVE. */
LogLevel log_level; /* Level for logging. */
int port; /* Port to connect. */
int connection_attempts; /* Max attempts (seconds) before giving up */
int number_of_password_prompts; /* Max number of password prompts. */
int cipher; /* Cipher to use. */
char *hostname; /* Real host to connect. */
char *proxy_command; /* Proxy command for connecting the host. */
char *user; /* User to log in as. */
int escape_char; /* Escape character; -2 = none */
int port; /* Port to connect. */
int connection_attempts; /* Max attempts (seconds) before
* giving up */
int number_of_password_prompts; /* Max number of password
* prompts. */
int cipher; /* Cipher to use. */
char *hostname; /* Real host to connect. */
char *proxy_command; /* Proxy command for connecting the host. */
char *user; /* User to log in as. */
int escape_char; /* Escape character; -2 = none */
char *system_hostfile; /* Path for /etc/ssh_known_hosts. */
char *user_hostfile; /* Path for $HOME/.ssh/known_hosts. */
char *system_hostfile;/* Path for /etc/ssh_known_hosts. */
char *user_hostfile; /* Path for $HOME/.ssh/known_hosts. */
int num_identity_files; /* Number of files for RSA identities. */
char *identity_files[SSH_MAX_IDENTITY_FILES];
int num_identity_files; /* Number of files for RSA identities. */
char *identity_files[SSH_MAX_IDENTITY_FILES];
/* Local TCP/IP forward requests. */
int num_local_forwards;
Forward local_forwards[SSH_MAX_FORWARDS_PER_DIRECTION];
/* Local TCP/IP forward requests. */
int num_local_forwards;
Forward local_forwards[SSH_MAX_FORWARDS_PER_DIRECTION];
/* Remote TCP/IP forward requests. */
int num_remote_forwards;
Forward remote_forwards[SSH_MAX_FORWARDS_PER_DIRECTION];
} Options;
/* Remote TCP/IP forward requests. */
int num_remote_forwards;
Forward remote_forwards[SSH_MAX_FORWARDS_PER_DIRECTION];
} Options;
/* Initializes options to special values that indicate that they have not
yet been set. Read_config_file will only set options with this value.
Options are processed in the following order: command line, user config
file, system config file. Last, fill_default_options is called. */
void initialize_options(Options *options);
void initialize_options(Options * options);
/* Called after processing other sources of option data, this fills those
options for which no value has been specified with their default values. */
void fill_default_options(Options *options);
void fill_default_options(Options * options);
/* Processes a single option line as used in the configuration files.
/* Processes a single option line as used in the configuration files.
This only sets those values that have not already been set.
Returns 0 for legal options */
int process_config_line(Options *options, const char *host,
char *line, const char *filename, int linenum,
int *activep);
int
process_config_line(Options * options, const char *host,
char *line, const char *filename, int linenum,
int *activep);
/* Reads the config file and modifies the options accordingly. Options should
already be initialized before this call. This never returns if there
is an error. If the file does not exist, this returns immediately. */
void read_config_file(const char *filename, const char *host,
Options *options);
void
read_config_file(const char *filename, const char *host,
Options * options);
/* Adds a local TCP/IP port forward to options. Never returns if there
is an error. */
void add_local_forward(Options *options, int port, const char *host,
int host_port);
void
add_local_forward(Options * options, int port, const char *host,
int host_port);
/* Adds a remote TCP/IP port forward to options. Never returns if there
is an error. */
void add_remote_forward(Options *options, int port, const char *host,
int host_port);
void
add_remote_forward(Options * options, int port, const char *host,
int host_port);
#endif /* READCONF_H */
#endif /* READCONF_H */

Просмотреть файл

@ -1,20 +1,20 @@
/*
readpass.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Mon Jul 10 22:08:59 1995 ylo
Functions for reading passphrases and passwords.
*/
*
* readpass.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Mon Jul 10 22:08:59 1995 ylo
*
* Functions for reading passphrases and passwords.
*
*/
#include "includes.h"
RCSID("$Id: readpass.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
RCSID("$Id: readpass.c,v 1.2 1999/11/24 13:26:22 damien Exp $");
#include "xmalloc.h"
#include "ssh.h"
@ -23,92 +23,91 @@ RCSID("$Id: readpass.c,v 1.1 1999/10/27 03:42:44 damien Exp $");
static struct termios saved_tio;
/* Old interrupt signal handler for read_passphrase. */
static void (*old_handler)(int sig) = NULL;
static void (*old_handler) (int sig) = NULL;
/* Interrupt signal handler for read_passphrase. */
void intr_handler(int sig)
void
intr_handler(int sig)
{
/* Restore terminal modes. */
tcsetattr(fileno(stdin), TCSANOW, &saved_tio);
/* Restore the old signal handler. */
signal(sig, old_handler);
/* Resend the signal, with the old handler. */
kill(getpid(), sig);
/* Restore terminal modes. */
tcsetattr(fileno(stdin), TCSANOW, &saved_tio);
/* Restore the old signal handler. */
signal(sig, old_handler);
/* Resend the signal, with the old handler. */
kill(getpid(), sig);
}
/* Reads a passphrase from /dev/tty with echo turned off. Returns the
passphrase (allocated with xmalloc). Exits if EOF is encountered.
/* Reads a passphrase from /dev/tty with echo turned off. Returns the
passphrase (allocated with xmalloc). Exits if EOF is encountered.
The passphrase if read from stdin if from_stdin is true (as is the
case with ssh-keygen). */
char *read_passphrase(const char *prompt, int from_stdin)
char *
read_passphrase(const char *prompt, int from_stdin)
{
char buf[1024], *cp;
struct termios tio;
FILE *f;
if (from_stdin)
f = stdin;
else
{
/* Read the passphrase from /dev/tty to make it possible to ask it even
when stdin has been redirected. */
f = fopen("/dev/tty", "r");
if (!f)
{
/* No controlling terminal and no DISPLAY. Nowhere to read. */
fprintf(stderr, "You have no controlling tty and no DISPLAY. Cannot read passphrase.\n");
exit(1);
char buf[1024], *cp;
struct termios tio;
FILE *f;
if (from_stdin)
f = stdin;
else {
/* Read the passphrase from /dev/tty to make it possible
to ask it even when stdin has been redirected. */
f = fopen("/dev/tty", "r");
if (!f) {
/* No controlling terminal and no DISPLAY. Nowhere to read. */
fprintf(stderr, "You have no controlling tty and no DISPLAY. Cannot read passphrase.\n");
exit(1);
}
}
}
/* Display the prompt (on stderr because stdout might be redirected). */
fflush(stdout);
fprintf(stderr, "%s", prompt);
fflush(stderr);
/* Display the prompt (on stderr because stdout might be redirected). */
fflush(stdout);
fprintf(stderr, "%s", prompt);
fflush(stderr);
/* Get terminal modes. */
tcgetattr(fileno(f), &tio);
saved_tio = tio;
/* Save signal handler and set the new handler. */
old_handler = signal(SIGINT, intr_handler);
/* Get terminal modes. */
tcgetattr(fileno(f), &tio);
saved_tio = tio;
/* Save signal handler and set the new handler. */
old_handler = signal(SIGINT, intr_handler);
/* Set new terminal modes disabling all echo. */
tio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
tcsetattr(fileno(f), TCSANOW, &tio);
/* Set new terminal modes disabling all echo. */
tio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
tcsetattr(fileno(f), TCSANOW, &tio);
/* Read the passphrase from the terminal. */
if (fgets(buf, sizeof(buf), f) == NULL)
{
/* Got EOF. Just exit. */
/* Restore terminal modes. */
tcsetattr(fileno(f), TCSANOW, &saved_tio);
/* Restore the signal handler. */
signal(SIGINT, old_handler);
/* Print a newline (the prompt probably didn\'t have one). */
fprintf(stderr, "\n");
/* Close the file. */
if (f != stdin)
fclose(f);
exit(1);
}
/* Restore terminal modes. */
tcsetattr(fileno(f), TCSANOW, &saved_tio);
/* Restore the signal handler. */
(void)signal(SIGINT, old_handler);
/* Remove newline from the passphrase. */
if (strchr(buf, '\n'))
*strchr(buf, '\n') = 0;
/* Allocate a copy of the passphrase. */
cp = xstrdup(buf);
/* Clear the buffer so we don\'t leave copies of the passphrase laying
around. */
memset(buf, 0, sizeof(buf));
/* Print a newline since the prompt probably didn\'t have one. */
fprintf(stderr, "\n");
/* Close the file. */
if (f != stdin)
fclose(f);
return cp;
/* Read the passphrase from the terminal. */
if (fgets(buf, sizeof(buf), f) == NULL) {
/* Got EOF. Just exit. */
/* Restore terminal modes. */
tcsetattr(fileno(f), TCSANOW, &saved_tio);
/* Restore the signal handler. */
signal(SIGINT, old_handler);
/* Print a newline (the prompt probably didn\'t have one). */
fprintf(stderr, "\n");
/* Close the file. */
if (f != stdin)
fclose(f);
exit(1);
}
/* Restore terminal modes. */
tcsetattr(fileno(f), TCSANOW, &saved_tio);
/* Restore the signal handler. */
(void) signal(SIGINT, old_handler);
/* Remove newline from the passphrase. */
if (strchr(buf, '\n'))
*strchr(buf, '\n') = 0;
/* Allocate a copy of the passphrase. */
cp = xstrdup(buf);
/* Clear the buffer so we don\'t leave copies of the passphrase
laying around. */
memset(buf, 0, sizeof(buf));
/* Print a newline since the prompt probably didn\'t have one. */
fprintf(stderr, "\n");
/* Close the file. */
if (f != stdin)
fclose(f);
return cp;
}

215
rsa.c
Просмотреть файл

@ -1,41 +1,41 @@
/*
rsa.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Fri Mar 3 22:07:06 1995 ylo
Description of the RSA algorithm can be found e.g. from the following sources:
Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994.
Jennifer Seberry and Josed Pieprzyk: Cryptography: An Introduction to
Computer Security. Prentice-Hall, 1989.
Man Young Rhee: Cryptography and Secure Data Communications. McGraw-Hill,
1994.
R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic Communications
System and Method. US Patent 4,405,829, 1983.
Hans Riesel: Prime Numbers and Computer Methods for Factorization.
Birkhauser, 1994.
The RSA Frequently Asked Questions document by RSA Data Security, Inc., 1995.
RSA in 3 lines of perl by Adam Back <aba@atlax.ex.ac.uk>, 1995, as included
below:
gone - had to be deleted - what a pity
*
* rsa.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Fri Mar 3 22:07:06 1995 ylo
*
* Description of the RSA algorithm can be found e.g. from the following sources:
*
* Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994.
*
* Jennifer Seberry and Josed Pieprzyk: Cryptography: An Introduction to
* Computer Security. Prentice-Hall, 1989.
*
* Man Young Rhee: Cryptography and Secure Data Communications. McGraw-Hill,
* 1994.
*
* R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic Communications
* System and Method. US Patent 4,405,829, 1983.
*
* Hans Riesel: Prime Numbers and Computer Methods for Factorization.
* Birkhauser, 1994.
*
* The RSA Frequently Asked Questions document by RSA Data Security, Inc., 1995.
*
* RSA in 3 lines of perl by Adam Back <aba@atlax.ex.ac.uk>, 1995, as included
* below:
*
* [gone - had to be deleted - what a pity]
*
*/
#include "includes.h"
RCSID("$Id: rsa.c,v 1.3 1999/11/08 23:35:52 damien Exp $");
RCSID("$Id: rsa.c,v 1.4 1999/11/24 13:26:22 damien Exp $");
#include "rsa.h"
#include "ssh.h"
@ -46,13 +46,13 @@ int rsa_verbose = 1;
int
rsa_alive()
{
RSA *key;
RSA *key;
key = RSA_generate_key(32, 3, NULL, NULL);
if (key == NULL)
return (0);
RSA_free(key);
return (1);
key = RSA_generate_key(32, 3, NULL, NULL);
if (key == NULL)
return (0);
RSA_free(key);
return (1);
}
/* Generates RSA public and private keys. This initializes the data
@ -62,101 +62,100 @@ rsa_alive()
void
rsa_generate_key(RSA *prv, RSA *pub, unsigned int bits)
{
RSA *key;
RSA *key;
if (rsa_verbose) {
printf("Generating RSA keys: ");
fflush(stdout);
}
if (rsa_verbose) {
printf("Generating RSA keys: ");
fflush(stdout);
}
key = RSA_generate_key(bits, 35, NULL, NULL);
if (key == NULL)
fatal("rsa_generate_key: key generation failed.");
key = RSA_generate_key(bits, 35, NULL, NULL);
if (key == NULL)
fatal("rsa_generate_key: key generation failed.");
/* Copy public key parameters */
pub->n = BN_new();
BN_copy(pub->n, key->n);
pub->e = BN_new();
BN_copy(pub->e, key->e);
/* Copy public key parameters */
pub->n = BN_new();
BN_copy(pub->n, key->n);
pub->e = BN_new();
BN_copy(pub->e, key->e);
/* Copy private key parameters */
prv->n = BN_new();
BN_copy(prv->n, key->n);
prv->e = BN_new();
BN_copy(prv->e, key->e);
prv->d = BN_new();
BN_copy(prv->d, key->d);
prv->p = BN_new();
BN_copy(prv->p, key->p);
prv->q = BN_new();
BN_copy(prv->q, key->q);
/* Copy private key parameters */
prv->n = BN_new();
BN_copy(prv->n, key->n);
prv->e = BN_new();
BN_copy(prv->e, key->e);
prv->d = BN_new();
BN_copy(prv->d, key->d);
prv->p = BN_new();
BN_copy(prv->p, key->p);
prv->q = BN_new();
BN_copy(prv->q, key->q);
prv->dmp1 = BN_new();
BN_copy(prv->dmp1, key->dmp1);
prv->dmp1 = BN_new();
BN_copy(prv->dmp1, key->dmp1);
prv->dmq1 = BN_new();
BN_copy(prv->dmq1, key->dmq1);
prv->dmq1 = BN_new();
BN_copy(prv->dmq1, key->dmq1);
prv->iqmp = BN_new();
BN_copy(prv->iqmp, key->iqmp);
prv->iqmp = BN_new();
BN_copy(prv->iqmp, key->iqmp);
RSA_free(key);
RSA_free(key);
if (rsa_verbose)
printf("Key generation complete.\n");
if (rsa_verbose)
printf("Key generation complete.\n");
}
void
rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA* key)
rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
{
char *inbuf, *outbuf;
int len, ilen, olen;
char *inbuf, *outbuf;
int len, ilen, olen;
if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e))
fatal("rsa_public_encrypt() exponent too small or not odd");
if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e))
fatal("rsa_public_encrypt() exponent too small or not odd");
olen = BN_num_bytes(key->n);
outbuf = xmalloc(olen);
olen = BN_num_bytes(key->n);
outbuf = xmalloc(olen);
ilen = BN_num_bytes(in);
inbuf = xmalloc(ilen);
BN_bn2bin(in, inbuf);
ilen = BN_num_bytes(in);
inbuf = xmalloc(ilen);
BN_bn2bin(in, inbuf);
if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key,
RSA_PKCS1_PADDING)) <= 0)
fatal("rsa_public_encrypt() failed");
if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key,
RSA_PKCS1_PADDING)) <= 0)
fatal("rsa_public_encrypt() failed");
BN_bin2bn(outbuf, len, out);
BN_bin2bn(outbuf, len, out);
memset(outbuf, 0, olen);
memset(inbuf, 0, ilen);
xfree(outbuf);
xfree(inbuf);
memset(outbuf, 0, olen);
memset(inbuf, 0, ilen);
xfree(outbuf);
xfree(inbuf);
}
void
rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
{
char *inbuf, *outbuf;
int len, ilen, olen;
char *inbuf, *outbuf;
int len, ilen, olen;
olen = BN_num_bytes(key->n);
outbuf = xmalloc(olen);
olen = BN_num_bytes(key->n);
outbuf = xmalloc(olen);
ilen = BN_num_bytes(in);
inbuf = xmalloc(ilen);
BN_bn2bin(in, inbuf);
ilen = BN_num_bytes(in);
inbuf = xmalloc(ilen);
BN_bn2bin(in, inbuf);
if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key,
RSA_SSLV23_PADDING)) <= 0)
fatal("rsa_private_decrypt() failed");
if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key,
RSA_SSLV23_PADDING)) <= 0)
fatal("rsa_private_decrypt() failed");
BN_bin2bn(outbuf, len, out);
BN_bin2bn(outbuf, len, out);
memset(outbuf, 0, olen);
memset(inbuf, 0, ilen);
xfree(outbuf);
xfree(inbuf);
memset(outbuf, 0, olen);
memset(inbuf, 0, ilen);
xfree(outbuf);
xfree(inbuf);
}
/* Set whether to output verbose messages during key generation. */
@ -164,5 +163,5 @@ rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
void
rsa_set_verbose(int verbose)
{
rsa_verbose = verbose;
rsa_verbose = verbose;
}

41
rsa.h
Просмотреть файл

@ -1,24 +1,25 @@
/*
rsa.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Fri Mar 3 22:01:06 1995 ylo
RSA key generation, encryption and decryption.
*
* rsa.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Fri Mar 3 22:01:06 1995 ylo
*
* RSA key generation, encryption and decryption.
*
*/
/* RCSID("$Id: rsa.h,v 1.3 1999/11/10 23:40:23 damien Exp $"); */
#include "config.h"
/* RCSID("$Id: rsa.h,v 1.4 1999/11/24 13:26:22 damien Exp $"); */
#ifndef RSA_H
#define RSA_H
#include "config.h"
#ifdef HAVE_OPENSSL
#include <openssl/bn.h>
#include <openssl/rsa.h>
@ -30,15 +31,15 @@ RSA key generation, encryption and decryption.
#endif
/* Calls SSL RSA_generate_key, only copies to prv and pub */
void rsa_generate_key(RSA *prv, RSA *pub, unsigned int bits);
void rsa_generate_key(RSA * prv, RSA * pub, unsigned int bits);
/* Indicates whether the rsa module is permitted to show messages on
the terminal. */
void rsa_set_verbose(int verbose);
void rsa_set_verbose __P((int verbose));
int rsa_alive(void);
int rsa_alive __P((void));
void rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *prv);
void rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *prv);
void rsa_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
void rsa_private_decrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
#endif /* RSA_H */
#endif /* RSA_H */

619
scp.c

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,18 +1,18 @@
/*
servconf.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Mon Aug 21 15:48:58 1995 ylo
*/
*
* servconf.c
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Mon Aug 21 15:48:58 1995 ylo
*
*/
#include "includes.h"
RCSID("$Id: servconf.c,v 1.5 1999/11/21 02:23:53 damien Exp $");
RCSID("$Id: servconf.c,v 1.6 1999/11/24 13:26:22 damien Exp $");
#include "ssh.h"
#include "servconf.h"
@ -20,535 +20,514 @@ RCSID("$Id: servconf.c,v 1.5 1999/11/21 02:23:53 damien Exp $");
/* Initializes the server options to their default values. */
void initialize_server_options(ServerOptions *options)
void
initialize_server_options(ServerOptions *options)
{
memset(options, 0, sizeof(*options));
options->port = -1;
options->listen_addr.s_addr = htonl(INADDR_ANY);
options->host_key_file = NULL;
options->server_key_bits = -1;
options->login_grace_time = -1;
options->key_regeneration_time = -1;
options->permit_root_login = -1;
options->ignore_rhosts = -1;
options->ignore_user_known_hosts = -1;
options->print_motd = -1;
options->check_mail = -1;
options->x11_forwarding = -1;
options->x11_display_offset = -1;
options->strict_modes = -1;
options->keepalives = -1;
options->log_facility = (SyslogFacility)-1;
options->log_level = (LogLevel)-1;
options->rhosts_authentication = -1;
options->rhosts_rsa_authentication = -1;
options->rsa_authentication = -1;
memset(options, 0, sizeof(*options));
options->port = -1;
options->listen_addr.s_addr = htonl(INADDR_ANY);
options->host_key_file = NULL;
options->server_key_bits = -1;
options->login_grace_time = -1;
options->key_regeneration_time = -1;
options->permit_root_login = -1;
options->ignore_rhosts = -1;
options->ignore_user_known_hosts = -1;
options->print_motd = -1;
options->check_mail = -1;
options->x11_forwarding = -1;
options->x11_display_offset = -1;
options->strict_modes = -1;
options->keepalives = -1;
options->log_facility = (SyslogFacility) - 1;
options->log_level = (LogLevel) - 1;
options->rhosts_authentication = -1;
options->rhosts_rsa_authentication = -1;
options->rsa_authentication = -1;
#ifdef KRB4
options->kerberos_authentication = -1;
options->kerberos_or_local_passwd = -1;
options->kerberos_ticket_cleanup = -1;
options->kerberos_authentication = -1;
options->kerberos_or_local_passwd = -1;
options->kerberos_ticket_cleanup = -1;
#endif
#ifdef AFS
options->kerberos_tgt_passing = -1;
options->afs_token_passing = -1;
options->kerberos_tgt_passing = -1;
options->afs_token_passing = -1;
#endif
options->password_authentication = -1;
options->password_authentication = -1;
#ifdef SKEY
options->skey_authentication = -1;
options->skey_authentication = -1;
#endif
options->permit_empty_passwd = -1;
options->use_login = -1;
options->num_allow_users = 0;
options->num_deny_users = 0;
options->num_allow_groups = 0;
options->num_deny_groups = 0;
options->permit_empty_passwd = -1;
options->use_login = -1;
options->num_allow_users = 0;
options->num_deny_users = 0;
options->num_allow_groups = 0;
options->num_deny_groups = 0;
}
void fill_default_server_options(ServerOptions *options)
void
fill_default_server_options(ServerOptions *options)
{
if (options->port == -1)
{
struct servent *sp;
if (options->port == -1) {
struct servent *sp;
sp = getservbyname(SSH_SERVICE_NAME, "tcp");
if (sp)
options->port = ntohs(sp->s_port);
else
options->port = SSH_DEFAULT_PORT;
endservent();
}
if (options->host_key_file == NULL)
options->host_key_file = HOST_KEY_FILE;
if (options->server_key_bits == -1)
options->server_key_bits = 768;
if (options->login_grace_time == -1)
options->login_grace_time = 600;
if (options->key_regeneration_time == -1)
options->key_regeneration_time = 3600;
if (options->permit_root_login == -1)
options->permit_root_login = 1; /* yes */
if (options->ignore_rhosts == -1)
options->ignore_rhosts = 0;
if (options->ignore_user_known_hosts == -1)
options->ignore_user_known_hosts = 0;
if (options->check_mail == -1)
options->check_mail = 0;
if (options->print_motd == -1)
options->print_motd = 1;
if (options->x11_forwarding == -1)
options->x11_forwarding = 1;
if (options->x11_display_offset == -1)
options->x11_display_offset = 1;
if (options->strict_modes == -1)
options->strict_modes = 1;
if (options->keepalives == -1)
options->keepalives = 1;
if (options->log_facility == (SyslogFacility)(-1))
options->log_facility = SYSLOG_FACILITY_AUTH;
if (options->log_level == (LogLevel)(-1))
options->log_level = SYSLOG_LEVEL_INFO;
if (options->rhosts_authentication == -1)
options->rhosts_authentication = 0;
if (options->rhosts_rsa_authentication == -1)
options->rhosts_rsa_authentication = 1;
if (options->rsa_authentication == -1)
options->rsa_authentication = 1;
sp = getservbyname(SSH_SERVICE_NAME, "tcp");
if (sp)
options->port = ntohs(sp->s_port);
else
options->port = SSH_DEFAULT_PORT;
endservent();
}
if (options->host_key_file == NULL)
options->host_key_file = HOST_KEY_FILE;
if (options->server_key_bits == -1)
options->server_key_bits = 768;
if (options->login_grace_time == -1)
options->login_grace_time = 600;
if (options->key_regeneration_time == -1)
options->key_regeneration_time = 3600;
if (options->permit_root_login == -1)
options->permit_root_login = 1; /* yes */
if (options->ignore_rhosts == -1)
options->ignore_rhosts = 0;
if (options->ignore_user_known_hosts == -1)
options->ignore_user_known_hosts = 0;
if (options->check_mail == -1)
options->check_mail = 0;
if (options->print_motd == -1)
options->print_motd = 1;
if (options->x11_forwarding == -1)
options->x11_forwarding = 1;
if (options->x11_display_offset == -1)
options->x11_display_offset = 1;
if (options->strict_modes == -1)
options->strict_modes = 1;
if (options->keepalives == -1)
options->keepalives = 1;
if (options->log_facility == (SyslogFacility) (-1))
options->log_facility = SYSLOG_FACILITY_AUTH;
if (options->log_level == (LogLevel) (-1))
options->log_level = SYSLOG_LEVEL_INFO;
if (options->rhosts_authentication == -1)
options->rhosts_authentication = 0;
if (options->rhosts_rsa_authentication == -1)
options->rhosts_rsa_authentication = 1;
if (options->rsa_authentication == -1)
options->rsa_authentication = 1;
#ifdef KRB4
if (options->kerberos_authentication == -1)
options->kerberos_authentication = (access(KEYFILE, R_OK) == 0);
if (options->kerberos_or_local_passwd == -1)
options->kerberos_or_local_passwd = 1;
if (options->kerberos_ticket_cleanup == -1)
options->kerberos_ticket_cleanup = 1;
if (options->kerberos_authentication == -1)
options->kerberos_authentication = (access(KEYFILE, R_OK) == 0);
if (options->kerberos_or_local_passwd == -1)
options->kerberos_or_local_passwd = 1;
if (options->kerberos_ticket_cleanup == -1)
options->kerberos_ticket_cleanup = 1;
#endif /* KRB4 */
#ifdef AFS
if (options->kerberos_tgt_passing == -1)
options->kerberos_tgt_passing = 0;
if (options->afs_token_passing == -1)
options->afs_token_passing = k_hasafs();
if (options->kerberos_tgt_passing == -1)
options->kerberos_tgt_passing = 0;
if (options->afs_token_passing == -1)
options->afs_token_passing = k_hasafs();
#endif /* AFS */
if (options->password_authentication == -1)
options->password_authentication = 1;
if (options->password_authentication == -1)
options->password_authentication = 1;
#ifdef SKEY
if (options->skey_authentication == -1)
options->skey_authentication = 1;
if (options->skey_authentication == -1)
options->skey_authentication = 1;
#endif
if (options->permit_empty_passwd == -1)
options->permit_empty_passwd = 1;
if (options->use_login == -1)
options->use_login = 0;
if (options->permit_empty_passwd == -1)
options->permit_empty_passwd = 1;
if (options->use_login == -1)
options->use_login = 0;
}
#define WHITESPACE " \t\r\n"
/* Keyword tokens. */
typedef enum
{
sBadOption, /* == unknown option */
sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
sPermitRootLogin, sLogFacility, sLogLevel,
sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
typedef enum {
sBadOption, /* == unknown option */
sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
sPermitRootLogin, sLogFacility, sLogLevel,
sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
#ifdef KRB4
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
#endif
#ifdef AFS
sKerberosTgtPassing, sAFSTokenPassing,
sKerberosTgtPassing, sAFSTokenPassing,
#endif
#ifdef SKEY
sSkeyAuthentication,
sSkeyAuthentication,
#endif
sPasswordAuthentication, sListenAddress,
sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts
sPasswordAuthentication, sListenAddress,
sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts
} ServerOpCodes;
/* Textual representation of the tokens. */
static struct
{
const char *name;
ServerOpCodes opcode;
} keywords[] =
{
{ "port", sPort },
{ "hostkey", sHostKeyFile },
{ "serverkeybits", sServerKeyBits },
{ "logingracetime", sLoginGraceTime },
{ "keyregenerationinterval", sKeyRegenerationTime },
{ "permitrootlogin", sPermitRootLogin },
{ "syslogfacility", sLogFacility },
{ "loglevel", sLogLevel },
{ "rhostsauthentication", sRhostsAuthentication },
{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
{ "rsaauthentication", sRSAAuthentication },
static struct {
const char *name;
ServerOpCodes opcode;
} keywords[] = {
{ "port", sPort },
{ "hostkey", sHostKeyFile },
{ "serverkeybits", sServerKeyBits },
{ "logingracetime", sLoginGraceTime },
{ "keyregenerationinterval", sKeyRegenerationTime },
{ "permitrootlogin", sPermitRootLogin },
{ "syslogfacility", sLogFacility },
{ "loglevel", sLogLevel },
{ "rhostsauthentication", sRhostsAuthentication },
{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
{ "rsaauthentication", sRSAAuthentication },
#ifdef KRB4
{ "kerberosauthentication", sKerberosAuthentication },
{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
{ "kerberosticketcleanup", sKerberosTicketCleanup },
{ "kerberosauthentication", sKerberosAuthentication },
{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
{ "kerberosticketcleanup", sKerberosTicketCleanup },
#endif
#ifdef AFS
{ "kerberostgtpassing", sKerberosTgtPassing },
{ "afstokenpassing", sAFSTokenPassing },
{ "kerberostgtpassing", sKerberosTgtPassing },
{ "afstokenpassing", sAFSTokenPassing },
#endif
{ "passwordauthentication", sPasswordAuthentication },
{ "passwordauthentication", sPasswordAuthentication },
#ifdef SKEY
{ "skeyauthentication", sSkeyAuthentication },
{ "skeyauthentication", sSkeyAuthentication },
#endif
{ "checkmail", sCheckMail },
{ "listenaddress", sListenAddress },
{ "printmotd", sPrintMotd },
{ "ignorerhosts", sIgnoreRhosts },
{ "ignoreuserknownhosts", sIgnoreUserKnownHosts },
{ "x11forwarding", sX11Forwarding },
{ "x11displayoffset", sX11DisplayOffset },
{ "strictmodes", sStrictModes },
{ "permitemptypasswords", sEmptyPasswd },
{ "uselogin", sUseLogin },
{ "randomseed", sRandomSeedFile },
{ "keepalive", sKeepAlives },
{ "allowusers", sAllowUsers },
{ "denyusers", sDenyUsers },
{ "allowgroups", sAllowGroups },
{ "denygroups", sDenyGroups },
{ NULL, 0 }
{ "checkmail", sCheckMail },
{ "listenaddress", sListenAddress },
{ "printmotd", sPrintMotd },
{ "ignorerhosts", sIgnoreRhosts },
{ "ignoreuserknownhosts", sIgnoreUserKnownHosts },
{ "x11forwarding", sX11Forwarding },
{ "x11displayoffset", sX11DisplayOffset },
{ "strictmodes", sStrictModes },
{ "permitemptypasswords", sEmptyPasswd },
{ "uselogin", sUseLogin },
{ "randomseed", sRandomSeedFile },
{ "keepalive", sKeepAlives },
{ "allowusers", sAllowUsers },
{ "denyusers", sDenyUsers },
{ "allowgroups", sAllowGroups },
{ "denygroups", sDenyGroups },
{ NULL, 0 }
};
/* Returns the number of the token pointed to by cp of length len.
Never returns if the token is not known. */
static ServerOpCodes parse_token(const char *cp, const char *filename,
int linenum)
static ServerOpCodes
parse_token(const char *cp, const char *filename,
int linenum)
{
unsigned int i;
unsigned int i;
for (i = 0; keywords[i].name; i++)
if (strcmp(cp, keywords[i].name) == 0)
return keywords[i].opcode;
for (i = 0; keywords[i].name; i++)
if (strcmp(cp, keywords[i].name) == 0)
return keywords[i].opcode;
fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
filename, linenum, cp);
return sBadOption;
fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
filename, linenum, cp);
return sBadOption;
}
/* Reads the server configuration file. */
void read_server_config(ServerOptions *options, const char *filename)
void
read_server_config(ServerOptions *options, const char *filename)
{
FILE *f;
char line[1024];
char *cp, **charptr;
int linenum, *intptr, value;
int bad_options = 0;
ServerOpCodes opcode;
FILE *f;
char line[1024];
char *cp, **charptr;
int linenum, *intptr, value;
int bad_options = 0;
ServerOpCodes opcode;
f = fopen(filename, "r");
if (!f)
{
perror(filename);
exit(1);
}
linenum = 0;
while (fgets(line, sizeof(line), f))
{
linenum++;
cp = line + strspn(line, WHITESPACE);
if (!*cp || *cp == '#')
continue;
cp = strtok(cp, WHITESPACE);
{
char *t = cp;
for (; *t != 0; t++)
if ('A' <= *t && *t <= 'Z')
*t = *t - 'A' + 'a'; /* tolower */
}
opcode = parse_token(cp, filename, linenum);
switch (opcode)
{
case sBadOption:
bad_options++;
continue;
case sPort:
intptr = &options->port;
parse_int:
cp = strtok(NULL, WHITESPACE);
if (!cp)
{
fprintf(stderr, "%s line %d: missing integer value.\n",
filename, linenum);
exit(1);
}
value = atoi(cp);
if (*intptr == -1)
*intptr = value;
break;
case sServerKeyBits:
intptr = &options->server_key_bits;
goto parse_int;
case sLoginGraceTime:
intptr = &options->login_grace_time;
goto parse_int;
case sKeyRegenerationTime:
intptr = &options->key_regeneration_time;
goto parse_int;
case sListenAddress:
cp = strtok(NULL, WHITESPACE);
if (!cp)
{
fprintf(stderr, "%s line %d: missing inet addr.\n",
filename, linenum);
exit(1);
}
options->listen_addr.s_addr = inet_addr(cp);
break;
case sHostKeyFile:
charptr = &options->host_key_file;
cp = strtok(NULL, WHITESPACE);
if (!cp)
{
fprintf(stderr, "%s line %d: missing file name.\n",
filename, linenum);
exit(1);
}
if (*charptr == NULL)
*charptr = tilde_expand_filename(cp, getuid());
break;
case sRandomSeedFile:
fprintf(stderr, "%s line %d: \"randomseed\" option is obsolete.\n",
filename, linenum);
cp = strtok(NULL, WHITESPACE);
break;
case sPermitRootLogin:
intptr = &options->permit_root_login;
cp = strtok(NULL, WHITESPACE);
if (!cp)
{
fprintf(stderr, "%s line %d: missing yes/without-password/no argument.\n",
filename, linenum);
exit(1);
}
if (strcmp(cp, "without-password") == 0)
value = 2;
else if (strcmp(cp, "yes") == 0)
value = 1;
else if (strcmp(cp, "no") == 0)
value = 0;
else
{
fprintf(stderr, "%s line %d: Bad yes/without-password/no argument: %s\n",
filename, linenum, cp);
exit(1);
}
if (*intptr == -1)
*intptr = value;
break;
case sIgnoreRhosts:
intptr = &options->ignore_rhosts;
parse_flag:
cp = strtok(NULL, WHITESPACE);
if (!cp)
{
fprintf(stderr, "%s line %d: missing yes/no argument.\n",
filename, linenum);
exit(1);
}
if (strcmp(cp, "yes") == 0)
value = 1;
else
if (strcmp(cp, "no") == 0)
value = 0;
else
{
fprintf(stderr, "%s line %d: Bad yes/no argument: %s\n",
filename, linenum, cp);
f = fopen(filename, "r");
if (!f) {
perror(filename);
exit(1);
}
if (*intptr == -1)
*intptr = value;
break;
}
linenum = 0;
while (fgets(line, sizeof(line), f)) {
linenum++;
cp = line + strspn(line, WHITESPACE);
if (!*cp || *cp == '#')
continue;
cp = strtok(cp, WHITESPACE);
{
char *t = cp;
for (; *t != 0; t++)
if ('A' <= *t && *t <= 'Z')
*t = *t - 'A' + 'a'; /* tolower */
case sIgnoreUserKnownHosts:
intptr = &options->ignore_user_known_hosts;
goto parse_int;
}
opcode = parse_token(cp, filename, linenum);
switch (opcode) {
case sBadOption:
bad_options++;
continue;
case sPort:
intptr = &options->port;
parse_int:
cp = strtok(NULL, WHITESPACE);
if (!cp) {
fprintf(stderr, "%s line %d: missing integer value.\n",
filename, linenum);
exit(1);
}
value = atoi(cp);
if (*intptr == -1)
*intptr = value;
break;
case sRhostsAuthentication:
intptr = &options->rhosts_authentication;
goto parse_flag;
case sServerKeyBits:
intptr = &options->server_key_bits;
goto parse_int;
case sLoginGraceTime:
intptr = &options->login_grace_time;
goto parse_int;
case sKeyRegenerationTime:
intptr = &options->key_regeneration_time;
goto parse_int;
case sListenAddress:
cp = strtok(NULL, WHITESPACE);
if (!cp) {
fprintf(stderr, "%s line %d: missing inet addr.\n",
filename, linenum);
exit(1);
}
options->listen_addr.s_addr = inet_addr(cp);
break;
case sHostKeyFile:
charptr = &options->host_key_file;
cp = strtok(NULL, WHITESPACE);
if (!cp) {
fprintf(stderr, "%s line %d: missing file name.\n",
filename, linenum);
exit(1);
}
if (*charptr == NULL)
*charptr = tilde_expand_filename(cp, getuid());
break;
case sRandomSeedFile:
fprintf(stderr, "%s line %d: \"randomseed\" option is obsolete.\n",
filename, linenum);
cp = strtok(NULL, WHITESPACE);
break;
case sPermitRootLogin:
intptr = &options->permit_root_login;
cp = strtok(NULL, WHITESPACE);
if (!cp) {
fprintf(stderr, "%s line %d: missing yes/without-password/no argument.\n",
filename, linenum);
exit(1);
}
if (strcmp(cp, "without-password") == 0)
value = 2;
else if (strcmp(cp, "yes") == 0)
value = 1;
else if (strcmp(cp, "no") == 0)
value = 0;
else {
fprintf(stderr, "%s line %d: Bad yes/without-password/no argument: %s\n",
filename, linenum, cp);
exit(1);
}
if (*intptr == -1)
*intptr = value;
break;
case sIgnoreRhosts:
intptr = &options->ignore_rhosts;
parse_flag:
cp = strtok(NULL, WHITESPACE);
if (!cp) {
fprintf(stderr, "%s line %d: missing yes/no argument.\n",
filename, linenum);
exit(1);
}
if (strcmp(cp, "yes") == 0)
value = 1;
else if (strcmp(cp, "no") == 0)
value = 0;
else {
fprintf(stderr, "%s line %d: Bad yes/no argument: %s\n",
filename, linenum, cp);
exit(1);
}
if (*intptr == -1)
*intptr = value;
break;
case sIgnoreUserKnownHosts:
intptr = &options->ignore_user_known_hosts;
goto parse_int;
case sRhostsAuthentication:
intptr = &options->rhosts_authentication;
goto parse_flag;
case sRhostsRSAAuthentication:
intptr = &options->rhosts_rsa_authentication;
goto parse_flag;
case sRSAAuthentication:
intptr = &options->rsa_authentication;
goto parse_flag;
case sRhostsRSAAuthentication:
intptr = &options->rhosts_rsa_authentication;
goto parse_flag;
case sRSAAuthentication:
intptr = &options->rsa_authentication;
goto parse_flag;
#ifdef KRB4
case sKerberosAuthentication:
intptr = &options->kerberos_authentication;
goto parse_flag;
case sKerberosOrLocalPasswd:
intptr = &options->kerberos_or_local_passwd;
goto parse_flag;
case sKerberosAuthentication:
intptr = &options->kerberos_authentication;
goto parse_flag;
case sKerberosTicketCleanup:
intptr = &options->kerberos_ticket_cleanup;
goto parse_flag;
case sKerberosOrLocalPasswd:
intptr = &options->kerberos_or_local_passwd;
goto parse_flag;
case sKerberosTicketCleanup:
intptr = &options->kerberos_ticket_cleanup;
goto parse_flag;
#endif
#ifdef AFS
case sKerberosTgtPassing:
intptr = &options->kerberos_tgt_passing;
goto parse_flag;
case sKerberosTgtPassing:
intptr = &options->kerberos_tgt_passing;
goto parse_flag;
case sAFSTokenPassing:
intptr = &options->afs_token_passing;
goto parse_flag;
case sAFSTokenPassing:
intptr = &options->afs_token_passing;
goto parse_flag;
#endif
case sPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
case sPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
case sCheckMail:
intptr = &options->check_mail;
goto parse_flag;
case sCheckMail:
intptr = &options->check_mail;
goto parse_flag;
#ifdef SKEY
case sSkeyAuthentication:
intptr = &options->skey_authentication;
goto parse_flag;
case sSkeyAuthentication:
intptr = &options->skey_authentication;
goto parse_flag;
#endif
case sPrintMotd:
intptr = &options->print_motd;
goto parse_flag;
case sPrintMotd:
intptr = &options->print_motd;
goto parse_flag;
case sX11Forwarding:
intptr = &options->x11_forwarding;
goto parse_flag;
case sX11Forwarding:
intptr = &options->x11_forwarding;
goto parse_flag;
case sX11DisplayOffset:
intptr = &options->x11_display_offset;
goto parse_int;
case sX11DisplayOffset:
intptr = &options->x11_display_offset;
goto parse_int;
case sStrictModes:
intptr = &options->strict_modes;
goto parse_flag;
case sStrictModes:
intptr = &options->strict_modes;
goto parse_flag;
case sKeepAlives:
intptr = &options->keepalives;
goto parse_flag;
case sEmptyPasswd:
intptr = &options->permit_empty_passwd;
goto parse_flag;
case sKeepAlives:
intptr = &options->keepalives;
goto parse_flag;
case sUseLogin:
intptr = &options->use_login;
goto parse_flag;
case sEmptyPasswd:
intptr = &options->permit_empty_passwd;
goto parse_flag;
case sLogFacility:
intptr = (int *)&options->log_facility;
cp = strtok(NULL, WHITESPACE);
value = log_facility_number(cp);
if (value == (SyslogFacility)-1)
fatal("%.200s line %d: unsupported log facility '%s'\n",
filename, linenum, cp ? cp : "<NONE>");
if (*intptr == -1)
*intptr = (SyslogFacility)value;
break;
case sUseLogin:
intptr = &options->use_login;
goto parse_flag;
case sLogLevel:
intptr = (int *)&options->log_level;
cp = strtok(NULL, WHITESPACE);
value = log_level_number(cp);
if (value == (LogLevel)-1)
fatal("%.200s line %d: unsupported log level '%s'\n",
filename, linenum, cp ? cp : "<NONE>");
if (*intptr == -1)
*intptr = (LogLevel)value;
break;
case sAllowUsers:
while ((cp = strtok(NULL, WHITESPACE)))
{
if (options->num_allow_users >= MAX_ALLOW_USERS)
{
fprintf(stderr, "%s line %d: too many allow users.\n",
filename, linenum);
exit(1);
case sLogFacility:
intptr = (int *) &options->log_facility;
cp = strtok(NULL, WHITESPACE);
value = log_facility_number(cp);
if (value == (SyslogFacility) - 1)
fatal("%.200s line %d: unsupported log facility '%s'\n",
filename, linenum, cp ? cp : "<NONE>");
if (*intptr == -1)
*intptr = (SyslogFacility) value;
break;
case sLogLevel:
intptr = (int *) &options->log_level;
cp = strtok(NULL, WHITESPACE);
value = log_level_number(cp);
if (value == (LogLevel) - 1)
fatal("%.200s line %d: unsupported log level '%s'\n",
filename, linenum, cp ? cp : "<NONE>");
if (*intptr == -1)
*intptr = (LogLevel) value;
break;
case sAllowUsers:
while ((cp = strtok(NULL, WHITESPACE))) {
if (options->num_allow_users >= MAX_ALLOW_USERS) {
fprintf(stderr, "%s line %d: too many allow users.\n",
filename, linenum);
exit(1);
}
options->allow_users[options->num_allow_users++] = xstrdup(cp);
}
break;
case sDenyUsers:
while ((cp = strtok(NULL, WHITESPACE))) {
if (options->num_deny_users >= MAX_DENY_USERS) {
fprintf(stderr, "%s line %d: too many deny users.\n",
filename, linenum);
exit(1);
}
options->deny_users[options->num_deny_users++] = xstrdup(cp);
}
break;
case sAllowGroups:
while ((cp = strtok(NULL, WHITESPACE))) {
if (options->num_allow_groups >= MAX_ALLOW_GROUPS) {
fprintf(stderr, "%s line %d: too many allow groups.\n",
filename, linenum);
exit(1);
}
options->allow_groups[options->num_allow_groups++] = xstrdup(cp);
}
break;
case sDenyGroups:
while ((cp = strtok(NULL, WHITESPACE))) {
if (options->num_deny_groups >= MAX_DENY_GROUPS) {
fprintf(stderr, "%s line %d: too many deny groups.\n",
filename, linenum);
exit(1);
}
options->deny_groups[options->num_deny_groups++] = xstrdup(cp);
}
break;
default:
fprintf(stderr, "%s line %d: Missing handler for opcode %s (%d)\n",
filename, linenum, cp, opcode);
exit(1);
}
options->allow_users[options->num_allow_users++] = xstrdup(cp);
}
break;
case sDenyUsers:
while ((cp = strtok(NULL, WHITESPACE)))
{
if (options->num_deny_users >= MAX_DENY_USERS)
{
fprintf(stderr, "%s line %d: too many deny users.\n",
filename, linenum);
exit(1);
if (strtok(NULL, WHITESPACE) != NULL) {
fprintf(stderr, "%s line %d: garbage at end of line.\n",
filename, linenum);
exit(1);
}
options->deny_users[options->num_deny_users++] = xstrdup(cp);
}
break;
case sAllowGroups:
while ((cp = strtok(NULL, WHITESPACE)))
{
if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
{
fprintf(stderr, "%s line %d: too many allow groups.\n",
filename, linenum);
exit(1);
}
options->allow_groups[options->num_allow_groups++] = xstrdup(cp);
}
break;
case sDenyGroups:
while ((cp = strtok(NULL, WHITESPACE)))
{
if (options->num_deny_groups >= MAX_DENY_GROUPS)
{
fprintf(stderr, "%s line %d: too many deny groups.\n",
filename, linenum);
exit(1);
}
options->deny_groups[options->num_deny_groups++] = xstrdup(cp);
}
break;
default:
fprintf(stderr, "%s line %d: Missing handler for opcode %s (%d)\n",
filename, linenum, cp, opcode);
exit(1);
}
if (strtok(NULL, WHITESPACE) != NULL)
{
fprintf(stderr, "%s line %d: garbage at end of line.\n",
filename, linenum);
exit(1);
fclose(f);
if (bad_options > 0) {
fprintf(stderr, "%s: terminating, %d bad configuration options\n",
filename, bad_options);
exit(1);
}
}
fclose(f);
if (bad_options > 0) {
fprintf(stderr, "%s: terminating, %d bad configuration options\n",
filename, bad_options);
exit(1);
}
}

Просмотреть файл

@ -1,86 +1,98 @@
/*
*
* servconf.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Mon Aug 21 15:35:03 1995 ylo
*
* Definitions for server configuration data and for the functions reading it.
*
*/
servconf.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Mon Aug 21 15:35:03 1995 ylo
Definitions for server configuration data and for the functions reading it.
*/
/* RCSID("$Id: servconf.h,v 1.3 1999/11/12 00:33:04 damien Exp $"); */
/* RCSID("$Id: servconf.h,v 1.4 1999/11/24 13:26:22 damien Exp $"); */
#ifndef SERVCONF_H
#define SERVCONF_H
#define MAX_ALLOW_USERS 256 /* Max # users on allow list. */
#define MAX_DENY_USERS 256 /* Max # users on deny list. */
#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */
#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
#define MAX_ALLOW_USERS 256 /* Max # users on allow list. */
#define MAX_DENY_USERS 256 /* Max # users on deny list. */
#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */
#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
typedef struct
{
int port; /* Port number to listen on. */
struct in_addr listen_addr; /* Address on which the server listens. */
char *host_key_file; /* File containing host key. */
int server_key_bits; /* Size of the server key. */
int login_grace_time; /* Disconnect if no auth in this time (sec). */
int key_regeneration_time; /* Server key lifetime (seconds). */
int permit_root_login; /* If true, permit root login. */
int ignore_rhosts; /* Ignore .rhosts and .shosts. */
int ignore_user_known_hosts; /* Ignore ~/.ssh/known_hosts for RhostsRsaAuth */
int print_motd; /* If true, print /etc/motd. */
int check_mail; /* If true, check for new mail. */
int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */
int x11_display_offset; /* What DISPLAY number to start searching at */
int strict_modes; /* If true, require string home dir modes. */
int keepalives; /* If true, set SO_KEEPALIVE. */
SyslogFacility log_facility; /* Facility for system logging. */
LogLevel log_level; /* Level for system logging. */
int rhosts_authentication; /* If true, permit rhosts authentication. */
int rhosts_rsa_authentication;/* If true, permit rhosts RSA authentication.*/
int rsa_authentication; /* If true, permit RSA authentication. */
typedef struct {
int port; /* Port number to listen on. */
struct in_addr listen_addr; /* Address on which the server
* listens. */
char *host_key_file; /* File containing host key. */
int server_key_bits;/* Size of the server key. */
int login_grace_time; /* Disconnect if no auth in this time
* (sec). */
int key_regeneration_time; /* Server key lifetime (seconds). */
int permit_root_login; /* If true, permit root login. */
int ignore_rhosts; /* Ignore .rhosts and .shosts. */
int ignore_user_known_hosts; /* Ignore ~/.ssh/known_hosts
* for RhostsRsaAuth */
int print_motd; /* If true, print /etc/motd. */
int check_mail; /* If true, check for new mail. */
int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */
int x11_display_offset; /* What DISPLAY number to start
* searching at */
int strict_modes; /* If true, require string home dir modes. */
int keepalives; /* If true, set SO_KEEPALIVE. */
SyslogFacility log_facility; /* Facility for system logging. */
LogLevel log_level; /* Level for system logging. */
int rhosts_authentication; /* If true, permit rhosts
* authentication. */
int rhosts_rsa_authentication; /* If true, permit rhosts RSA
* authentication. */
int rsa_authentication; /* If true, permit RSA authentication. */
#ifdef KRB4
int kerberos_authentication; /* If true, permit Kerberos authentication. */
int kerberos_or_local_passwd; /* If true, permit kerberos and any other
password authentication mechanism, such
as SecurID or /etc/passwd */
int kerberos_ticket_cleanup; /* If true, destroy ticket file on logout. */
int kerberos_authentication; /* If true, permit Kerberos
* authentication. */
int kerberos_or_local_passwd; /* If true, permit kerberos
* and any other password
* authentication mechanism,
* such as SecurID or
* /etc/passwd */
int kerberos_ticket_cleanup; /* If true, destroy ticket
* file on logout. */
#endif
#ifdef AFS
int kerberos_tgt_passing; /* If true, permit Kerberos tgt passing. */
int afs_token_passing; /* If true, permit AFS token passing. */
int kerberos_tgt_passing; /* If true, permit Kerberos tgt
* passing. */
int afs_token_passing; /* If true, permit AFS token passing. */
#endif
int password_authentication; /* If true, permit password authentication. */
int password_authentication; /* If true, permit password
* authentication. */
#ifdef SKEY
int skey_authentication; /* If true, permit s/key authentication. */
int skey_authentication; /* If true, permit s/key
* authentication. */
#endif
int permit_empty_passwd; /* If false, do not permit empty passwords. */
int use_login; /* If true, login(1) is used */
unsigned int num_allow_users;
char *allow_users[MAX_ALLOW_USERS];
unsigned int num_deny_users;
char *deny_users[MAX_DENY_USERS];
unsigned int num_allow_groups;
char *allow_groups[MAX_ALLOW_GROUPS];
unsigned int num_deny_groups;
char *deny_groups[MAX_DENY_GROUPS];
} ServerOptions;
int permit_empty_passwd; /* If false, do not permit empty
* passwords. */
int use_login; /* If true, login(1) is used */
unsigned int num_allow_users;
char *allow_users[MAX_ALLOW_USERS];
unsigned int num_deny_users;
char *deny_users[MAX_DENY_USERS];
unsigned int num_allow_groups;
char *allow_groups[MAX_ALLOW_GROUPS];
unsigned int num_deny_groups;
char *deny_groups[MAX_DENY_GROUPS];
} ServerOptions;
/* Initializes the server options to special values that indicate that they
have not yet been set. */
void initialize_server_options(ServerOptions *options);
void initialize_server_options(ServerOptions * options);
/* Reads the server configuration file. This only sets the values for those
options that have the special value indicating they have not been set. */
void read_server_config(ServerOptions *options, const char *filename);
void read_server_config(ServerOptions * options, const char *filename);
/* Sets values for those values that have not yet been set. */
void fill_default_server_options(ServerOptions *options);
void fill_default_server_options(ServerOptions * options);
#endif /* SERVCONF_H */
#endif /* SERVCONF_H */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

471
ssh-add.c
Просмотреть файл

@ -1,20 +1,13 @@
/*
ssh-add.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Thu Apr 6 00:52:24 1995 ylo
Adds an identity to the authentication server, or removes an identity.
*/
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Created: Thu Apr 6 00:52:24 1995 ylo
* Adds an identity to the authentication server, or removes an identity.
*/
#include "includes.h"
RCSID("$Id: ssh-add.c,v 1.12 1999/11/23 00:24:32 damien Exp $");
RCSID("$Id: ssh-add.c,v 1.13 1999/11/24 13:26:22 damien Exp $");
#include "rsa.h"
#include "ssh.h"
@ -35,291 +28,279 @@ const char *__progname = "ssh-add";
void
delete_file(AuthenticationConnection *ac, const char *filename)
{
RSA *key;
char *comment;
RSA *key;
char *comment;
key = RSA_new();
if (!load_public_key(filename, key, &comment))
{
printf("Bad key file %s: %s\n", filename, strerror(errno));
return;
}
if (ssh_remove_identity(ac, key))
fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
else
fprintf(stderr, "Could not remove identity: %s\n", filename);
RSA_free(key);
xfree(comment);
key = RSA_new();
if (!load_public_key(filename, key, &comment)) {
printf("Bad key file %s: %s\n", filename, strerror(errno));
return;
}
if (ssh_remove_identity(ac, key))
fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
else
fprintf(stderr, "Could not remove identity: %s\n", filename);
RSA_free(key);
xfree(comment);
}
void
delete_all(AuthenticationConnection *ac)
{
/* Send a request to remove all identities. */
if (ssh_remove_all_identities(ac))
fprintf(stderr, "All identities removed.\n");
else
fprintf(stderr, "Failed to remove all identitities.\n");
/* Send a request to remove all identities. */
if (ssh_remove_all_identities(ac))
fprintf(stderr, "All identities removed.\n");
else
fprintf(stderr, "Failed to remove all identitities.\n");
}
void
add_file(AuthenticationConnection *ac, const char *filename)
{
RSA *key;
RSA *public_key;
char *saved_comment, *comment;
int success;
key = RSA_new();
public_key = RSA_new();
if (!load_public_key(filename, public_key, &saved_comment))
{
printf("Bad key file %s: %s\n", filename, strerror(errno));
return;
}
RSA_free(public_key);
RSA *key;
RSA *public_key;
char *saved_comment, *comment;
int success;
/* At first, try empty passphrase */
success = load_private_key(filename, "", key, &comment);
if (!success) {
printf("Need passphrase for %s (%s).\n", filename, saved_comment);
if (!isatty(STDIN_FILENO)) {
key = RSA_new();
public_key = RSA_new();
if (!load_public_key(filename, public_key, &saved_comment)) {
printf("Bad key file %s: %s\n", filename, strerror(errno));
return;
}
RSA_free(public_key);
/* At first, try empty passphrase */
success = load_private_key(filename, "", key, &comment);
if (!success) {
printf("Need passphrase for %s (%s).\n", filename, saved_comment);
if (!isatty(STDIN_FILENO)) {
#ifdef USE_EXTERNAL_ASKPASS
int prompts = 3;
while (prompts && !success)
{
success = askpass(filename, key, saved_comment, &comment);
prompts--;
}
if (!success)
{
xfree(saved_comment);
return;
}
int prompts = 3;
while (prompts && !success) {
success = askpass(filename, key, saved_comment, &comment);
prompts--;
}
if (!success) {
xfree(saved_comment);
return;
}
#else /* !USE_EXTERNAL_ASKPASS */
xfree(saved_comment);
return;
xfree(saved_comment);
return;
#endif /* USE_EXTERNAL_ASKPASS */
}
}
while (!success) {
char *pass = read_passphrase("Enter passphrase: ", 1);
if (strcmp(pass, "") == 0){
xfree(pass);
xfree(saved_comment);
return;
}
success = load_private_key(filename, pass, key, &comment);
memset(pass, 0, strlen(pass));
xfree(pass);
if (success)
break;
printf("Bad passphrase.\n");
}
}
xfree(saved_comment);
while (!success) {
char *pass = read_passphrase("Enter passphrase: ", 1);
if (strcmp(pass, "") == 0) {
xfree(pass);
xfree(saved_comment);
return;
}
success = load_private_key(filename, pass, key, &comment);
memset(pass, 0, strlen(pass));
xfree(pass);
if (success)
break;
printf("Bad passphrase.\n");
}
}
xfree(saved_comment);
if (ssh_add_identity(ac, key, comment))
fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
else
fprintf(stderr, "Could not add identity: %s\n", filename);
RSA_free(key);
xfree(comment);
if (ssh_add_identity(ac, key, comment))
fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
else
fprintf(stderr, "Could not add identity: %s\n", filename);
RSA_free(key);
xfree(comment);
}
void
list_identities(AuthenticationConnection *ac, int fp)
{
BIGNUM *e, *n;
int status;
char *comment;
int had_identities;
BIGNUM *e, *n;
int status;
char *comment;
int had_identities;
e = BN_new();
n = BN_new();
had_identities = 0;
for (status = ssh_get_first_identity(ac, e, n, &comment);
status;
status = ssh_get_next_identity(ac, e, n, &comment))
{
unsigned int bits = BN_num_bits(n);
had_identities = 1;
if (fp) {
printf("%d %s %s\n", bits, fingerprint(e, n), comment);
} else {
char *ebuf, *nbuf;
ebuf = BN_bn2dec(e);
if (ebuf == NULL) {
error("list_identities: BN_bn2dec(e) failed.");
}else{
nbuf = BN_bn2dec(n);
if (nbuf == NULL) {
error("list_identities: BN_bn2dec(n) failed.");
}else{
printf("%d %s %s %s\n", bits, ebuf, nbuf, comment);
free(nbuf);
}
free(ebuf);
e = BN_new();
n = BN_new();
had_identities = 0;
for (status = ssh_get_first_identity(ac, e, n, &comment);
status;
status = ssh_get_next_identity(ac, e, n, &comment)) {
unsigned int bits = BN_num_bits(n);
had_identities = 1;
if (fp) {
printf("%d %s %s\n", bits, fingerprint(e, n), comment);
} else {
char *ebuf, *nbuf;
ebuf = BN_bn2dec(e);
if (ebuf == NULL) {
error("list_identities: BN_bn2dec(e) failed.");
} else {
nbuf = BN_bn2dec(n);
if (nbuf == NULL) {
error("list_identities: BN_bn2dec(n) failed.");
} else {
printf("%d %s %s %s\n", bits, ebuf, nbuf, comment);
free(nbuf);
}
free(ebuf);
}
}
xfree(comment);
}
}
xfree(comment);
}
BN_clear_free(e);
BN_clear_free(n);
if (!had_identities)
printf("The agent has no identities.\n");
BN_clear_free(e);
BN_clear_free(n);
if (!had_identities)
printf("The agent has no identities.\n");
}
int
main(int argc, char **argv)
{
AuthenticationConnection *ac = NULL;
struct passwd *pw;
char buf[1024];
int no_files = 1;
int i;
int deleting = 0;
AuthenticationConnection *ac = NULL;
struct passwd *pw;
char buf[1024];
int no_files = 1;
int i;
int deleting = 0;
/* check if RSA support exists */
if (rsa_alive() == 0) {
fprintf(stderr,
"%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
__progname);
exit(1);
}
/* check if RSA support exists */
if (rsa_alive() == 0) {
extern char *__progname;
/* At first, get a connection to the authentication agent. */
ac = ssh_get_authentication_connection();
if (ac == NULL) {
fprintf(stderr, "Could not open a connection to your authentication agent.\n");
exit(1);
}
for (i = 1; i < argc; i++)
{
if ((strcmp(argv[i], "-l") == 0) ||
(strcmp(argv[i], "-L") == 0))
{
list_identities(ac, argv[i][1] == 'l' ? 1 : 0);
no_files = 0; /* Don't default-add/delete if -l. */
continue;
fprintf(stderr,
"%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
__progname);
exit(1);
}
if (strcmp(argv[i], "-d") == 0)
{
deleting = 1;
continue;
/* At first, get a connection to the authentication agent. */
ac = ssh_get_authentication_connection();
if (ac == NULL) {
fprintf(stderr, "Could not open a connection to your authentication agent.\n");
exit(1);
}
if (strcmp(argv[i], "-D") == 0)
{
delete_all(ac);
no_files = 0;
continue;
for (i = 1; i < argc; i++) {
if ((strcmp(argv[i], "-l") == 0) ||
(strcmp(argv[i], "-L") == 0)) {
list_identities(ac, argv[i][1] == 'l' ? 1 : 0);
/* Don't default-add/delete if -l. */
no_files = 0;
continue;
}
if (strcmp(argv[i], "-d") == 0) {
deleting = 1;
continue;
}
if (strcmp(argv[i], "-D") == 0) {
delete_all(ac);
no_files = 0;
continue;
}
no_files = 0;
if (deleting)
delete_file(ac, argv[i]);
else
add_file(ac, argv[i]);
}
no_files = 0;
if (deleting)
delete_file(ac, argv[i]);
else
add_file(ac, argv[i]);
}
if (no_files)
{
pw = getpwuid(getuid());
if (!pw)
{
fprintf(stderr, "No user found with uid %d\n", (int)getuid());
ssh_close_authentication_connection(ac);
exit(1);
if (no_files) {
pw = getpwuid(getuid());
if (!pw) {
fprintf(stderr, "No user found with uid %d\n", (int) getuid());
ssh_close_authentication_connection(ac);
exit(1);
}
snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
if (deleting)
delete_file(ac, buf);
else
add_file(ac, buf);
}
snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
if (deleting)
delete_file(ac, buf);
else
add_file(ac, buf);
}
ssh_close_authentication_connection(ac);
exit(0);
ssh_close_authentication_connection(ac);
exit(0);
}
#ifdef USE_EXTERNAL_ASKPASS
int askpass(const char *filename, RSA *key, const char *saved_comment, char **comment)
{
int pipes[2];
char buf[1024];
int tmp;
pid_t child;
FILE *pipef;
int pipes[2];
char buf[1024];
int tmp;
pid_t child;
FILE *pipef;
/* Check that we are X11-capable */
if (getenv("DISPLAY") == NULL)
exit(1);
/* Check that we are X11-capable */
if (getenv("DISPLAY") == NULL)
exit(1);
if (pipe(pipes) == -1) {
fprintf(stderr, "Creating pipes failed: %s\n", strerror(errno));
exit(1);
}
if (pipe(pipes) == -1) {
fprintf(stderr, "Creating pipes failed: %s\n", strerror(errno));
exit(1);
}
if (fflush(NULL) == EOF) {
fprintf(stderr, "Cannot flush buffers: %s\n", strerror(errno));
exit(1);
}
if (fflush(NULL) == EOF) {
fprintf(stderr, "Cannot flush buffers: %s\n", strerror(errno));
exit(1);
}
child = fork();
if (child == -1) {
fprintf(stderr, "Cannot fork: %s\n", strerror(errno));
exit(1);
}
if (child == 0) {
/* In child */
child = fork();
if (child == -1) {
fprintf(stderr, "Cannot fork: %s\n", strerror(errno));
exit(1);
}
close(pipes[0]);
if (dup2(pipes[1], 1) ==-1) {
fprintf(stderr, "dup2 failed: %s\n", strerror(errno));
exit(1);
}
if (child == 0) {
/* In child */
tmp = snprintf(buf, sizeof(buf), "Need passphrase for %s", saved_comment);
/* skip the prompt if it won't fit */
if ((tmp < 0) || (tmp >= sizeof(buf)))
tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", 0);
else
tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", buf, 0);
close(pipes[0]);
if (dup2(pipes[1], 1) ==-1) {
fprintf(stderr, "dup2 failed: %s\n", strerror(errno));
exit(1);
}
/* Shouldn't get this far */
fprintf(stderr, "Executing ssh-askpass failed: %s\n", strerror(errno));
exit(1);
}
tmp = snprintf(buf, sizeof(buf), "Need passphrase for %s", saved_comment);
/* skip the prompt if it won't fit */
if ((tmp < 0) || (tmp >= sizeof(buf)))
tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", 0);
else
tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", buf, 0);
/* In parent */
close(pipes[1]);
/* Shouldn't get this far */
fprintf(stderr, "Executing ssh-askpass failed: %s\n", strerror(errno));
exit(1);
}
if ((pipef = fdopen(pipes[0], "r")) == NULL) {
fprintf(stderr, "fdopen failed: %s\n", strerror(errno));
exit(1);
}
/* Read passphrase back from child, abort if none presented */
if(fgets(buf, sizeof(buf), pipef) == NULL)
exit(1);
/* In parent */
close(pipes[1]);
fclose(pipef);
if ((pipef = fdopen(pipes[0], "r")) == NULL) {
fprintf(stderr, "fdopen failed: %s\n", strerror(errno));
exit(1);
}
if (strchr(buf, '\n'))
*strchr(buf, '\n') = 0;
/* Read passphrase back from child, abort if none presented */
if(fgets(buf, sizeof(buf), pipef) == NULL)
exit(1);
if (waitpid(child, NULL, 0) == -1) {
fprintf(stderr, "Waiting for child failed: %s\n",
strerror(errno));
exit(1);
}
fclose(pipef);
/* Try password as it was presented */
tmp = load_private_key(filename, buf, key, comment);
if (strchr(buf, '\n'))
*strchr(buf, '\n') = 0;
memset(buf, 0, sizeof(buf));
if (waitpid(child, NULL, 0) == -1) {
fprintf(stderr, "Waiting for child failed: %s\n",
strerror(errno));
exit(1);
}
return(tmp);
/* Try password as it was presented */
tmp = load_private_key(filename, buf, key, comment);
memset(buf, 0, sizeof(buf));
return(tmp);
}
#endif /* USE_EXTERNAL_ASKPASS */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

12
ssh.1
Просмотреть файл

@ -9,7 +9,7 @@
.\"
.\" Created: Sat Apr 22 21:55:14 1995 ylo
.\"
.\" $Id: ssh.1,v 1.8 1999/11/18 00:35:13 damien Exp $
.\" $Id: ssh.1,v 1.9 1999/11/24 13:26:23 damien Exp $
.\"
.Dd September 25, 1999
.Dt SSH 1
@ -662,6 +662,16 @@ or
RSA authentication will only be
attempted if the identity file exists, or an authentication agent is
running.
.It Cm SkeyAuthentication
Specifies whether to use
.Xr skey 1
authentication. The argument to
this keyword must be
.Dq yes
or
.Dq no .
The default is
.Dq no .
.It Cm CheckHostIP
If this flag is set to
.Dq yes ,

1307
ssh.c

Разница между файлами не показана из-за своего большого размера Загрузить разницу

347
ssh.h
Просмотреть файл

@ -1,19 +1,19 @@
/*
*
* ssh.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Fri Mar 17 17:09:37 1995 ylo
*
* Generic header file for ssh.
*
*/
ssh.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Fri Mar 17 17:09:37 1995 ylo
Generic header file for ssh.
*/
/* RCSID("$Id: ssh.h,v 1.14 1999/11/21 02:23:53 damien Exp $"); */
/* RCSID("$Id: ssh.h,v 1.15 1999/11/24 13:26:23 damien Exp $"); */
#ifndef SSH_H
#define SSH_H
@ -25,7 +25,7 @@ Generic header file for ssh.
#include "rsa.h"
#include "cipher.h"
/* The default cipher used if IDEA is not supported by the remote host.
/* The default cipher used if IDEA is not supported by the remote host.
It is recommended that this be one of the mandatory ciphers (DES, 3DES),
though that is not required. */
#define SSH_FALLBACK_CIPHER SSH_CIPHER_3DES
@ -59,7 +59,9 @@ Generic header file for ssh.
#define ETCDIR "/etc"
#endif /* ETCDIR */
#ifndef PIDDIR
#define PIDDIR "/var/run"
#endif /* PIDDIR */
/* System-wide file containing host keys of known hosts. This file should be
world-readable. */
@ -76,15 +78,15 @@ only by root, whereas ssh_config should be world-readable. */
#define HOST_CONFIG_FILE ETCDIR "/ssh_config"
#ifndef SSH_PROGRAM
#define SSH_PROGRAM "/usr/bin/ssh"
#define SSH_PROGRAM "/usr/bin/ssh"
#endif /* SSH_PROGRAM */
#ifndef LOGIN_PROGRAM
#define LOGIN_PROGRAM "/usr/bin/login"
#define LOGIN_PROGRAM "/usr/bin/login"
#endif /* LOGIN_PROGRAM */
#ifndef ASKPASS_PROGRAM
#define ASKPASS_PROGRAM "/usr/lib/ssh/ssh-askpass"
#define ASKPASS_PROGRAM "/usr/lib/ssh/ssh-askpass"
#endif /* ASKPASS_PROGRAM */
/* The process id of the daemon listening for connections is saved
@ -100,7 +102,7 @@ only by root, whereas ssh_config should be world-readable. */
not contain anything particularly secret. */
#define SSH_USER_HOSTFILE "~/.ssh/known_hosts"
/* Name of the default file containing client-side authentication key.
/* Name of the default file containing client-side authentication key.
This file should only be readable by the user him/herself. */
#define SSH_CLIENT_IDENTITY ".ssh/identity"
@ -116,7 +118,7 @@ only by root, whereas ssh_config should be world-readable. */
readable by anyone but the user him/herself, but does not contain
anything particularly secret. If the user\'s home directory resides
on an NFS volume where root is mapped to nobody, this may need to be
world-readable. (This file is read by the daemon which is running as
world-readable. (This file is read by the daemon which is running as
root.) */
#define SSH_USER_PERMITTED_KEYS ".ssh/authorized_keys"
@ -130,7 +132,7 @@ only by root, whereas ssh_config should be world-readable. */
/* Ssh-only version of /etc/hosts.equiv. */
#define SSH_HOSTS_EQUIV ETCDIR "/shosts.equiv"
/* Additionally, the daemon may use ~/.rhosts and /etc/hosts.equiv if
/* Additionally, the daemon may use ~/.rhosts and /etc/hosts.equiv if
rhosts authentication is enabled. */
/* Name of the environment variable containing the pathname of the
@ -145,7 +147,7 @@ only by root, whereas ssh_config should be world-readable. */
many bits. This is to make double encryption with rsaref work. */
#define SSH_KEY_BITS_RESERVED 128
/* Length of the session key in bytes. (Specified as 256 bits in the
/* Length of the session key in bytes. (Specified as 256 bits in the
protocol.) */
#define SSH_SESSION_KEY_LENGTH 32
@ -158,21 +160,23 @@ only by root, whereas ssh_config should be world-readable. */
#define SSH_AUTH_RSA 2
#define SSH_AUTH_PASSWORD 3
#define SSH_AUTH_RHOSTS_RSA 4
/* 5 is TIS */
#define SSH_AUTH_TIS 5
#define SSH_AUTH_KERBEROS 6
#define SSH_PASS_KERBEROS_TGT 7
/* 8 to 15 are reserved */
/* 8 to 15 are reserved */
#define SSH_PASS_AFS_TOKEN 21
/* Protocol flags. These are bit masks. */
#define SSH_PROTOFLAG_SCREEN_NUMBER 1 /* X11 forwarding includes screen */
#define SSH_PROTOFLAG_HOST_IN_FWD_OPEN 2 /* forwarding opens contain host */
#define SSH_PROTOFLAG_SCREEN_NUMBER 1 /* X11 forwarding includes
* screen */
#define SSH_PROTOFLAG_HOST_IN_FWD_OPEN 2 /* forwarding opens contain
* host */
/* Definition of message types. New values can be added, but old values
should not be removed or without careful consideration of the consequences
for compatibility. The maximum value is 254; value 255 is reserved
for future extension. */
/* Message name */ /* msg code */ /* arguments */
/* Message name *//* msg code *//* arguments */
#define SSH_MSG_NONE 0 /* no message */
#define SSH_MSG_DISCONNECT 1 /* cause (string) */
#define SSH_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */
@ -212,10 +216,9 @@ only by root, whereas ssh_config should be world-readable. */
#define SSH_MSG_DEBUG 36 /* string */
#define SSH_CMSG_REQUEST_COMPRESSION 37 /* level 1-9 (int) */
#define SSH_CMSG_MAX_PACKET_SIZE 38 /* size 4k-1024k (int) */
#define SSH_CMSG_AUTH_TIS 39 /* this is proto-1.5, but we ignore TIS */
#define SSH_SMSG_AUTH_TIS_CHALLENGE 40
#define SSH_CMSG_AUTH_TIS_RESPONSE 41
#define SSH_CMSG_AUTH_TIS 39 /* we use this for s/key */
#define SSH_SMSG_AUTH_TIS_CHALLENGE 40 /* challenge (string) */
#define SSH_CMSG_AUTH_TIS_RESPONSE 41 /* response (string) */
#define SSH_CMSG_AUTH_KERBEROS 42 /* (KTEXT) */
#define SSH_SMSG_AUTH_KERBEROS_RESPONSE 43 /* (KTEXT) */
#define SSH_CMSG_HAVE_KERBEROS_TGT 44 /* credentials (s) */
@ -223,74 +226,79 @@ only by root, whereas ssh_config should be world-readable. */
/*------------ definitions for login.c -------------*/
/* Returns the time when the user last logged in. Returns 0 if the
information is not available. This must be called before record_login.
/* Returns the time when the user last logged in. Returns 0 if the
information is not available. This must be called before record_login.
The host from which the user logged in is stored in buf. */
unsigned long get_last_login_time(uid_t uid, const char *logname,
char *buf, unsigned int bufsize);
unsigned long
get_last_login_time(uid_t uid, const char *logname,
char *buf, unsigned int bufsize);
/* Records that the user has logged in. This does many things normally
done by login(1). */
void record_login(int pid, const char *ttyname, const char *user, uid_t uid,
const char *host, struct sockaddr_in *addr);
void
record_login(int pid, const char *ttyname, const char *user, uid_t uid,
const char *host, struct sockaddr_in * addr);
/* Records that the user has logged out. This does many thigs normally
done by login(1) or init. */
void record_logout(int pid, const char *ttyname);
void record_logout(int pid, const char *ttyname);
/*------------ definitions for sshconnect.c ----------*/
/* Opens a TCP/IP connection to the remote server on the given host. If
port is 0, the default port will be used. If anonymous is zero,
a privileged port will be allocated to make the connection.
This requires super-user privileges if anonymous is false.
a privileged port will be allocated to make the connection.
This requires super-user privileges if anonymous is false.
Connection_attempts specifies the maximum number of tries, one per
second. This returns true on success, and zero on failure. If the
connection is successful, this calls packet_set_connection for the
connection. */
int ssh_connect(const char *host, struct sockaddr_in *hostaddr,
int port, int connection_attempts,
int anonymous, uid_t original_real_uid,
const char *proxy_command);
int
ssh_connect(const char *host, struct sockaddr_in * hostaddr,
int port, int connection_attempts,
int anonymous, uid_t original_real_uid,
const char *proxy_command);
/* Starts a dialog with the server, and authenticates the current user on the
server. This does not need any extra privileges. The basic connection
to the server must already have been established before this is called.
If login fails, this function prints an error and never returns.
to the server must already have been established before this is called.
If login fails, this function prints an error and never returns.
This initializes the random state, and leaves it initialized (it will also
have references from the packet module). */
void ssh_login(int host_key_valid, RSA *host_key, const char *host,
struct sockaddr_in *hostaddr, uid_t original_real_uid);
void
ssh_login(int host_key_valid, RSA * host_key, const char *host,
struct sockaddr_in * hostaddr, uid_t original_real_uid);
/*------------ Definitions for various authentication methods. -------*/
/* Tries to authenticate the user using the .rhosts file. Returns true if
authentication succeeds. If ignore_rhosts is non-zero, this will not
consider .rhosts and .shosts (/etc/hosts.equiv will still be used). */
int auth_rhosts(struct passwd *pw, const char *client_user);
int auth_rhosts(struct passwd * pw, const char *client_user);
/* Tries to authenticate the user using the .rhosts file and the host using
its host key. Returns true if authentication succeeds. */
int auth_rhosts_rsa(struct passwd *pw, const char *client_user,
BIGNUM *client_host_key_e, BIGNUM *client_host_key_n);
int
auth_rhosts_rsa(struct passwd * pw, const char *client_user,
BIGNUM * client_host_key_e, BIGNUM * client_host_key_n);
/* Tries to authenticate the user using password. Returns true if
authentication succeeds. */
int auth_password(struct passwd *pw, const char *password);
int auth_password(struct passwd * pw, const char *password);
/* Performs the RSA authentication dialog with the client. This returns
0 if the client could not be authenticated, and 1 if authentication was
successful. This may exit if there is a serious protocol violation. */
int auth_rsa(struct passwd *pw, BIGNUM *client_n);
int auth_rsa(struct passwd * pw, BIGNUM * client_n);
/* Parses an RSA key (number of bits, e, n) from a string. Moves the pointer
over the key. Skips any whitespace at the beginning and at end. */
int auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM *e, BIGNUM *n);
int auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n);
/* Returns the name of the machine at the other end of the socket. The
returned string should be freed by the caller. */
char *get_remote_hostname(int socket);
char *get_remote_hostname(int socket);
/* Return the canonical name of the host in the other side of the current
connection (as returned by packet_get_connection). The host name is
@ -302,296 +310,301 @@ const char *get_canonical_hostname(void);
const char *get_remote_ipaddr(void);
/* Returns the port number of the peer of the socket. */
int get_peer_port(int sock);
int get_peer_port(int sock);
/* Returns the port number of the remote host. */
int get_remote_port(void);
int get_remote_port(void);
/* Tries to match the host name (which must be in all lowercase) against the
comma-separated sequence of subpatterns (each possibly preceded by ! to
comma-separated sequence of subpatterns (each possibly preceded by ! to
indicate negation). Returns true if there is a positive match; zero
otherwise. */
int match_hostname(const char *host, const char *pattern, unsigned int len);
int match_hostname(const char *host, const char *pattern, unsigned int len);
/* Checks whether the given host is already in the list of our known hosts.
Returns HOST_OK if the host is known and has the specified key,
HOST_NEW if the host is not known, and HOST_CHANGED if the host is known
but used to have a different host key. The host must be in all lowercase. */
typedef enum { HOST_OK, HOST_NEW, HOST_CHANGED } HostStatus;
HostStatus check_host_in_hostfile(const char *filename, const char *host,
BIGNUM *e, BIGNUM *n, BIGNUM *ke, BIGNUM *kn);
typedef enum {
HOST_OK, HOST_NEW, HOST_CHANGED
} HostStatus;
HostStatus
check_host_in_hostfile(const char *filename, const char *host,
BIGNUM * e, BIGNUM * n, BIGNUM * ke, BIGNUM * kn);
/* Appends an entry to the host file. Returns false if the entry
could not be appended. */
int add_host_to_hostfile(const char *filename, const char *host,
BIGNUM *e, BIGNUM *n);
int
add_host_to_hostfile(const char *filename, const char *host,
BIGNUM * e, BIGNUM * n);
/* Performs the RSA authentication challenge-response dialog with the client,
and returns true (non-zero) if the client gave the correct answer to
our challenge; returns zero if the client gives a wrong answer. */
int auth_rsa_challenge_dialog(BIGNUM *e, BIGNUM *n);
int auth_rsa_challenge_dialog(BIGNUM * e, BIGNUM * n);
/* Reads a passphrase from /dev/tty with echo turned off. Returns the
passphrase (allocated with xmalloc). Exits if EOF is encountered.
/* Reads a passphrase from /dev/tty with echo turned off. Returns the
passphrase (allocated with xmalloc). Exits if EOF is encountered.
If from_stdin is true, the passphrase will be read from stdin instead. */
char *read_passphrase(const char *prompt, int from_stdin);
char *read_passphrase(const char *prompt, int from_stdin);
/* Saves the authentication (private) key in a file, encrypting it with
passphrase. The identification of the file (lowest 64 bits of n)
will precede the key to provide identification of the key without
needing a passphrase. */
int save_private_key(const char *filename, const char *passphrase,
RSA *private_key, const char *comment);
int
save_private_key(const char *filename, const char *passphrase,
RSA * private_key, const char *comment);
/* Loads the public part of the key file (public key and comment).
/* Loads the public part of the key file (public key and comment).
Returns 0 if an error occurred; zero if the public key was successfully
read. The comment of the key is returned in comment_return if it is
non-NULL; the caller must free the value with xfree. */
int load_public_key(const char *filename, RSA *pub,
char **comment_return);
int
load_public_key(const char *filename, RSA * pub,
char **comment_return);
/* Loads the private key from the file. Returns 0 if an error is encountered
(file does not exist or is not readable, or passphrase is bad).
This initializes the private key. The comment of the key is returned
in comment_return if it is non-NULL; the caller must free the value
This initializes the private key. The comment of the key is returned
in comment_return if it is non-NULL; the caller must free the value
with xfree. */
int load_private_key(const char *filename, const char *passphrase,
RSA *private_key, char **comment_return);
int
load_private_key(const char *filename, const char *passphrase,
RSA * private_key, char **comment_return);
/*------------ Definitions for logging. -----------------------*/
/* Supported syslog facilities and levels. */
typedef enum
{
SYSLOG_FACILITY_DAEMON,
SYSLOG_FACILITY_USER,
SYSLOG_FACILITY_AUTH,
SYSLOG_FACILITY_LOCAL0,
SYSLOG_FACILITY_LOCAL1,
SYSLOG_FACILITY_LOCAL2,
SYSLOG_FACILITY_LOCAL3,
SYSLOG_FACILITY_LOCAL4,
SYSLOG_FACILITY_LOCAL5,
SYSLOG_FACILITY_LOCAL6,
SYSLOG_FACILITY_LOCAL7
} SyslogFacility;
typedef enum
{
SYSLOG_LEVEL_QUIET,
SYSLOG_LEVEL_FATAL,
SYSLOG_LEVEL_ERROR,
SYSLOG_LEVEL_INFO,
SYSLOG_LEVEL_CHAT,
SYSLOG_LEVEL_DEBUG
} LogLevel;
typedef enum {
SYSLOG_FACILITY_DAEMON,
SYSLOG_FACILITY_USER,
SYSLOG_FACILITY_AUTH,
SYSLOG_FACILITY_LOCAL0,
SYSLOG_FACILITY_LOCAL1,
SYSLOG_FACILITY_LOCAL2,
SYSLOG_FACILITY_LOCAL3,
SYSLOG_FACILITY_LOCAL4,
SYSLOG_FACILITY_LOCAL5,
SYSLOG_FACILITY_LOCAL6,
SYSLOG_FACILITY_LOCAL7
} SyslogFacility;
typedef enum {
SYSLOG_LEVEL_QUIET,
SYSLOG_LEVEL_FATAL,
SYSLOG_LEVEL_ERROR,
SYSLOG_LEVEL_INFO,
SYSLOG_LEVEL_VERBOSE,
SYSLOG_LEVEL_DEBUG
} LogLevel;
/* Initializes logging. */
void log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr);
void log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr);
/* Logging implementation, depending on server or client */
void do_log(LogLevel level, const char *fmt, va_list args);
void do_log(LogLevel level, const char *fmt, va_list args);
/* name to facility/level */
SyslogFacility log_facility_number(char *name);
LogLevel log_level_number(char *name);
/* Output a message to syslog or stderr */
void fatal(const char *fmt, ...);
void error(const char *fmt, ...);
void log(const char *fmt, ...);
void chat(const char *fmt, ...);
void debug(const char *fmt, ...);
void fatal(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void error(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void log(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void verbose(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void debug(const char *fmt,...) __attribute__((format(printf, 1, 2)));
/* same as fatal() but w/o logging */
void fatal_cleanup(void);
void fatal_cleanup(void);
/* Registers a cleanup function to be called by fatal()/fatal_cleanup() before exiting.
/* Registers a cleanup function to be called by fatal()/fatal_cleanup() before exiting.
It is permissible to call fatal_remove_cleanup for the function itself
from the function. */
void fatal_add_cleanup(void (*proc)(void *context), void *context);
void fatal_add_cleanup(void (*proc) (void *context), void *context);
/* Removes a cleanup function to be called at fatal(). */
void fatal_remove_cleanup(void (*proc)(void *context), void *context);
void fatal_remove_cleanup(void (*proc) (void *context), void *context);
/*---------------- definitions for channels ------------------*/
/* Sets specific protocol options. */
void channel_set_options(int hostname_in_open);
void channel_set_options(int hostname_in_open);
/* Allocate a new channel object and set its type and socket. Remote_name
must have been allocated with xmalloc; this will free it when the channel
is freed. */
int channel_allocate(int type, int sock, char *remote_name);
int channel_allocate(int type, int sock, char *remote_name);
/* Free the channel and close its socket. */
void channel_free(int channel);
void channel_free(int channel);
/* Add any bits relevant to channels in select bitmasks. */
void channel_prepare_select(fd_set *readset, fd_set *writeset);
void channel_prepare_select(fd_set * readset, fd_set * writeset);
/* After select, perform any appropriate operations for channels which
have events pending. */
void channel_after_select(fd_set *readset, fd_set *writeset);
void channel_after_select(fd_set * readset, fd_set * writeset);
/* If there is data to send to the connection, send some of it now. */
void channel_output_poll(void);
void channel_output_poll(void);
/* This is called when a packet of type CHANNEL_DATA has just been received.
The message type has already been consumed, but channel number and data
is still there. */
void channel_input_data(int payload_len);
void channel_input_data(int payload_len);
/* Returns true if no channel has too much buffered data. */
int channel_not_very_much_buffered_data(void);
int channel_not_very_much_buffered_data(void);
/* This is called after receiving CHANNEL_CLOSE. */
void channel_input_close(void);
void channel_input_close(void);
/* This is called after receiving CHANNEL_CLOSE_CONFIRMATION. */
void channel_input_close_confirmation(void);
void channel_input_close_confirmation(void);
/* This is called after receiving CHANNEL_OPEN_CONFIRMATION. */
void channel_input_open_confirmation(void);
void channel_input_open_confirmation(void);
/* This is called after receiving CHANNEL_OPEN_FAILURE from the other side. */
void channel_input_open_failure(void);
void channel_input_open_failure(void);
/* This closes any sockets that are listening for connections; this removes
any unix domain sockets. */
void channel_stop_listening(void);
void channel_stop_listening(void);
/* Closes the sockets of all channels. This is used to close extra file
descriptors after a fork. */
void channel_close_all(void);
void channel_close_all(void);
/* Returns the maximum file descriptor number used by the channels. */
int channel_max_fd(void);
int channel_max_fd(void);
/* Returns true if there is still an open channel over the connection. */
int channel_still_open(void);
int channel_still_open(void);
/* Returns a string containing a list of all open channels. The list is
suitable for displaying to the user. It uses crlf instead of newlines.
The caller should free the string with xfree. */
char *channel_open_message(void);
char *channel_open_message(void);
/* Initiate forwarding of connections to local port "port" through the secure
channel to host:port from remote side. This never returns if there
was an error. */
void channel_request_local_forwarding(int port, const char *host,
int remote_port);
void
channel_request_local_forwarding(int port, const char *host,
int remote_port);
/* Initiate forwarding of connections to port "port" on remote host through
the secure channel to host:port from local side. This never returns
if there was an error. This registers that open requests for that
port are permitted. */
void channel_request_remote_forwarding(int port, const char *host,
int remote_port);
void
channel_request_remote_forwarding(int port, const char *host,
int remote_port);
/* Permits opening to any host/port in SSH_MSG_PORT_OPEN. This is usually
called by the server, because the user could connect to any port anyway,
and the server has no way to know but to trust the client anyway. */
void channel_permit_all_opens(void);
void channel_permit_all_opens(void);
/* This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
listening for the port, and sends back a success reply (or disconnect
message if there was an error). This never returns if there was an
message if there was an error). This never returns if there was an
error. */
void channel_input_port_forward_request(int is_root);
void channel_input_port_forward_request(int is_root);
/* This is called after receiving PORT_OPEN message. This attempts to connect
to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION or
CHANNEL_OPEN_FAILURE. */
void channel_input_port_open(int payload_len);
void channel_input_port_open(int payload_len);
/* Creates a port for X11 connections, and starts listening for it.
Returns the display name, or NULL if an error was encountered. */
char *x11_create_display(int screen);
char *x11_create_display(int screen);
/* Creates an internet domain socket for listening for X11 connections.
/* Creates an internet domain socket for listening for X11 connections.
Returns a suitable value for the DISPLAY variable, or NULL if an error
occurs. */
char *x11_create_display_inet(int screen);
char *x11_create_display_inet(int screen);
/* This is called when SSH_SMSG_X11_OPEN is received. The packet contains
the remote channel number. We should do whatever we want, and respond
with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE. */
void x11_input_open(int payload_len);
void x11_input_open(int payload_len);
/* Requests forwarding of X11 connections. This should be called on the
/* Requests forwarding of X11 connections. This should be called on the
client only. */
void x11_request_forwarding(void);
void x11_request_forwarding(void);
/* Requests forwarding for X11 connections, with authentication spoofing.
This should be called in the client only. */
void x11_request_forwarding_with_spoofing(const char *proto, const char *data);
void x11_request_forwarding_with_spoofing(const char *proto, const char *data);
/* Sends a message to the server to request authentication fd forwarding. */
void auth_request_forwarding(void);
void auth_request_forwarding(void);
/* Returns the name of the forwarded authentication socket. Returns NULL
if there is no forwarded authentication socket. The returned value points
to a static buffer. */
char *auth_get_socket_name(void);
char *auth_get_socket_name(void);
/* This if called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server.
This starts forwarding authentication requests. */
void auth_input_request_forwarding(struct passwd *pw);
void auth_input_request_forwarding(struct passwd * pw);
/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
void auth_input_open_request(void);
void auth_input_open_request(void);
/* Returns true if the given string matches the pattern (which may contain
? and * as wildcards), and zero if it does not match. */
int match_pattern(const char *s, const char *pattern);
int match_pattern(const char *s, const char *pattern);
/* Expands tildes in the file name. Returns data allocated by xmalloc.
Warning: this calls getpw*. */
char *tilde_expand_filename(const char *filename, uid_t my_uid);
char *tilde_expand_filename(const char *filename, uid_t my_uid);
/* Performs the interactive session. This handles data transmission between
the client and the program. Note that the notion of stdin, stdout, and
stderr in this function is sort of reversed: this function writes to
stdin (of the child program), and reads from stdout and stderr (of the
child program). */
void server_loop(int pid, int fdin, int fdout, int fderr);
void server_loop(int pid, int fdin, int fdout, int fderr);
/* 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);
/* Linked list of custom environment strings (see auth-rsa.c). */
struct envstring {
struct envstring *next;
char *s;
struct envstring *next;
char *s;
};
#ifdef KRB4
#include <krb.h>
/* Performs Kerberos v4 mutual authentication with the client. This returns
0 if the client could not be authenticated, and 1 if authentication was
successful. This may exit if there is a serious protocol violation. */
int auth_krb4(const char *server_user, KTEXT auth, char **client);
int krb4_init(uid_t uid);
void krb4_cleanup_proc(void *ignore);
int auth_krb4(const char *server_user, KTEXT auth, char **client);
int krb4_init(uid_t uid);
void krb4_cleanup_proc(void *ignore);
#ifdef AFS
#include <kafs.h>
/* Accept passed Kerberos v4 ticket-granting ticket and AFS tokens. */
int auth_kerberos_tgt(struct passwd *pw, const char *string);
int auth_afs_token(struct passwd *pw, const char *token_string);
int auth_kerberos_tgt(struct passwd * pw, const char *string);
int auth_afs_token(struct passwd * pw, const char *token_string);
int creds_to_radix(CREDENTIALS *creds, unsigned char *buf);
int radix_to_creds(const char *buf, CREDENTIALS *creds);
#endif /* AFS */
int creds_to_radix(CREDENTIALS * creds, unsigned char *buf);
int radix_to_creds(const char *buf, CREDENTIALS * creds);
#endif /* AFS */
#endif /* KRB4 */
#endif /* KRB4 */
#ifdef SKEY
#include <skey.h>
char *skey_fake_keyinfo(char *username);
#endif /* SKEY */
char *skey_fake_keyinfo(char *username);
#endif /* SKEY */
#endif /* SSH_H */
#endif /* SSH_H */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

12
sshd.8
Просмотреть файл

@ -9,7 +9,7 @@
.\"
.\" Created: Sat Apr 22 21:55:14 1995 ylo
.\"
.\" $Id: sshd.8,v 1.8 1999/11/21 02:23:53 damien Exp $
.\" $Id: sshd.8,v 1.9 1999/11/24 13:26:23 damien Exp $
.\"
.Dd September 25, 1999
.Dt SSHD 8
@ -26,6 +26,7 @@
.Op Fl h Ar host_key_file
.Op Fl k Ar key_gen_time
.Op Fl p Ar port
.Op Fl V Ar client_protocol_id
.Sh DESCRIPTION
.Nm
(Secure Shell Daemon) is the daemon program for
@ -165,6 +166,13 @@ Quiet mode. Nothing is sent to the system log. Normally the beginning,
authentication, and termination of each connection is logged.
.It Fl Q
Do not print an error message if RSA support is missing.
.It Fl V Ar client_protocol_id
SSH2 compatibility mode.
When this options is specified
.Nm
assumes the client has sent the given version string
and skips the
Protocol Version Identification Exchange.
.El
.Sh CONFIGURATION FILE
.Nm
@ -320,7 +328,7 @@ The default is 600 (seconds).
Gives the verbosity level that is used when logging messages from
.Nm sshd .
The possible values are:
QUIET, FATAL, ERROR, INFO, CHAT and DEBUG.
QUIET, FATAL, ERROR, INFO, VERBOSE and DEBUG.
The default is INFO.
Logging with level DEBUG violates the privacy of users
and is not recommended.

4329
sshd.c

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,70 +1,62 @@
/*
tildexpand.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Wed Jul 12 01:07:36 1995 ylo
*/
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Created: Wed Jul 12 01:07:36 1995 ylo
*/
#include "includes.h"
RCSID("$Id: tildexpand.c,v 1.1 1999/10/27 03:42:46 damien Exp $");
RCSID("$Id: tildexpand.c,v 1.2 1999/11/24 13:26:23 damien Exp $");
#include "xmalloc.h"
#include "ssh.h"
/* Expands tildes in the file name. Returns data allocated by xmalloc.
Warning: this calls getpw*. */
char *tilde_expand_filename(const char *filename, uid_t my_uid)
/*
* Expands tildes in the file name. Returns data allocated by xmalloc.
* Warning: this calls getpw*.
*/
char *
tilde_expand_filename(const char *filename, uid_t my_uid)
{
const char *cp;
unsigned int userlen;
char *expanded;
struct passwd *pw;
char user[100];
const char *cp;
unsigned int userlen;
char *expanded;
struct passwd *pw;
char user[100];
/* Return immediately if no tilde. */
if (filename[0] != '~')
return xstrdup(filename);
/* Return immediately if no tilde. */
if (filename[0] != '~')
return xstrdup(filename);
/* Skip the tilde. */
filename++;
/* Skip the tilde. */
filename++;
/* Find where the username ends. */
cp = strchr(filename, '/');
if (cp)
userlen = cp - filename; /* Have something after username. */
else
userlen = strlen(filename); /* Nothign after username. */
if (userlen == 0)
pw = getpwuid(my_uid); /* Own home directory. */
else
{
/* Tilde refers to someone elses home directory. */
if (userlen > sizeof(user) - 1)
fatal("User name after tilde too long.");
memcpy(user, filename, userlen);
user[userlen] = 0;
pw = getpwnam(user);
}
/* Find where the username ends. */
cp = strchr(filename, '/');
if (cp)
userlen = cp - filename; /* Something after username. */
else
userlen = strlen(filename); /* Nothing after username. */
if (userlen == 0)
pw = getpwuid(my_uid); /* Own home directory. */
else {
/* Tilde refers to someone elses home directory. */
if (userlen > sizeof(user) - 1)
fatal("User name after tilde too long.");
memcpy(user, filename, userlen);
user[userlen] = 0;
pw = getpwnam(user);
}
/* Check that we found the user. */
if (!pw)
fatal("Unknown user %100s.", user);
/* Check that we found the user. */
if (!pw)
fatal("Unknown user %100s.", user);
/* If referring to someones home directory, return it now. */
if (!cp)
{ /* Only home directory specified */
return xstrdup(pw->pw_dir);
}
/* Build a path combining the specified directory and path. */
expanded = xmalloc(strlen(pw->pw_dir) + strlen(cp + 1) + 2);
sprintf(expanded, "%s/%s", pw->pw_dir, cp + 1);
return expanded;
/* If referring to someones home directory, return it now. */
if (!cp) { /* Only home directory specified */
return xstrdup(pw->pw_dir);
}
/* Build a path combining the specified directory and path. */
expanded = xmalloc(strlen(pw->pw_dir) + strlen(cp + 1) + 2);
sprintf(expanded, "%s/%s", pw->pw_dir, cp + 1);
return expanded;
}

Просмотреть файл

@ -1,233 +1,229 @@
/*
ttymodes.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Tue Mar 21 15:59:15 1995 ylo
Encoding and decoding of terminal modes in a portable way.
Much of the format is defined in ttymodes.h; it is included multiple times
into this file with the appropriate macro definitions to generate the
suitable code.
*/
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Created: Tue Mar 21 15:59:15 1995 ylo
* Encoding and decoding of terminal modes in a portable way.
* Much of the format is defined in ttymodes.h; it is included multiple times
* into this file with the appropriate macro definitions to generate the
* suitable code.
*/
#include "includes.h"
RCSID("$Id: ttymodes.c,v 1.1 1999/10/27 03:42:46 damien Exp $");
RCSID("$Id: ttymodes.c,v 1.2 1999/11/24 13:26:23 damien Exp $");
#include "packet.h"
#include "ssh.h"
#define TTY_OP_END 0
#define TTY_OP_ISPEED 192 /* int follows */
#define TTY_OP_OSPEED 193 /* int follows */
#define TTY_OP_ISPEED 192 /* int follows */
#define TTY_OP_OSPEED 193 /* int follows */
/* Converts POSIX speed_t to a baud rate. The values of the constants
for speed_t are not themselves portable. */
static int speed_to_baud(speed_t speed)
/*
* Converts POSIX speed_t to a baud rate. The values of the
* constants for speed_t are not themselves portable.
*/
static int
speed_to_baud(speed_t speed)
{
switch (speed)
{
case B0:
return 0;
case B50:
return 50;
case B75:
return 75;
case B110:
return 110;
case B134:
return 134;
case B150:
return 150;
case B200:
return 200;
case B300:
return 300;
case B600:
return 600;
case B1200:
return 1200;
case B1800:
return 1800;
case B2400:
return 2400;
case B4800:
return 4800;
case B9600:
return 9600;
switch (speed) {
case B0:
return 0;
case B50:
return 50;
case B75:
return 75;
case B110:
return 110;
case B134:
return 134;
case B150:
return 150;
case B200:
return 200;
case B300:
return 300;
case B600:
return 600;
case B1200:
return 1200;
case B1800:
return 1800;
case B2400:
return 2400;
case B4800:
return 4800;
case B9600:
return 9600;
#ifdef B19200
case B19200:
return 19200;
case B19200:
return 19200;
#else /* B19200 */
#ifdef EXTA
case EXTA:
return 19200;
case EXTA:
return 19200;
#endif /* EXTA */
#endif /* B19200 */
#ifdef B38400
case B38400:
return 38400;
case B38400:
return 38400;
#else /* B38400 */
#ifdef EXTB
case EXTB:
return 38400;
case EXTB:
return 38400;
#endif /* EXTB */
#endif /* B38400 */
#ifdef B7200
case B7200:
return 7200;
case B7200:
return 7200;
#endif /* B7200 */
#ifdef B14400
case B14400:
return 14400;
case B14400:
return 14400;
#endif /* B14400 */
#ifdef B28800
case B28800:
return 28800;
case B28800:
return 28800;
#endif /* B28800 */
#ifdef B57600
case B57600:
return 57600;
case B57600:
return 57600;
#endif /* B57600 */
#ifdef B76800
case B76800:
return 76800;
case B76800:
return 76800;
#endif /* B76800 */
#ifdef B115200
case B115200:
return 115200;
case B115200:
return 115200;
#endif /* B115200 */
#ifdef B230400
case B230400:
return 230400;
case B230400:
return 230400;
#endif /* B230400 */
default:
return 9600;
}
default:
return 9600;
}
}
/* Converts a numeric baud rate to a POSIX speed_t. */
static speed_t baud_to_speed(int baud)
/*
* Converts a numeric baud rate to a POSIX speed_t.
*/
static speed_t
baud_to_speed(int baud)
{
switch (baud)
{
case 0:
return B0;
case 50:
return B50;
case 75:
return B75;
case 110:
return B110;
case 134:
return B134;
case 150:
return B150;
case 200:
return B200;
case 300:
return B300;
case 600:
return B600;
case 1200:
return B1200;
case 1800:
return B1800;
case 2400:
return B2400;
case 4800:
return B4800;
case 9600:
return B9600;
switch (baud) {
case 0:
return B0;
case 50:
return B50;
case 75:
return B75;
case 110:
return B110;
case 134:
return B134;
case 150:
return B150;
case 200:
return B200;
case 300:
return B300;
case 600:
return B600;
case 1200:
return B1200;
case 1800:
return B1800;
case 2400:
return B2400;
case 4800:
return B4800;
case 9600:
return B9600;
#ifdef B19200
case 19200:
return B19200;
case 19200:
return B19200;
#else /* B19200 */
#ifdef EXTA
case 19200:
return EXTA;
case 19200:
return EXTA;
#endif /* EXTA */
#endif /* B19200 */
#ifdef B38400
case 38400:
return B38400;
case 38400:
return B38400;
#else /* B38400 */
#ifdef EXTB
case 38400:
return EXTB;
case 38400:
return EXTB;
#endif /* EXTB */
#endif /* B38400 */
#ifdef B7200
case 7200:
return B7200;
case 7200:
return B7200;
#endif /* B7200 */
#ifdef B14400
case 14400:
return B14400;
case 14400:
return B14400;
#endif /* B14400 */
#ifdef B28800
case 28800:
return B28800;
case 28800:
return B28800;
#endif /* B28800 */
#ifdef B57600
case 57600:
return B57600;
case 57600:
return B57600;
#endif /* B57600 */
#ifdef B76800
case 76800:
return B76800;
case 76800:
return B76800;
#endif /* B76800 */
#ifdef B115200
case 115200:
return B115200;
case 115200:
return B115200;
#endif /* B115200 */
#ifdef B230400
case 230400:
return B230400;
case 230400:
return B230400;
#endif /* B230400 */
default:
return B9600;
}
default:
return B9600;
}
}
/* Encodes terminal modes for the terminal referenced by fd in a portable
manner, and appends the modes to a packet being constructed. */
void tty_make_modes(int fd)
/*
* Encodes terminal modes for the terminal referenced by fd
* in a portable manner, and appends the modes to a packet
* being constructed.
*/
void
tty_make_modes(int fd)
{
struct termios tio;
int baud;
struct termios tio;
int baud;
/* Get the modes. */
if (tcgetattr(fd, &tio) < 0)
{
packet_put_char(TTY_OP_END);
log("tcgetattr: %.100s", strerror(errno));
return;
}
/* Get the modes. */
if (tcgetattr(fd, &tio) < 0) {
packet_put_char(TTY_OP_END);
log("tcgetattr: %.100s", strerror(errno));
return;
}
/* Store input and output baud rates. */
baud = speed_to_baud(cfgetospeed(&tio));
packet_put_char(TTY_OP_OSPEED);
packet_put_int(baud);
baud = speed_to_baud(cfgetispeed(&tio));
packet_put_char(TTY_OP_ISPEED);
packet_put_int(baud);
/* Store input and output baud rates. */
baud = speed_to_baud(cfgetospeed(&tio));
packet_put_char(TTY_OP_OSPEED);
packet_put_int(baud);
baud = speed_to_baud(cfgetispeed(&tio));
packet_put_char(TTY_OP_ISPEED);
packet_put_int(baud);
/* Store values of mode flags. */
/* Store values of mode flags. */
#define TTYCHAR(NAME, OP) \
packet_put_char(OP); packet_put_char(tio.c_cc[NAME]);
#define TTYMODE(NAME, FIELD, OP) \
@ -244,48 +240,50 @@ void tty_make_modes(int fd)
#undef SGTTYMODE
#undef SGTTYMODEN
/* Mark end of mode data. */
packet_put_char(TTY_OP_END);
/* Mark end of mode data. */
packet_put_char(TTY_OP_END);
}
/* Decodes terminal modes for the terminal referenced by fd in a portable
manner from a packet being read. */
void tty_parse_modes(int fd, int *n_bytes_ptr)
/*
* Decodes terminal modes for the terminal referenced by fd in a portable
* manner from a packet being read.
*/
void
tty_parse_modes(int fd, int *n_bytes_ptr)
{
struct termios tio;
int opcode, baud;
int n_bytes = 0;
int failure = 0;
struct termios tio;
int opcode, baud;
int n_bytes = 0;
int failure = 0;
/* Get old attributes for the terminal. We will modify these flags.
I am hoping that if there are any machine-specific modes, they will
initially have reasonable values. */
if (tcgetattr(fd, &tio) < 0)
failure = -1;
/*
* Get old attributes for the terminal. We will modify these
* flags. I am hoping that if there are any machine-specific
* modes, they will initially have reasonable values.
*/
if (tcgetattr(fd, &tio) < 0)
failure = -1;
for (;;)
{
n_bytes += 1;
opcode = packet_get_char();
switch (opcode)
{
case TTY_OP_END:
goto set;
for (;;) {
n_bytes += 1;
opcode = packet_get_char();
switch (opcode) {
case TTY_OP_END:
goto set;
case TTY_OP_ISPEED:
n_bytes += 4;
baud = packet_get_int();
if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) < 0)
error("cfsetispeed failed for %d", baud);
break;
case TTY_OP_ISPEED:
n_bytes += 4;
baud = packet_get_int();
if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) < 0)
error("cfsetispeed failed for %d", baud);
break;
case TTY_OP_OSPEED:
n_bytes += 4;
baud = packet_get_int();
if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) < 0)
error("cfsetospeed failed for %d", baud);
break;
case TTY_OP_OSPEED:
n_bytes += 4;
baud = packet_get_int();
if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) < 0)
error("cfsetospeed failed for %d", baud);
break;
#define TTYCHAR(NAME, OP) \
case OP: \
@ -312,48 +310,51 @@ void tty_parse_modes(int fd, int *n_bytes_ptr)
#undef SGTTYMODE
#undef SGTTYMODEN
default:
debug("Ignoring unsupported tty mode opcode %d (0x%x)",
opcode, opcode);
/* Opcodes 0 to 127 are defined to have a one-byte argument. */
if (opcode >= 0 && opcode < 128)
{
n_bytes += 1;
(void)packet_get_char();
break;
}
else
{
/* Opcodes 128 to 159 are defined to have an integer argument. */
if (opcode >= 128 && opcode < 160)
{
n_bytes += 4;
(void)packet_get_int();
break;
default:
debug("Ignoring unsupported tty mode opcode %d (0x%x)",
opcode, opcode);
/*
* Opcodes 0 to 127 are defined to have
* a one-byte argument.
*/
if (opcode >= 0 && opcode < 128) {
n_bytes += 1;
(void) packet_get_char();
break;
} else {
/*
* Opcodes 128 to 159 are defined to have
* an integer argument.
*/
if (opcode >= 128 && opcode < 160) {
n_bytes += 4;
(void) packet_get_int();
break;
}
}
/*
* It is a truly undefined opcode (160 to 255).
* We have no idea about its arguments. So we
* must stop parsing. Note that some data may be
* left in the packet; hopefully there is nothing
* more coming after the mode data.
*/
log("parse_tty_modes: unknown opcode %d", opcode);
packet_integrity_check(0, 1, SSH_CMSG_REQUEST_PTY);
goto set;
}
}
/* It is a truly undefined opcode (160 to 255). We have no idea
about its arguments. So we must stop parsing. Note that some
data may be left in the packet; hopefully there is nothing more
coming after the mode data. */
log("parse_tty_modes: unknown opcode %d", opcode);
packet_integrity_check(0, 1, SSH_CMSG_REQUEST_PTY);
goto set;
}
}
set:
if (*n_bytes_ptr != n_bytes)
{
*n_bytes_ptr = n_bytes;
return; /* Don't process bytes passed */
}
set:
if (*n_bytes_ptr != n_bytes) {
*n_bytes_ptr = n_bytes;
return; /* Don't process bytes passed */
}
if (failure == -1)
return; /* Packet parsed ok but tty stuff failed */
if (failure == -1)
return; /* Packet parsed ok but tty stuff failed */
/* Set the new modes for the terminal. */
if (tcsetattr(fd, TCSANOW, &tio) < 0)
log("Setting tty modes failed: %.100s", strerror(errno));
return;
/* Set the new modes for the terminal. */
if (tcsetattr(fd, TCSANOW, &tio) < 0)
log("Setting tty modes failed: %.100s", strerror(errno));
return;
}

Просмотреть файл

@ -1,138 +1,140 @@
/*
*
* ttymodes.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* SGTTY stuff contributed by Janne Snabb <snabb@niksula.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Tue Mar 21 15:42:09 1995 ylo
*
*/
ttymodes.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
SGTTY stuff contributed by Janne Snabb <snabb@niksula.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Tue Mar 21 15:42:09 1995 ylo
*/
/* RCSID("$Id: ttymodes.h,v 1.1 1999/10/27 03:42:46 damien Exp $"); */
/* RCSID("$Id: ttymodes.h,v 1.2 1999/11/24 13:26:23 damien Exp $"); */
/* The tty mode description is a stream of bytes. The stream consists of
opcode-arguments pairs. It is terminated by opcode TTY_OP_END (0).
Opcodes 1-127 have one-byte arguments. Opcodes 128-159 have integer
arguments. Opcodes 160-255 are not yet defined, and cause parsing to
stop (they should only be used after any other data).
* opcode-arguments pairs. It is terminated by opcode TTY_OP_END (0).
* Opcodes 1-127 have one-byte arguments. Opcodes 128-159 have integer
* arguments. Opcodes 160-255 are not yet defined, and cause parsing to
* stop (they should only be used after any other data).
*
* The client puts in the stream any modes it knows about, and the
* server ignores any modes it does not know about. This allows some degree
* of machine-independence, at least between systems that use a posix-like
* tty interface. The protocol can support other systems as well, but might
* require reimplementing as mode names would likely be different.
*/
The client puts in the stream any modes it knows about, and the
server ignores any modes it does not know about. This allows some degree
of machine-independence, at least between systems that use a posix-like
tty interface. The protocol can support other systems as well, but might
require reimplementing as mode names would likely be different. */
/* Some constants and prototypes are defined in packet.h; this file
is only intended for including from ttymodes.h. */
/*
* Some constants and prototypes are defined in packet.h; this file
* is only intended for including from ttymodes.h.
*/
/* termios macro */ /* sgtty macro */
/* termios macro *//* sgtty macro */
/* name, op */
TTYCHAR(VINTR, 1) SGTTYCHAR(tiotc.t_intrc, 1)
TTYCHAR(VQUIT, 2) SGTTYCHAR(tiotc.t_quitc, 2)
TTYCHAR(VERASE, 3) SGTTYCHAR(tio.sg_erase, 3)
TTYCHAR(VINTR, 1) SGTTYCHAR(tiotc.t_intrc, 1)
TTYCHAR(VQUIT, 2) SGTTYCHAR(tiotc.t_quitc, 2)
TTYCHAR(VERASE, 3) SGTTYCHAR(tio.sg_erase, 3)
#if defined(VKILL)
TTYCHAR(VKILL, 4) SGTTYCHAR(tio.sg_kill, 4)
#endif /* VKILL */
TTYCHAR(VEOF, 5) SGTTYCHAR(tiotc.t_eofc, 5)
TTYCHAR(VKILL, 4) SGTTYCHAR(tio.sg_kill, 4)
#endif /* VKILL */
TTYCHAR(VEOF, 5) SGTTYCHAR(tiotc.t_eofc, 5)
#if defined(VEOL)
TTYCHAR(VEOL, 6) SGTTYCHAR(tiotc.t_brkc, 6)
#endif /* VEOL */
TTYCHAR(VEOL, 6) SGTTYCHAR(tiotc.t_brkc, 6)
#endif /* VEOL */
#ifdef VEOL2 /* n/a */
TTYCHAR(VEOL2, 7)
#endif /* VEOL2 */
TTYCHAR(VSTART, 8) SGTTYCHAR(tiotc.t_startc, 8)
TTYCHAR(VSTOP, 9) SGTTYCHAR(tiotc.t_stopc, 9)
#endif /* VEOL2 */
TTYCHAR(VSTART, 8) SGTTYCHAR(tiotc.t_startc, 8)
TTYCHAR(VSTOP, 9) SGTTYCHAR(tiotc.t_stopc, 9)
#if defined(VSUSP)
TTYCHAR(VSUSP, 10) SGTTYCHAR(tioltc.t_suspc, 10)
#endif /* VSUSP */
TTYCHAR(VSUSP, 10) SGTTYCHAR(tioltc.t_suspc, 10)
#endif /* VSUSP */
#if defined(VDSUSP)
TTYCHAR(VDSUSP, 11) SGTTYCHAR(tioltc.t_dsuspc, 11)
#endif /* VDSUSP */
TTYCHAR(VDSUSP, 11) SGTTYCHAR(tioltc.t_dsuspc, 11)
#endif /* VDSUSP */
#if defined(VREPRINT)
TTYCHAR(VREPRINT, 12) SGTTYCHAR(tioltc.t_rprntc, 12)
#endif /* VREPRINT */
TTYCHAR(VREPRINT, 12) SGTTYCHAR(tioltc.t_rprntc, 12)
#endif /* VREPRINT */
#if defined(VWERASE)
TTYCHAR(VWERASE, 13) SGTTYCHAR(tioltc.t_werasc, 13)
#endif /* VWERASE */
TTYCHAR(VWERASE, 13) SGTTYCHAR(tioltc.t_werasc, 13)
#endif /* VWERASE */
#if defined(VLNEXT)
TTYCHAR(VLNEXT, 14) SGTTYCHAR(tioltc.t_lnextc, 14)
#endif /* VLNEXT */
TTYCHAR(VLNEXT, 14) SGTTYCHAR(tioltc.t_lnextc, 14)
#endif /* VLNEXT */
#if defined(VFLUSH)
TTYCHAR(VFLUSH, 15) SGTTYCHAR(tioltc.t_flushc, 15)
#endif /* VFLUSH */
TTYCHAR(VFLUSH, 15) SGTTYCHAR(tioltc.t_flushc, 15)
#endif /* VFLUSH */
#ifdef VSWTCH
TTYCHAR(VSWTCH, 16) /* n/a */
#endif /* VSWTCH */
#endif /* VSWTCH */
#if defined(VSTATUS)
TTYCHAR(VSTATUS, 17) SGTTYCHAR(tiots.tc_statusc, 17)
#endif /* VSTATUS */
TTYCHAR(VSTATUS, 17) SGTTYCHAR(tiots.tc_statusc, 17)
#endif /* VSTATUS */
#ifdef VDISCARD
TTYCHAR(VDISCARD, 18) /* n/a */
#endif /* VDISCARD */
#endif /* VDISCARD */
/* name, field, op */
TTYMODE(IGNPAR, c_iflag, 30) /* n/a */
TTYMODE(PARMRK, c_iflag, 31) /* n/a */
TTYMODE(INPCK, c_iflag, 32) SGTTYMODEN(ANYP, tio.sg_flags, 32)
TTYMODE(ISTRIP, c_iflag, 33) SGTTYMODEN(LPASS8, tiolm, 33)
TTYMODE(INLCR, c_iflag, 34) /* n/a */
TTYMODE(IGNCR, c_iflag, 35) /* n/a */
TTYMODE(ICRNL, c_iflag, 36) SGTTYMODE(CRMOD, tio.sg_flags, 36)
TTYMODE(IGNPAR, c_iflag, 30) /* n/a */
TTYMODE(PARMRK, c_iflag, 31) /* n/a */
TTYMODE(INPCK, c_iflag, 32) SGTTYMODEN(ANYP, tio.sg_flags, 32)
TTYMODE(ISTRIP, c_iflag, 33) SGTTYMODEN(LPASS8, tiolm, 33)
TTYMODE(INLCR, c_iflag, 34) /* n/a */
TTYMODE(IGNCR, c_iflag, 35) /* n/a */
TTYMODE(ICRNL, c_iflag, 36) SGTTYMODE(CRMOD, tio.sg_flags, 36)
#if defined(IUCLC)
TTYMODE(IUCLC, c_iflag, 37) SGTTYMODE(LCASE, tio.sg_flags, 37)
TTYMODE(IUCLC, c_iflag, 37) SGTTYMODE(LCASE, tio.sg_flags, 37)
#endif
TTYMODE(IXON, c_iflag, 38) /* n/a */
TTYMODE(IXANY, c_iflag, 39) SGTTYMODEN(LDECCTQ, tiolm, 39)
TTYMODE(IXOFF, c_iflag, 40) SGTTYMODE(TANDEM, tio.sg_flags, 40)
TTYMODE(IXON, c_iflag, 38) /* n/a */
TTYMODE(IXANY, c_iflag, 39) SGTTYMODEN(LDECCTQ, tiolm, 39)
TTYMODE(IXOFF, c_iflag, 40) SGTTYMODE(TANDEM, tio.sg_flags, 40)
#ifdef IMAXBEL
TTYMODE(IMAXBEL,c_iflag, 41) /* n/a */
#endif /* IMAXBEL */
TTYMODE(IMAXBEL, c_iflag, 41) /* n/a */
#endif /* IMAXBEL */
TTYMODE(ISIG, c_lflag, 50) /* n/a */
TTYMODE(ICANON, c_lflag, 51) SGTTYMODEN(CBREAK, tio.sg_flags, 51)
TTYMODE(ISIG, c_lflag, 50) /* n/a */
TTYMODE(ICANON, c_lflag, 51) SGTTYMODEN(CBREAK, tio.sg_flags, 51)
#ifdef XCASE
TTYMODE(XCASE, c_lflag, 52) /* n/a */
TTYMODE(XCASE, c_lflag, 52) /* n/a */
#endif
TTYMODE(ECHO, c_lflag, 53) SGTTYMODE(ECHO, tio.sg_flags, 53)
TTYMODE(ECHOE, c_lflag, 54) SGTTYMODE(LCRTERA, tiolm, 54)
TTYMODE(ECHOK, c_lflag, 55) SGTTYMODE(LCRTKIL, tiolm, 55)
TTYMODE(ECHONL, c_lflag, 56) /* n/a */
TTYMODE(NOFLSH, c_lflag, 57) SGTTYMODE(LNOFLSH, tiolm, 57)
TTYMODE(TOSTOP, c_lflag, 58) SGTTYMODE(LTOSTOP, tiolm, 58)
TTYMODE(ECHO, c_lflag, 53) SGTTYMODE(ECHO, tio.sg_flags, 53)
TTYMODE(ECHOE, c_lflag, 54) SGTTYMODE(LCRTERA, tiolm, 54)
TTYMODE(ECHOK, c_lflag, 55) SGTTYMODE(LCRTKIL, tiolm, 55)
TTYMODE(ECHONL, c_lflag, 56) /* n/a */
TTYMODE(NOFLSH, c_lflag, 57) SGTTYMODE(LNOFLSH, tiolm, 57)
TTYMODE(TOSTOP, c_lflag, 58) SGTTYMODE(LTOSTOP, tiolm, 58)
#ifdef IEXTEN
TTYMODE(IEXTEN, c_lflag, 59) /* n/a */
#endif /* IEXTEN */
#endif /* IEXTEN */
#if defined(ECHOCTL)
TTYMODE(ECHOCTL,c_lflag, 60) SGTTYMODE(LCTLECH, tiolm, 60)
#endif /* ECHOCTL */
TTYMODE(ECHOCTL, c_lflag, 60) SGTTYMODE(LCTLECH, tiolm, 60)
#endif /* ECHOCTL */
#ifdef ECHOKE
TTYMODE(ECHOKE, c_lflag, 61) /* n/a */
#endif /* ECHOKE */
TTYMODE(ECHOKE, c_lflag, 61) /* n/a */
#endif /* ECHOKE */
#if defined(PENDIN)
TTYMODE(PENDIN, c_lflag, 62) SGTTYMODE(LPENDIN, tiolm, 62)
#endif /* PENDIN */
TTYMODE(PENDIN, c_lflag, 62) SGTTYMODE(LPENDIN, tiolm, 62)
#endif /* PENDIN */
TTYMODE(OPOST, c_oflag, 70) /* n/a */
TTYMODE(OPOST, c_oflag, 70) /* n/a */
#if defined(OLCUC)
TTYMODE(OLCUC, c_oflag, 71) SGTTYMODE(LCASE, tio.sg_flags, 71)
TTYMODE(OLCUC, c_oflag, 71) SGTTYMODE(LCASE, tio.sg_flags, 71)
#endif
TTYMODE(ONLCR, c_oflag, 72) SGTTYMODE(CRMOD, tio.sg_flags, 72)
TTYMODE(ONLCR, c_oflag, 72) SGTTYMODE(CRMOD, tio.sg_flags, 72)
#ifdef OCRNL
TTYMODE(OCRNL, c_oflag, 73) /* n/a */
TTYMODE(OCRNL, c_oflag, 73) /* n/a */
#endif
#ifdef ONOCR
TTYMODE(ONOCR, c_oflag, 74) /* n/a */
TTYMODE(ONOCR, c_oflag, 74) /* n/a */
#endif
#ifdef ONLRET
TTYMODE(ONLRET, c_oflag, 75) /* n/a */
TTYMODE(ONLRET, c_oflag, 75) /* n/a */
#endif
TTYMODE(CS7, c_cflag, 90) /* n/a */
TTYMODE(CS8, c_cflag, 91) SGTTYMODE(LPASS8, tiolm, 91)
TTYMODE(PARENB, c_cflag, 92) /* n/a */
TTYMODE(PARODD, c_cflag, 93) SGTTYMODE(ODDP, tio.sg_flags, 93)
TTYMODE(CS7, c_cflag, 90) /* n/a */
TTYMODE(CS8, c_cflag, 91) SGTTYMODE(LPASS8, tiolm, 91)
TTYMODE(PARENB, c_cflag, 92) /* n/a */
TTYMODE(PARODD, c_cflag, 93) SGTTYMODE(ODDP, tio.sg_flags, 93)

115
uidswap.c
Просмотреть файл

@ -1,32 +1,25 @@
/*
uidswap.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Sat Sep 9 01:56:14 1995 ylo
Code for uid-swapping.
*/
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Created: Sat Sep 9 01:56:14 1995 ylo
* Code for uid-swapping.
*/
#include "includes.h"
RCSID("$Id: uidswap.c,v 1.1 1999/10/27 03:42:46 damien Exp $");
RCSID("$Id: uidswap.c,v 1.2 1999/11/24 13:26:23 damien Exp $");
#include "ssh.h"
#include "uidswap.h"
/* Note: all these functions must work in all of the following cases:
1. euid=0, ruid=0
2. euid=0, ruid!=0
3. euid!=0, ruid!=0
Additionally, they must work regardless of whether the system has
POSIX saved uids or not. */
/*
* Note: all these functions must work in all of the following cases:
* 1. euid=0, ruid=0
* 2. euid=0, ruid!=0
* 3. euid!=0, ruid!=0
* Additionally, they must work regardless of whether the system has
* POSIX saved uids or not.
*/
#ifdef _POSIX_SAVED_IDS
/* Lets assume that posix saved ids also work with seteuid, even though that
@ -37,59 +30,57 @@ RCSID("$Id: uidswap.c,v 1.1 1999/10/27 03:42:46 damien Exp $");
/* Saved effective uid. */
static uid_t saved_euid = 0;
/* Temporarily changes to the given uid. If the effective user id is not
root, this does nothing. This call cannot be nested. */
void temporarily_use_uid(uid_t uid)
/*
* Temporarily changes to the given uid. If the effective user
* id is not root, this does nothing. This call cannot be nested.
*/
void
temporarily_use_uid(uid_t uid)
{
#ifdef SAVED_IDS_WORK_WITH_SETEUID
/* Save the current euid. */
saved_euid = geteuid();
/* Save the current euid. */
saved_euid = geteuid();
/* Set the effective uid to the given (unprivileged) uid. */
if (seteuid(uid) == -1)
debug("seteuid %d: %.100s", (int)uid, strerror(errno));
/* Set the effective uid to the given (unprivileged) uid. */
if (seteuid(uid) == -1)
debug("seteuid %d: %.100s", (int) uid, strerror(errno));
#else /* SAVED_IDS_WORK_WITH_SETUID */
/* Propagate the privileged uid to all of our uids. */
if (setuid(geteuid()) < 0)
debug("setuid %d: %.100s", (int) geteuid(), strerror(errno));
/* Propagate the privileged uid to all of our uids. */
if (setuid(geteuid()) < 0)
debug("setuid %d: %.100s", (int)geteuid(), strerror(errno));
/* Set the effective uid to the given (unprivileged) uid. */
if (seteuid(uid) == -1)
debug("seteuid %d: %.100s", (int)uid, strerror(errno));
/* Set the effective uid to the given (unprivileged) uid. */
if (seteuid(uid) == -1)
debug("seteuid %d: %.100s", (int) uid, strerror(errno));
#endif /* SAVED_IDS_WORK_WITH_SETEUID */
}
/* Restores to the original uid. */
void restore_uid()
/*
* Restores to the original uid.
*/
void
restore_uid()
{
#ifdef SAVED_IDS_WORK_WITH_SETEUID
/* Set the effective uid back to the saved uid. */
if (seteuid(saved_euid) < 0)
debug("seteuid %d: %.100s", (int)saved_euid, strerror(errno));
/* Set the effective uid back to the saved uid. */
if (seteuid(saved_euid) < 0)
debug("seteuid %d: %.100s", (int) saved_euid, strerror(errno));
#else /* SAVED_IDS_WORK_WITH_SETEUID */
/* We are unable to restore the real uid to its unprivileged value. */
/* Propagate the real uid (usually more privileged) to effective uid
as well. */
setuid(getuid());
/* We are unable to restore the real uid to its unprivileged
value. */
/* Propagate the real uid (usually more privileged) to effective
uid as well. */
setuid(getuid());
#endif /* SAVED_IDS_WORK_WITH_SETEUID */
}
/* Permanently sets all uids to the given uid. This cannot be called while
temporarily_use_uid is effective. */
void permanently_set_uid(uid_t uid)
/*
* Permanently sets all uids to the given uid. This cannot be
* called while temporarily_use_uid is effective.
*/
void
permanently_set_uid(uid_t uid)
{
if (setuid(uid) < 0)
debug("setuid %d: %.100s", (int)uid, strerror(errno));
if (setuid(uid) < 0)
debug("setuid %d: %.100s", (int) uid, strerror(errno));
}

Просмотреть файл

@ -1,30 +1,36 @@
/*
uidswap.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Sat Sep 9 01:43:15 1995 ylo
Last modified: Sat Sep 9 02:34:04 1995 ylo
*/
*
* uidswap.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Sat Sep 9 01:43:15 1995 ylo
* Last modified: Sat Sep 9 02:34:04 1995 ylo
*
*/
#ifndef UIDSWAP_H
#define UIDSWAP_H
/* Temporarily changes to the given uid. If the effective user id is not
root, this does nothing. This call cannot be nested. */
void temporarily_use_uid(uid_t uid);
/*
* Temporarily changes to the given uid. If the effective user id is not
* root, this does nothing. This call cannot be nested.
*/
void temporarily_use_uid(uid_t uid);
/* Restores the original effective user id after temporarily_use_uid().
This should only be called while temporarily_use_uid is effective. */
void restore_uid();
/*
* Restores the original effective user id after temporarily_use_uid().
* This should only be called while temporarily_use_uid is effective.
*/
void restore_uid();
/* Permanently sets all uids to the given uid. This cannot be called while
temporarily_use_uid is effective. This must also clear any saved uids. */
void permanently_set_uid(uid_t uid);
/*
* Permanently sets all uids to the given uid. This cannot be called while
* temporarily_use_uid is effective. This must also clear any saved uids.
*/
void permanently_set_uid(uid_t uid);
#endif /* UIDSWAP_H */
#endif /* UIDSWAP_H */

Просмотреть файл

@ -1,56 +1,53 @@
/*
xmalloc.c
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Mon Mar 20 21:23:10 1995 ylo
Versions of malloc and friends that check their results, and never return
failure (they call fatal if they encounter an error).
*/
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Created: Mon Mar 20 21:23:10 1995 ylo
* Versions of malloc and friends that check their results, and never return
* failure (they call fatal if they encounter an error).
*/
#include "includes.h"
RCSID("$Id: xmalloc.c,v 1.1 1999/10/27 03:42:46 damien Exp $");
RCSID("$Id: xmalloc.c,v 1.2 1999/11/24 13:26:23 damien Exp $");
#include "ssh.h"
void *xmalloc(size_t size)
void *
xmalloc(size_t size)
{
void *ptr = malloc(size);
if (ptr == NULL)
fatal("xmalloc: out of memory (allocating %d bytes)", (int)size);
return ptr;
void *ptr = malloc(size);
if (ptr == NULL)
fatal("xmalloc: out of memory (allocating %d bytes)", (int) size);
return ptr;
}
void *xrealloc(void *ptr, size_t new_size)
void *
xrealloc(void *ptr, size_t new_size)
{
void *new_ptr;
void *new_ptr;
if (ptr == NULL)
fatal("xrealloc: NULL pointer given as argument");
new_ptr = realloc(ptr, new_size);
if (new_ptr == NULL)
fatal("xrealloc: out of memory (new_size %d bytes)", (int)new_size);
return new_ptr;
if (ptr == NULL)
fatal("xrealloc: NULL pointer given as argument");
new_ptr = realloc(ptr, new_size);
if (new_ptr == NULL)
fatal("xrealloc: out of memory (new_size %d bytes)", (int) new_size);
return new_ptr;
}
void xfree(void *ptr)
void
xfree(void *ptr)
{
if (ptr == NULL)
fatal("xfree: NULL pointer given as argument");
free(ptr);
if (ptr == NULL)
fatal("xfree: NULL pointer given as argument");
free(ptr);
}
char *xstrdup(const char *str)
char *
xstrdup(const char *str)
{
int len = strlen(str) + 1;
int len = strlen(str) + 1;
char *cp = xmalloc(len);
strlcpy(cp, str, len);
return cp;
char *cp = xmalloc(len);
strlcpy(cp, str, len);
return cp;
}

Просмотреть файл

@ -1,34 +1,34 @@
/*
*
* xmalloc.h
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Created: Mon Mar 20 22:09:17 1995 ylo
*
* Versions of malloc and friends that check their results, and never return
* failure (they call fatal if they encounter an error).
*
*/
xmalloc.h
Author: Tatu Ylonen <ylo@cs.hut.fi>
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
All rights reserved
Created: Mon Mar 20 22:09:17 1995 ylo
Versions of malloc and friends that check their results, and never return
failure (they call fatal if they encounter an error).
*/
/* RCSID("$Id: xmalloc.h,v 1.1 1999/10/27 03:42:46 damien Exp $"); */
/* RCSID("$Id: xmalloc.h,v 1.2 1999/11/24 13:26:23 damien Exp $"); */
#ifndef XMALLOC_H
#define XMALLOC_H
/* Like malloc, but calls fatal() if out of memory. */
void *xmalloc(size_t size);
void *xmalloc(size_t size);
/* Like realloc, but calls fatal() if out of memory. */
void *xrealloc(void *ptr, size_t new_size);
void *xrealloc(void *ptr, size_t new_size);
/* Frees memory allocated using xmalloc or xrealloc. */
void xfree(void *ptr);
void xfree(void *ptr);
/* Allocates memory using xmalloc, and copies the string into that memory. */
char *xstrdup(const char *str);
char *xstrdup(const char *str);
#endif /* XMALLOC_H */
#endif /* XMALLOC_H */