nomachine + additional changes applied to openssh 7.1p1 source base

This commit is contained in:
arif-pragmasys 2015-09-21 16:03:51 -05:00
parent 47c23e53d7
commit f4b56e2280
322 changed files with 44053 additions and 16163 deletions

View File

@ -59,7 +59,7 @@ LDFLAGS=-L. -Lopenbsd-compat/ -Lcontrib/win32/win32compat @LDFLAGS@
EXEEXT=@EXEEXT@
MANFMT=@MANFMT@
TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT)
TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT)
LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \

View File

@ -1,4 +1,4 @@
/* $OpenBSD: addrmatch.c,v 1.5 2010/02/26 20:29:54 djm Exp $ */
/* $OpenBSD: addrmatch.c,v 1.10 2015/07/08 19:04:21 markus Exp $ */
/*
* Copyright (c) 2004-2008 Damien Miller <djm@mindrot.org>
@ -31,7 +31,6 @@
#include "match.h"
#include "log.h"
#include "xmalloc.h"
struct xaddr {
sa_family_t af;
@ -88,13 +87,13 @@ addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa)
switch (sa->sa_family) {
case AF_INET:
if (slen < sizeof(*in4))
if (slen < (socklen_t)sizeof(*in4))
return -1;
xa->af = AF_INET;
memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4));
break;
case AF_INET6:
if (slen < sizeof(*in6))
if (slen < (socklen_t)sizeof(*in6))
return -1;
xa->af = AF_INET6;
memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6));
@ -318,7 +317,7 @@ addr_pton_cidr(const char *p, struct xaddr *n, u_int *l)
char addrbuf[64], *mp, *cp;
/* Don't modify argument */
if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) > sizeof(addrbuf))
if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) >= sizeof(addrbuf))
return -1;
if ((mp = strchr(addrbuf, '/')) != NULL) {
@ -420,7 +419,7 @@ addr_match_list(const char *addr, const char *_list)
goto foundit;
}
}
xfree(o);
free(o);
return ret;
}
@ -494,7 +493,7 @@ addr_match_cidr_list(const char *addr, const char *_list)
continue;
}
}
xfree(o);
free(o);
return ret;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: atomicio.c,v 1.26 2010/09/22 22:58:51 djm Exp $ */
/* $OpenBSD: atomicio.c,v 1.27 2015/01/16 06:40:12 deraadt Exp $ */
/*
* Copyright (c) 2006 Damien Miller. All rights reserved.
* Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
@ -41,6 +41,7 @@
#endif
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include "atomicio.h"
@ -56,8 +57,10 @@ atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n,
ssize_t res;
struct pollfd pfd;
#ifndef BROKEN_READ_COMPARISON
pfd.fd = fd;
pfd.events = f == read ? POLLIN : POLLOUT;
#endif
while (n > pos) {
res = (f) (fd, s + pos, n - pos);
switch (res) {
@ -65,7 +68,9 @@ atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n,
if (errno == EINTR)
continue;
if (errno == EAGAIN || errno == EWOULDBLOCK) {
#ifndef BROKEN_READ_COMPARISON
(void)poll(&pfd, 1, -1);
#endif
continue;
}
return 0;

View File

@ -1,4 +1,4 @@
/* $Id: audit-bsm.c,v 1.7 2011/01/17 10:15:29 dtucker Exp $ */
/* $Id: audit-bsm.c,v 1.8 2012/02/23 23:40:43 dtucker Exp $ */
/*
* TODO
@ -55,6 +55,10 @@
#include <string.h>
#include <unistd.h>
#ifdef BROKEN_BSM_API
#include <libscf.h>
#endif
#include "ssh.h"
#include "log.h"
#include "key.h"
@ -124,6 +128,12 @@ extern int aug_daemon_session(void);
extern Authctxt *the_authctxt;
static AuditInfoTermID ssh_bsm_tid;
#ifdef BROKEN_BSM_API
/* For some reason this constant is no longer defined
in Solaris 11. */
#define BSM_TEXTBUFSZ 256
#endif
/* Below is the low-level BSM interface code */
/*
@ -171,6 +181,65 @@ aug_get_machine(char *host, u_int32_t *addr, u_int32_t *type)
}
#endif
#ifdef BROKEN_BSM_API
/*
In Solaris 11 the audit daemon has been moved to SMF. In the process
they simply dropped getacna() from the API, since it read from a now
non-existent config file. This function re-implements getacna() to
read from the SMF repository instead.
*/
int
getacna(char *auditstring, int len)
{
scf_handle_t *handle = NULL;
scf_property_t *property = NULL;
scf_value_t *value = NULL;
int ret = 0;
handle = scf_handle_create(SCF_VERSION);
if (handle == NULL)
return -2; /* The man page for getacna on Solaris 10 states
we should return -2 in case of error and set
errno to indicate the error. We don't bother
with errno here, though, since the only use
of this function below doesn't check for errors
anyway.
*/
ret = scf_handle_bind(handle);
if (ret == -1)
return -2;
property = scf_property_create(handle);
if (property == NULL)
return -2;
ret = scf_handle_decode_fmri(handle,
"svc:/system/auditd:default/:properties/preselection/naflags",
NULL, NULL, NULL, NULL, property, 0);
if (ret == -1)
return -2;
value = scf_value_create(handle);
if (value == NULL)
return -2;
ret = scf_property_get_value(property, value);
if (ret == -1)
return -2;
ret = scf_value_get_astring(value, auditstring, len);
if (ret == -1)
return -2;
scf_value_destroy(value);
scf_property_destroy(property);
scf_handle_destroy(handle);
return 0;
}
#endif
/*
* Check if the specified event is selected (enabled) for auditing.
* Returns 1 if the event is selected, 0 if not and -1 on failure.
@ -223,7 +292,15 @@ bsm_audit_record(int typ, char *string, au_event_t event_no)
(void) au_write(ad, au_to_text(string));
(void) au_write(ad, AUToReturnFunc(typ, rc));
#ifdef BROKEN_BSM_API
/* The last argument is the event modifier flags. For
some seemingly undocumented reason it was added in
Solaris 11. */
rc = au_close(ad, AU_TO_WRITE, event_no, 0);
#else
rc = au_close(ad, AU_TO_WRITE, event_no);
#endif
if (rc < 0)
error("BSM audit: %s failed to write \"%s\" record: %s",
__func__, string, strerror(errno));

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-bsdauth.c,v 1.11 2007/09/21 08:15:29 djm Exp $ */
/* $OpenBSD: auth-bsdauth.c,v 1.13 2014/06/24 01:13:21 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@ -24,7 +24,6 @@
*/
#include "includes.h"
/*
* We support only client side kerberos on Windows.
*/
@ -35,6 +34,8 @@
#endif
#include <sys/types.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdarg.h>
@ -63,6 +64,11 @@ bsdauth_query(void *ctx, char **name, char **infotxt,
Authctxt *authctxt = ctx;
char *challenge = NULL;
*infotxt = NULL;
*numprompts = 0;
*prompts = NULL;
*echo_on = NULL;
if (authctxt->as != NULL) {
debug2("bsdauth_query: try reuse session");
challenge = auth_getitem(authctxt->as, AUTHV_CHALLENGE);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-chall.c,v 1.12 2006/08/03 03:34:41 deraadt Exp $ */
/* $OpenBSD: auth-chall.c,v 1.14 2014/06/24 01:13:21 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@ -26,14 +26,16 @@
#include "includes.h"
#include <sys/types.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include "xmalloc.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
/* limited protocol v1 interface to kbd-interactive authentication */
@ -69,11 +71,11 @@ get_challenge(Authctxt *authctxt)
fatal("get_challenge: numprompts < 1");
challenge = xstrdup(prompts[0]);
for (i = 0; i < numprompts; i++)
xfree(prompts[i]);
xfree(prompts);
xfree(name);
xfree(echo_on);
xfree(info);
free(prompts[i]);
free(prompts);
free(name);
free(echo_on);
free(info);
return (challenge);
}
@ -102,11 +104,11 @@ verify_response(Authctxt *authctxt, const char *response)
authenticated = 1;
for (i = 0; i < numprompts; i++)
xfree(prompts[i]);
xfree(prompts);
xfree(name);
xfree(echo_on);
xfree(info);
free(prompts[i]);
free(prompts);
free(name);
free(echo_on);
free(info);
break;
}
device->free_ctx(authctxt->kbdintctxt);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-krb5.c,v 1.19 2006/08/03 03:34:41 deraadt Exp $ */
/* $OpenBSD: auth-krb5.c,v 1.20 2013/07/20 01:55:13 djm Exp $ */
/*
* Kerberos v5 authentication and ticket-passing routines.
*
@ -49,6 +49,7 @@
#include "packet.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "uidswap.h"
#include "key.h"
@ -88,6 +89,7 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
krb5_ccache ccache = NULL;
int len;
char *client, *platform_client;
const char *errmsg;
/* get platform-specific kerberos client principal name (if it exists) */
platform_client = platform_krb5_get_principal_name(authctxt->pw->pw_name);
@ -105,7 +107,12 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
goto out;
#ifdef HEIMDAL
# ifdef HAVE_KRB5_CC_NEW_UNIQUE
problem = krb5_cc_new_unique(authctxt->krb5_ctx,
krb5_mcc_ops.prefix, NULL, &ccache);
# else
problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache);
# endif
if (problem)
goto out;
@ -124,8 +131,13 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
if (problem)
goto out;
# ifdef HAVE_KRB5_CC_NEW_UNIQUE
problem = krb5_cc_new_unique(authctxt->krb5_ctx,
krb5_fcc_ops.prefix, NULL, &authctxt->krb5_fwd_ccache);
# else
problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops,
&authctxt->krb5_fwd_ccache);
# endif
if (problem)
goto out;
@ -155,7 +167,8 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
if (problem)
goto out;
if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) {
if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
authctxt->pw->pw_name)) {
problem = -1;
goto out;
}
@ -190,17 +203,19 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
out:
restore_uid();
if (platform_client != NULL)
xfree(platform_client);
free(platform_client);
if (problem) {
if (ccache)
krb5_cc_destroy(authctxt->krb5_ctx, ccache);
if (authctxt->krb5_ctx != NULL && problem!=-1)
debug("Kerberos password authentication failed: %s",
krb5_get_err_text(authctxt->krb5_ctx, problem));
else
if (authctxt->krb5_ctx != NULL && problem!=-1) {
errmsg = krb5_get_error_message(authctxt->krb5_ctx,
problem);
debug("Kerberos password authentication failed: %s",
errmsg);
krb5_free_error_message(authctxt->krb5_ctx, errmsg);
} else
debug("Kerberos password authentication failed: %d",
problem);
@ -235,7 +250,7 @@ krb5_cleanup_proc(Authctxt *authctxt)
#ifndef HEIMDAL
krb5_error_code
ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
int tmpfd, ret;
int tmpfd, ret, oerrno;
char ccname[40];
mode_t old_umask;
@ -246,16 +261,18 @@ ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
old_umask = umask(0177);
tmpfd = mkstemp(ccname + strlen("FILE:"));
oerrno = errno;
umask(old_umask);
if (tmpfd == -1) {
logit("mkstemp(): %.100s", strerror(errno));
return errno;
logit("mkstemp(): %.100s", strerror(oerrno));
return oerrno;
}
if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
logit("fchmod(): %.100s", strerror(errno));
oerrno = errno;
logit("fchmod(): %.100s", strerror(oerrno));
close(tmpfd);
return errno;
return oerrno;
}
close(tmpfd);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-options.c,v 1.54 2010/12/24 21:41:48 djm Exp $ */
/* $OpenBSD: auth-options.c,v 1.68 2015/07/03 03:43:18 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -30,22 +30,22 @@
#include <stdarg.h>
#include "openbsd-compat/sys-queue.h"
#include "key.h" /* XXX for typedef */
#include "buffer.h" /* XXX for typedef */
#include "xmalloc.h"
#include "match.h"
#include "ssherr.h"
#include "log.h"
#include "canohost.h"
#include "buffer.h"
#include "sshbuf.h"
#include "misc.h"
#include "channels.h"
#include "servconf.h"
#include "misc.h"
#include "key.h"
#include "sshkey.h"
#include "auth-options.h"
#include "hostfile.h"
#include "auth.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
/* Flags set authorized_keys flags */
int no_port_forwarding_flag = 0;
@ -81,15 +81,15 @@ auth_clear_options(void)
while (custom_environment) {
struct envstring *ce = custom_environment;
custom_environment = ce->next;
xfree(ce->s);
xfree(ce);
free(ce->s);
free(ce);
}
if (forced_command) {
xfree(forced_command);
free(forced_command);
forced_command = NULL;
}
if (authorized_principals) {
xfree(authorized_principals);
free(authorized_principals);
authorized_principals = NULL;
}
forced_tun_device = -1;
@ -158,7 +158,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
opts += strlen(cp);
if (forced_command != NULL)
xfree(forced_command);
free(forced_command);
forced_command = xmalloc(strlen(opts) + 1);
i = 0;
while (*opts) {
@ -176,7 +176,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
xfree(forced_command);
free(forced_command);
forced_command = NULL;
goto bad_option;
}
@ -189,7 +189,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
opts += strlen(cp);
if (authorized_principals != NULL)
xfree(authorized_principals);
free(authorized_principals);
authorized_principals = xmalloc(strlen(opts) + 1);
i = 0;
while (*opts) {
@ -207,7 +207,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
xfree(authorized_principals);
free(authorized_principals);
authorized_principals = NULL;
goto bad_option;
}
@ -218,8 +218,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
goto next_option;
}
cp = "environment=\"";
if (options.permit_user_env &&
strncasecmp(opts, cp, strlen(cp)) == 0) {
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
char *s;
struct envstring *new_envstring;
@ -241,17 +240,23 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
xfree(s);
free(s);
goto bad_option;
}
s[i] = '\0';
auth_debug_add("Adding to environment: %.900s", s);
debug("Adding to environment: %.900s", s);
opts++;
new_envstring = xmalloc(sizeof(struct envstring));
new_envstring->s = s;
new_envstring->next = custom_environment;
custom_environment = new_envstring;
if (options.permit_user_env) {
auth_debug_add("Adding to environment: "
"%.900s", s);
debug("Adding to environment: %.900s", s);
new_envstring = xcalloc(1,
sizeof(*new_envstring));
new_envstring->s = s;
new_envstring->next = custom_environment;
custom_environment = new_envstring;
s = NULL;
}
free(s);
goto next_option;
}
cp = "from=\"";
@ -278,7 +283,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
xfree(patterns);
free(patterns);
goto bad_option;
}
patterns[i] = '\0';
@ -286,7 +291,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
switch (match_host_and_ip(remote_host, remote_ip,
patterns)) {
case 1:
xfree(patterns);
free(patterns);
/* Host name matches. */
goto next_option;
case -1:
@ -296,7 +301,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
"invalid criteria", file, linenum);
/* FALLTHROUGH */
case 0:
xfree(patterns);
free(patterns);
logit("Authentication tried for %.100s with "
"correct key but not from a permitted "
"host (host=%.200s, ip=%.200s).",
@ -332,12 +337,13 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
file, linenum);
auth_debug_add("%.100s, line %lu: missing "
"end quote", file, linenum);
xfree(patterns);
free(patterns);
goto bad_option;
}
patterns[i] = '\0';
opts++;
p = patterns;
/* XXX - add streamlocal support */
host = hpdelim(&p);
if (host == NULL || strlen(host) >= NI_MAXHOST) {
debug("%.100s, line %lu: Bad permitopen "
@ -346,21 +352,21 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
auth_debug_add("%.100s, line %lu: "
"Bad permitopen specification", file,
linenum);
xfree(patterns);
free(patterns);
goto bad_option;
}
host = cleanhostname(host);
if (p == NULL || (port = a2port(p)) <= 0) {
if (p == NULL || (port = permitopen_port(p)) < 0) {
debug("%.100s, line %lu: Bad permitopen port "
"<%.100s>", file, linenum, p ? p : "");
auth_debug_add("%.100s, line %lu: "
"Bad permitopen port", file, linenum);
xfree(patterns);
free(patterns);
goto bad_option;
}
if (options.allow_tcp_forwarding)
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0)
channel_add_permitted_opens(host, port);
xfree(patterns);
free(patterns);
goto next_option;
}
cp = "tunnel=\"";
@ -379,13 +385,13 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
file, linenum);
auth_debug_add("%.100s, line %lu: missing end quote",
file, linenum);
xfree(tun);
free(tun);
forced_tun_device = -1;
goto bad_option;
}
tun[i] = '\0';
forced_tun_device = a2tun(tun, NULL);
xfree(tun);
free(tun);
if (forced_tun_device == SSH_TUNID_ERR) {
debug("%.100s, line %lu: invalid tun device",
file, linenum);
@ -429,7 +435,7 @@ bad_option:
#define OPTIONS_CRITICAL 1
#define OPTIONS_EXTENSIONS 2
static int
parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
parse_option_list(struct sshbuf *oblob, struct passwd *pw,
u_int which, int crit,
int *cert_no_port_forwarding_flag,
int *cert_no_agent_forwarding_flag,
@ -441,30 +447,26 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
{
char *command, *allowed;
const char *remote_ip;
u_char *name = NULL, *data_blob = NULL;
u_int nlen, dlen, clen;
Buffer c, data;
int ret = -1, found;
char *name = NULL;
struct sshbuf *c = NULL, *data = NULL;
int r, ret = -1, result, found;
buffer_init(&data);
if ((c = sshbuf_fromb(oblob)) == NULL) {
error("%s: sshbuf_fromb failed", __func__);
goto out;
}
/* Make copy to avoid altering original */
buffer_init(&c);
buffer_append(&c, optblob, optblob_len);
while (buffer_len(&c) > 0) {
if ((name = buffer_get_cstring_ret(&c, &nlen)) == NULL ||
(data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) {
error("Certificate options corrupt");
goto out;
}
buffer_append(&data, data_blob, dlen);
debug3("found certificate option \"%.100s\" len %u",
name, dlen);
if (strlen(name) != nlen) {
error("Certificate constraint name contains \\0");
while (sshbuf_len(c) > 0) {
sshbuf_free(data);
data = NULL;
if ((r = sshbuf_get_cstring(c, &name, NULL)) != 0 ||
(r = sshbuf_froms(c, &data)) != 0) {
error("Unable to parse certificate options: %s",
ssh_err(r));
goto out;
}
debug3("found certificate option \"%.100s\" len %zu",
name, sshbuf_len(data));
found = 0;
if ((which & OPTIONS_EXTENSIONS) != 0) {
if (strcmp(name, "permit-X11-forwarding") == 0) {
@ -488,50 +490,41 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
}
if (!found && (which & OPTIONS_CRITICAL) != 0) {
if (strcmp(name, "force-command") == 0) {
if ((command = buffer_get_cstring_ret(&data,
&clen)) == NULL) {
error("Certificate constraint \"%s\" "
"corrupt", name);
goto out;
}
if (strlen(command) != clen) {
error("force-command constraint "
"contains \\0");
if ((r = sshbuf_get_cstring(data, &command,
NULL)) != 0) {
error("Unable to parse \"%s\" "
"section: %s", name, ssh_err(r));
goto out;
}
if (*cert_forced_command != NULL) {
error("Certificate has multiple "
"force-command options");
xfree(command);
free(command);
goto out;
}
*cert_forced_command = command;
found = 1;
}
if (strcmp(name, "source-address") == 0) {
if ((allowed = buffer_get_cstring_ret(&data,
&clen)) == NULL) {
error("Certificate constraint "
"\"%s\" corrupt", name);
goto out;
}
if (strlen(allowed) != clen) {
error("source-address constraint "
"contains \\0");
if ((r = sshbuf_get_cstring(data, &allowed,
NULL)) != 0) {
error("Unable to parse \"%s\" "
"section: %s", name, ssh_err(r));
goto out;
}
if ((*cert_source_address_done)++) {
error("Certificate has multiple "
"source-address options");
xfree(allowed);
free(allowed);
goto out;
}
remote_ip = get_remote_ipaddr();
switch (addr_match_cidr_list(remote_ip,
allowed)) {
result = addr_match_cidr_list(remote_ip,
allowed);
free(allowed);
switch (result) {
case 1:
/* accepted */
xfree(allowed);
break;
case 0:
/* no match */
@ -544,12 +537,11 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
"is not permitted to use this "
"certificate for login.",
remote_ip);
xfree(allowed);
goto out;
case -1:
default:
error("Certificate source-address "
"contents invalid");
xfree(allowed);
goto out;
}
found = 1;
@ -565,15 +557,13 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
logit("Certificate extension \"%s\" "
"is not supported", name);
}
} else if (buffer_len(&data) != 0) {
} else if (sshbuf_len(data) != 0) {
error("Certificate option \"%s\" corrupt "
"(extra data)", name);
goto out;
}
buffer_clear(&data);
xfree(name);
xfree(data_blob);
name = data_blob = NULL;
free(name);
name = NULL;
}
/* successfully parsed all options */
ret = 0;
@ -582,15 +572,13 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
if (ret != 0 &&
cert_forced_command != NULL &&
*cert_forced_command != NULL) {
xfree(*cert_forced_command);
free(*cert_forced_command);
*cert_forced_command = NULL;
}
if (name != NULL)
xfree(name);
if (data_blob != NULL)
xfree(data_blob);
buffer_free(&data);
buffer_free(&c);
free(name);
sshbuf_free(data);
sshbuf_free(c);
return ret;
}
@ -599,7 +587,7 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
* options so this must be called after auth_parse_options().
*/
int
auth_cert_options(Key *k, struct passwd *pw)
auth_cert_options(struct sshkey *k, struct passwd *pw)
{
int cert_no_port_forwarding_flag = 1;
int cert_no_agent_forwarding_flag = 1;
@ -609,38 +597,21 @@ auth_cert_options(Key *k, struct passwd *pw)
char *cert_forced_command = NULL;
int cert_source_address_done = 0;
if (key_cert_is_legacy(k)) {
/* All options are in the one field for v00 certs */
if (parse_option_list(buffer_ptr(&k->cert->critical),
buffer_len(&k->cert->critical), pw,
OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1,
&cert_no_port_forwarding_flag,
&cert_no_agent_forwarding_flag,
&cert_no_x11_forwarding_flag,
&cert_no_pty_flag,
&cert_no_user_rc,
&cert_forced_command,
&cert_source_address_done) == -1)
return -1;
} else {
/* Separate options and extensions for v01 certs */
if (parse_option_list(buffer_ptr(&k->cert->critical),
buffer_len(&k->cert->critical), pw,
OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL,
&cert_forced_command,
&cert_source_address_done) == -1)
return -1;
if (parse_option_list(buffer_ptr(&k->cert->extensions),
buffer_len(&k->cert->extensions), pw,
OPTIONS_EXTENSIONS, 1,
&cert_no_port_forwarding_flag,
&cert_no_agent_forwarding_flag,
&cert_no_x11_forwarding_flag,
&cert_no_pty_flag,
&cert_no_user_rc,
NULL, NULL) == -1)
return -1;
}
/* Separate options and extensions for v01 certs */
if (parse_option_list(k->cert->critical, pw,
OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL,
&cert_forced_command,
&cert_source_address_done) == -1)
return -1;
if (parse_option_list(k->cert->extensions, pw,
OPTIONS_EXTENSIONS, 0,
&cert_no_port_forwarding_flag,
&cert_no_agent_forwarding_flag,
&cert_no_x11_forwarding_flag,
&cert_no_pty_flag,
&cert_no_user_rc,
NULL, NULL) == -1)
return -1;
no_port_forwarding_flag |= cert_no_port_forwarding_flag;
no_agent_forwarding_flag |= cert_no_agent_forwarding_flag;
@ -650,8 +621,9 @@ auth_cert_options(Key *k, struct passwd *pw)
/* CA-specified forced command supersedes key option */
if (cert_forced_command != NULL) {
if (forced_command != NULL)
xfree(forced_command);
free(forced_command);
forced_command = cert_forced_command;
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-options.h,v 1.20 2010/05/07 11:30:29 djm Exp $ */
/* $OpenBSD: auth-options.h,v 1.21 2015/01/14 10:30:34 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -35,6 +35,6 @@ extern char *authorized_principals;
int auth_parse_options(struct passwd *, char *, char *, u_long);
void auth_clear_options(void);
int auth_cert_options(Key *, struct passwd *);
int auth_cert_options(struct sshkey *, struct passwd *);
#endif

View File

@ -47,7 +47,6 @@
/* Based on $FreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des Exp $ */
#include "includes.h"
/*
* We support only client side kerberos on Windows.
*/
@ -421,10 +420,9 @@ sshpam_thread_conv(int n, sshpam_const struct pam_message **msg,
fail:
for(i = 0; i < n; i++) {
if (reply[i].resp != NULL)
xfree(reply[i].resp);
free(reply[i].resp);
}
xfree(reply);
free(reply);
buffer_free(&buffer);
return (PAM_CONV_ERR);
}
@ -448,8 +446,10 @@ sshpam_thread(void *ctxtp)
const char **ptr_pam_user = &pam_user;
char *tz = getenv("TZ");
pam_get_item(sshpam_handle, PAM_USER,
sshpam_err = pam_get_item(sshpam_handle, PAM_USER,
(sshpam_const void **)ptr_pam_user);
if (sshpam_err != PAM_SUCCESS)
goto auth_fail;
environ[0] = NULL;
if (tz != NULL)
@ -595,10 +595,9 @@ sshpam_store_conv(int n, sshpam_const struct pam_message **msg,
fail:
for(i = 0; i < n; i++) {
if (reply[i].resp != NULL)
xfree(reply[i].resp);
free(reply[i].resp);
}
xfree(reply);
free(reply);
return (PAM_CONV_ERR);
}
@ -702,7 +701,7 @@ sshpam_init_ctx(Authctxt *authctxt)
/* Start the authentication thread */
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, socks) == -1) {
error("PAM: failed create sockets: %s", strerror(errno));
xfree(ctxt);
free(ctxt);
return (NULL);
}
ctxt->pam_psock = socks[0];
@ -712,7 +711,7 @@ sshpam_init_ctx(Authctxt *authctxt)
strerror(errno));
close(socks[0]);
close(socks[1]);
xfree(ctxt);
free(ctxt);
return (NULL);
}
cleanup_ctxt = ctxt;
@ -747,22 +746,22 @@ sshpam_query(void *ctx, char **name, char **info,
case PAM_PROMPT_ECHO_OFF:
*num = 1;
len = plen + mlen + 1;
**prompts = xrealloc(**prompts, 1, len);
**prompts = xreallocarray(**prompts, 1, len);
strlcpy(**prompts + plen, msg, len - plen);
plen += mlen;
**echo_on = (type == PAM_PROMPT_ECHO_ON);
xfree(msg);
free(msg);
return (0);
case PAM_ERROR_MSG:
case PAM_TEXT_INFO:
/* accumulate messages */
len = plen + mlen + 2;
**prompts = xrealloc(**prompts, 1, len);
**prompts = xreallocarray(**prompts, 1, len);
strlcpy(**prompts + plen, msg, len - plen);
plen += mlen;
strlcat(**prompts + plen, "\n", len - plen);
plen++;
xfree(msg);
free(msg);
break;
case PAM_ACCT_EXPIRED:
sshpam_account_status = 0;
@ -775,7 +774,7 @@ sshpam_query(void *ctx, char **name, char **info,
*num = 0;
**echo_on = 0;
ctxt->pam_done = -1;
xfree(msg);
free(msg);
return 0;
}
/* FALLTHROUGH */
@ -785,7 +784,7 @@ sshpam_query(void *ctx, char **name, char **info,
debug("PAM: %s", **prompts);
buffer_append(&loginmsg, **prompts,
strlen(**prompts));
xfree(**prompts);
free(**prompts);
**prompts = NULL;
}
if (type == PAM_SUCCESS) {
@ -799,7 +798,7 @@ sshpam_query(void *ctx, char **name, char **info,
*num = 0;
**echo_on = 0;
ctxt->pam_done = 1;
xfree(msg);
free(msg);
return (0);
}
error("PAM: %s for %s%.100s from %.100s", msg,
@ -810,7 +809,7 @@ sshpam_query(void *ctx, char **name, char **info,
default:
*num = 0;
**echo_on = 0;
xfree(msg);
free(msg);
ctxt->pam_done = -1;
return (-1);
}
@ -861,7 +860,7 @@ sshpam_free_ctx(void *ctxtp)
debug3("PAM: %s entering", __func__);
sshpam_thread_cleanup();
xfree(ctxt);
free(ctxt);
/*
* We don't call sshpam_cleanup() here because we may need the PAM
* handle at a later stage, e.g. when setting up a session. It's
@ -1015,10 +1014,9 @@ sshpam_tty_conv(int n, sshpam_const struct pam_message **msg,
fail:
for(i = 0; i < n; i++) {
if (reply[i].resp != NULL)
xfree(reply[i].resp);
free(reply[i].resp);
}
xfree(reply);
free(reply);
return (PAM_CONV_ERR);
}
@ -1090,7 +1088,7 @@ do_pam_putenv(char *name, char *value)
snprintf(compound, len, "%s=%s", name, value);
ret = pam_putenv(sshpam_handle, compound);
xfree(compound);
free(compound);
#endif
return (ret);
@ -1117,8 +1115,8 @@ free_pam_environment(char **env)
return;
for (envp = env; *envp; envp++)
xfree(*envp);
xfree(env);
free(*envp);
free(env);
}
/*
@ -1174,10 +1172,9 @@ sshpam_passwd_conv(int n, sshpam_const struct pam_message **msg,
fail:
for(i = 0; i < n; i++) {
if (reply[i].resp != NULL)
xfree(reply[i].resp);
free(reply[i].resp);
}
xfree(reply);
free(reply);
return (PAM_CONV_ERR);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-passwd.c,v 1.43 2007/09/21 08:15:29 djm Exp $ */
/* $OpenBSD: auth-passwd.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -37,6 +37,7 @@
*/
#include "includes.h"
#include "xmalloc.h"
/*
@ -58,6 +59,7 @@
#include "packet.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "key.h"
#include "hostfile.h"
@ -197,6 +199,7 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
return (auth_close(as));
}
}
#elif defined(WIN32_FIXME)
int sys_auth_passwd(Authctxt *authctxt, const char *password)
{
@ -247,7 +250,7 @@ int sys_auth_passwd(Authctxt *authctxt, const char *password)
if (0 == MultiByteToWideChar(CP_UTF8, 0, authctxt -> user,
-1, user_UTF16, buffer_size))
{
xfree(user_UTF16);
free(user_UTF16);
return 0;
}
@ -270,7 +273,7 @@ int sys_auth_passwd(Authctxt *authctxt, const char *password)
if (0 == MultiByteToWideChar(CP_UTF8, 0, password, -1,
password_UTF16 , buffer_size))
{
xfree(password_UTF16 );
free(password_UTF16 );
return 0;
}
@ -308,8 +311,8 @@ int sys_auth_passwd(Authctxt *authctxt, const char *password)
}
}
xfree(user_UTF16);
xfree(password_UTF16);
free(user_UTF16);
free(password_UTF16);
/*
* If login still fails, go out.
@ -369,6 +372,7 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
* Authentication is accepted if the encrypted passwords
* are identical.
*/
return (strcmp(encrypted_password, pw_password) == 0);
return encrypted_password != NULL &&
strcmp(encrypted_password, pw_password) == 0;
}
#endif

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-rh-rsa.c,v 1.43 2010/03/04 10:36:03 djm Exp $ */
/* $OpenBSD: auth-rh-rsa.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -15,15 +15,13 @@
#include "includes.h"
/*
* We support only client side kerberos on Windows.
*/
#ifdef WIN32_FIXME
#undef GSSAPI
#undef KRB5
#endif
#ifdef WITH_SSH1
#include <sys/types.h>
#include <pwd.h>
@ -33,6 +31,7 @@
#include "uidswap.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "key.h"
#include "hostfile.h"
@ -110,3 +109,5 @@ auth_rhosts_rsa(Authctxt *authctxt, char *cuser, Key *client_host_key)
packet_send_debug("Rhosts with RSA host authentication accepted.");
return 1;
}
#endif /* WITH_SSH1 */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-rhosts.c,v 1.44 2010/03/07 11:57:13 dtucker Exp $ */
/* $OpenBSD: auth-rhosts.c,v 1.46 2014/12/23 22:42:48 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -43,12 +43,12 @@
#include "uidswap.h"
#include "pathnames.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "canohost.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "misc.h"
/* import */
extern ServerOptions options;
@ -67,7 +67,8 @@ check_rhosts_file(const char *filename, const char *hostname,
{
#ifndef WIN32_FIXME
FILE *f;
char buf[1024]; /* Must not be larger than host, user, dummy below. */
#define RBUFLN 1024
char buf[RBUFLN];/* Must not be larger than host, user, dummy below. */
int fd;
struct stat st;
@ -90,8 +91,9 @@ check_rhosts_file(const char *filename, const char *hostname,
return 0;
}
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;
/* All three must have length >= buf to avoid overflows. */
char hostbuf[RBUFLN], userbuf[RBUFLN], dummy[RBUFLN];
char *host, *user, *cp;
int negated;
for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
@ -150,8 +152,8 @@ check_rhosts_file(const char *filename, const char *hostname,
/* Check for empty host/user names (particularly '+'). */
if (!host[0] || !user[0]) {
/* We come here if either was '+' or '-'. */
auth_debug_add("Ignoring wild host/user names in %.100s.",
filename);
auth_debug_add("Ignoring wild host/user names "
"in %.100s.", filename);
continue;
}
/* Verify that host name matches. */
@ -159,7 +161,8 @@ check_rhosts_file(const char *filename, const char *hostname,
if (!innetgr(host + 1, hostname, NULL, NULL) &&
!innetgr(host + 1, ipaddr, NULL, NULL))
continue;
} else if (strcasecmp(host, hostname) && strcmp(host, ipaddr) != 0)
} else if (strcasecmp(host, hostname) &&
strcmp(host, ipaddr) != 0)
continue; /* Different hostname. */
/* Verify that user name matches. */
@ -185,6 +188,7 @@ check_rhosts_file(const char *filename, const char *hostname,
/* Authentication using this file denied. */
fclose(f);
return 0;
#else
return 1;
#endif
@ -221,7 +225,8 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam
/* Switch to the user's uid. */
temporarily_use_uid(pw);
/*
* Quick check: if the user has no .shosts or .rhosts files, return
* Quick check: if the user has no .shosts or .rhosts files and
* no system hosts.equiv/shosts.equiv files exist then return
* failure immediately without doing costly lookups from name
* servers.
*/
@ -236,27 +241,38 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam
/* Switch back to privileged uid. */
restore_uid();
/* Deny if The user has no .shosts or .rhosts file and there are no system-wide files. */
/*
* Deny if The user has no .shosts or .rhosts file and there
* are no system-wide files.
*/
if (!rhosts_files[rhosts_file_index] &&
stat(_PATH_RHOSTS_EQUIV, &st) < 0 &&
stat(_PATH_SSH_HOSTS_EQUIV, &st) < 0)
stat(_PATH_SSH_HOSTS_EQUIV, &st) < 0) {
debug3("%s: no hosts access files exist", __func__);
return 0;
}
/* If not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */
if (pw->pw_uid != 0) {
/*
* If not logging in as superuser, try /etc/hosts.equiv and
* shosts.equiv.
*/
if (pw->pw_uid == 0)
debug3("%s: root user, ignoring system hosts files", __func__);
else {
if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr,
client_user, pw->pw_name)) {
auth_debug_add("Accepted for %.100s [%.100s] by /etc/hosts.equiv.",
hostname, ipaddr);
auth_debug_add("Accepted for %.100s [%.100s] by "
"/etc/hosts.equiv.", hostname, ipaddr);
return 1;
}
if (check_rhosts_file(_PATH_SSH_HOSTS_EQUIV, hostname, ipaddr,
client_user, pw->pw_name)) {
auth_debug_add("Accepted for %.100s [%.100s] by %.100s.",
hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV);
auth_debug_add("Accepted for %.100s [%.100s] by "
"%.100s.", hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV);
return 1;
}
}
/*
* Check that the home directory is owned by root or the user, and is
* not group or world writable.
@ -303,20 +319,25 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam
auth_debug_add("Bad file modes for %.200s", buf);
continue;
}
/* Check if we have been configured to ignore .rhosts and .shosts files. */
/*
* Check if we have been configured to ignore .rhosts
* and .shosts files.
*/
if (options.ignore_rhosts) {
auth_debug_add("Server has been configured to ignore %.100s.",
rhosts_files[rhosts_file_index]);
auth_debug_add("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)) {
if (check_rhosts_file(buf, hostname, ipaddr,
client_user, pw->pw_name)) {
auth_debug_add("Accepted by %.100s.",
rhosts_files[rhosts_file_index]);
/* Restore the privileged uid. */
restore_uid();
auth_debug_add("Accepted host %s ip %s client_user %s server_user %s",
hostname, ipaddr, client_user, pw->pw_name);
auth_debug_add("Accepted host %s ip %s client_user "
"%s server_user %s", hostname, ipaddr,
client_user, pw->pw_name);
return 1;
}
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-rsa.c,v 1.80 2011/05/23 03:30:07 djm Exp $ */
/* $OpenBSD: auth-rsa.c,v 1.90 2015/01/28 22:36:00 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -25,11 +25,12 @@
#undef KRB5
#endif
#ifdef WITH_SSH1
#include <sys/types.h>
#include <sys/stat.h>
#include <openssl/rsa.h>
#include <openssl/md5.h>
#include <pwd.h>
#include <stdio.h>
@ -45,6 +46,7 @@
#include "buffer.h"
#include "pathnames.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "key.h"
#include "auth-options.h"
@ -55,7 +57,8 @@
#endif
#include "monitor_wrap.h"
#include "ssh.h"
#include "misc.h"
#include "digest.h"
/* import */
extern ServerOptions options;
@ -100,12 +103,13 @@ int
auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
{
u_char buf[32], mdbuf[16];
MD5_CTX md;
struct ssh_digest_ctx *md;
int len;
/* don't allow short keys */
if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits",
error("%s: RSA modulus too small: %d < minimum %d bits",
__func__,
BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE);
return (0);
}
@ -113,13 +117,15 @@ auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
if (len <= 0 || len > 32)
fatal("auth_rsa_verify_response: bad challenge length %d", len);
fatal("%s: bad challenge length %d", __func__, 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);
if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL ||
ssh_digest_update(md, buf, 32) < 0 ||
ssh_digest_update(md, session_id, 16) < 0 ||
ssh_digest_final(md, mdbuf, sizeof(mdbuf)) < 0)
fatal("%s: md5 failed", __func__);
ssh_digest_free(md);
/* Verify that the response is the original challenge. */
if (timingsafe_bcmp(response, mdbuf, 16) != 0) {
@ -149,7 +155,8 @@ auth_rsa_challenge_dialog(Key *key)
challenge = PRIVSEP(auth_rsa_generate_challenge(key));
/* Encrypt the challenge with the public key. */
rsa_public_encrypt(encrypted_challenge, challenge, key->rsa);
if (rsa_public_encrypt(encrypted_challenge, challenge, key->rsa) != 0)
fatal("%s: rsa_public_encrypt failed", __func__);
/* Send the encrypted challenge to the client. */
packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
@ -173,9 +180,8 @@ static int
rsa_key_allowed_in_file(struct passwd *pw, char *file,
const BIGNUM *client_n, Key **rkey)
{
char line[SSH_MAX_PUBKEY_BYTES];
int allowed = 0;
u_int bits;
char *fp, line[SSH_MAX_PUBKEY_BYTES];
int allowed = 0, bits;
FILE *f;
u_long linenum = 0;
Key *key;
@ -236,11 +242,18 @@ rsa_key_allowed_in_file(struct passwd *pw, char *file,
/* check the real bits */
keybits = BN_num_bits(key->rsa->n);
if (keybits < 0 || bits != (u_int)keybits)
if (keybits < 0 || bits != keybits)
logit("Warning: %s, line %lu: keysize mismatch: "
"actual %d vs. announced %d.",
file, linenum, BN_num_bits(key->rsa->n), bits);
if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL)
continue;
debug("matching key found: file %s, line %lu %s %s",
file, linenum, key_type(key), fp);
free(fp);
/* Never accept a revoked key */
if (auth_key_is_revoked(key))
break;
@ -285,10 +298,12 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
temporarily_use_uid(pw);
for (i = 0; !allowed && i < options.num_authkeys_files; i++) {
if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
continue;
file = expand_authorized_keys(
options.authorized_keys_files[i], pw);
allowed = rsa_key_allowed_in_file(pw, file, client_n, rkey);
xfree(file);
free(file);
}
restore_uid();
@ -305,7 +320,6 @@ int
auth_rsa(Authctxt *authctxt, BIGNUM *client_n)
{
Key *key;
char *fp;
struct passwd *pw = authctxt->pw;
/* no user given */
@ -335,12 +349,10 @@ auth_rsa(Authctxt *authctxt, BIGNUM *client_n)
* options; this will be reset if the options cause the
* authentication to be rejected.
*/
fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
verbose("Found matching %s key: %s",
key_type(key), fp);
xfree(fp);
key_free(key);
pubkey_auth_info(authctxt, key, NULL);
packet_send_debug("RSA authentication accepted.");
return (1);
}
#endif /* WITH_SSH1 */

201
auth.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth.c,v 1.94 2011/05/23 03:33:38 djm Exp $ */
/* $OpenBSD: auth.c,v 1.113 2015/08/21 03:42:19 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -36,7 +36,6 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <netinet/in.h>
@ -59,12 +58,14 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include "xmalloc.h"
#include "match.h"
#include "groupaccess.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "key.h"
#include "hostfile.h"
@ -72,7 +73,6 @@
#include "auth-options.h"
#include "canohost.h"
#include "uidswap.h"
#include "misc.h"
#include "packet.h"
#include "loginrec.h"
#ifdef GSSAPI
@ -80,6 +80,9 @@
#endif
#include "authfile.h"
#include "monitor_wrap.h"
#include "authfile.h"
#include "ssherr.h"
#include "compat.h"
/* import */
extern ServerOptions options;
@ -173,7 +176,7 @@ allowed_user(struct passwd * pw)
if (stat(shell, &st) != 0) {
logit("User %.100s not allowed because shell %.100s "
"does not exist", pw->pw_name, shell);
xfree(shell);
free(shell);
return 0;
}
#ifndef WIN32_FIXME
@ -181,11 +184,11 @@ allowed_user(struct passwd * pw)
(st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
logit("User %.100s not allowed because shell %.100s "
"is not executable", pw->pw_name, shell);
xfree(shell);
free(shell);
return 0;
}
#endif
xfree(shell);
free(shell);
}
if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
@ -262,7 +265,25 @@ allowed_user(struct passwd * pw)
}
void
auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
auth_info(Authctxt *authctxt, const char *fmt, ...)
{
va_list ap;
int i;
free(authctxt->info);
authctxt->info = NULL;
va_start(ap, fmt);
i = vasprintf(&authctxt->info, fmt, ap);
va_end(ap);
if (i < 0 || authctxt->info == NULL)
fatal("vasprintf failed");
}
void
auth_log(Authctxt *authctxt, int authenticated, int partial,
const char *method, const char *submethod)
{
void (*authlog) (const char *fmt,...) = verbose;
char *authmsg;
@ -279,17 +300,24 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
if (authctxt->postponed)
authmsg = "Postponed";
else if (partial)
authmsg = "Partial";
else
authmsg = authenticated ? "Accepted" : "Failed";
authlog("%s %s for %s%.100s from %.200s port %d%s",
authlog("%s %s%s%s for %s%.100s from %.200s port %d %s%s%s",
authmsg,
method,
submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
authctxt->valid ? "" : "invalid user ",
authctxt->user,
get_remote_ipaddr(),
get_remote_port(),
info);
compat20 ? "ssh2" : "ssh1",
authctxt->info != NULL ? ": " : "",
authctxt->info != NULL ? authctxt->info : "");
free(authctxt->info);
authctxt->info = NULL;
#ifdef CUSTOM_FAILED_LOGIN
if (authenticated == 0 && !authctxt->postponed &&
@ -310,17 +338,34 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
#endif
}
void
auth_maxtries_exceeded(Authctxt *authctxt)
{
error("maximum authentication attempts exceeded for "
"%s%.100s from %.200s port %d %s",
authctxt->valid ? "" : "invalid user ",
authctxt->user,
get_remote_ipaddr(),
get_remote_port(),
compat20 ? "ssh2" : "ssh1");
packet_disconnect("Too many authentication failures");
/* NOTREACHED */
}
/*
* Check whether root logins are disallowed.
*/
int
auth_root_allowed(char *method)
auth_root_allowed(const char *method)
{
switch (options.permit_root_login) {
case PERMIT_YES:
return 1;
case PERMIT_NO_PASSWD:
if (strcmp(method, "password") != 0)
if (strcmp(method, "publickey") == 0 ||
strcmp(method, "hostbased") == 0 ||
strcmp(method, "gssapi-with-mic") == 0)
return 1;
break;
case PERMIT_FORCED_ONLY:
@ -342,7 +387,7 @@ auth_root_allowed(char *method)
*
* This returns a buffer allocated by xmalloc.
*/
/*
* Win32 implementation uses UTF16 names.
*/
@ -408,7 +453,7 @@ wchar_t *expand_authorized_keys(const wchar_t *filename, struct passwd *pw)
fatal("expand_authorized_keys: path too long");
}
xfree(file_w);
free(file_w);
return (_wcsdup(ret));
}
@ -418,7 +463,7 @@ wchar_t *expand_authorized_keys(const wchar_t *filename, struct passwd *pw)
char *
expand_authorized_keys(const char *filename, struct passwd *pw)
{
char *file, ret[MAXPATHLEN];
char *file, ret[PATH_MAX];
int i;
file = percent_expand(filename, "h", pw->pw_dir,
@ -428,14 +473,13 @@ expand_authorized_keys(const char *filename, struct passwd *pw)
* Ensure that filename starts anchored. If not, be backward
* compatible and prepend the '%h/'
*/
if (*file == '/')
return (file);
i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file);
if (i < 0 || (size_t)i >= sizeof(ret))
fatal("expand_authorized_keys: path too long");
xfree(file);
free(file);
return (xstrdup(ret));
}
#endif /* WIN32_FIXME */
@ -477,7 +521,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
load_hostkeys(hostkeys, host, user_hostfile);
restore_uid();
}
xfree(user_hostfile);
free(user_hostfile);
}
host_status = check_key_in_hostkeys(hostkeys, key, &found);
if (host_status == HOST_REVOKED)
@ -494,42 +538,43 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
return host_status;
}
/*
* Check a given file for security. This is defined as all components
* Check a given path for security. This is defined as all components
* of the path to the file must be owned by either the owner of
* of the file or root and no directories must be group or world writable.
*
* XXX Should any specific check be done for sym links ?
*
* Takes an open file descriptor, the file name, a uid and and
* Takes a file name, its stat information (preferably from fstat() to
* avoid races), the uid of the expected owner, their home directory and an
* error buffer plus max size as arguments.
*
* Returns 0 on success and -1 on failure
*/
static int
secure_filename(FILE *f, const char *file, struct passwd *pw,
char *err, size_t errlen)
int
auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
uid_t uid, char *err, size_t errlen)
{
#ifndef WIN32_FIXME
uid_t uid = pw->pw_uid;
char buf[MAXPATHLEN], homedir[MAXPATHLEN];
char buf[PATH_MAX], homedir[PATH_MAX];
char *cp;
int comparehome = 0;
struct stat st;
if (realpath(file, buf) == NULL) {
snprintf(err, errlen, "realpath %s failed: %s", file,
if (realpath(name, buf) == NULL) {
snprintf(err, errlen, "realpath %s failed: %s", name,
strerror(errno));
return -1;
}
if (realpath(pw->pw_dir, homedir) != NULL)
if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
comparehome = 1;
/* check the open file to avoid races */
if (fstat(fileno(f), &st) < 0 ||
(st.st_uid != 0 && st.st_uid != uid) ||
(st.st_mode & 022) != 0) {
if (!S_ISREG(stp->st_mode)) {
snprintf(err, errlen, "%s is not a regular file", buf);
return -1;
}
if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) ||
(stp->st_mode & 022) != 0) {
snprintf(err, errlen, "bad ownership or modes for file %s",
buf);
return -1;
@ -544,7 +589,7 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
strlcpy(buf, cp, sizeof(buf));
if (stat(buf, &st) < 0 ||
(st.st_uid != 0 && st.st_uid != uid) ||
(!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) ||
(st.st_mode & 022) != 0) {
snprintf(err, errlen,
"bad ownership or modes for directory %s", buf);
@ -565,7 +610,32 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
return 0;
#else
return 0;
#endif
#endif
}
/*
* Version of secure_path() that accepts an open file descriptor to
* avoid races.
*
* Returns 0 on success and -1 on failure
*/
static int
secure_filename(FILE *f, const char *file, struct passwd *pw,
char *err, size_t errlen)
{
#ifndef WIN32_FIXME
struct stat st;
/* check the open file to avoid races */
if (fstat(fileno(f), &st) < 0) {
snprintf(err, errlen, "cannot stat file %s: %s",
file, strerror(errno));
return -1;
}
return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
#else
return 0;
#endif
}
static FILE *
@ -576,7 +646,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes,
struct stat st;
int fd;
FILE *f;
#ifdef WIN32_FIXME
if ((fd = WSHELPwopen(file, O_RDONLY|O_NONBLOCK)) == -1) {
#else
@ -598,11 +668,9 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes,
close(fd);
return NULL;
}
#ifndef WIN32_FIXME
unset_nonblock(fd);
#endif
if ((f = fdopen(fd, "r")) == NULL) {
close(fd);
return NULL;
@ -642,9 +710,10 @@ getpwnamallow(const char *user)
#endif
#endif
struct passwd *pw;
struct connection_info *ci = get_connection_info(1, options.use_dns);
parse_server_match_config(&options, user,
get_canonical_hostname(options.use_dns), get_remote_ipaddr());
ci->user = user;
parse_server_match_config(&options, ci);
#if defined(_AIX) && defined(HAVE_SETAUTHDB)
aix_setauthdb(user);
@ -706,29 +775,39 @@ getpwnamallow(const char *user)
int
auth_key_is_revoked(Key *key)
{
char *key_fp;
char *fp = NULL;
int r;
if (options.revoked_keys_file == NULL)
return 0;
switch (key_in_file(key, options.revoked_keys_file, 0)) {
case 0:
/* key not revoked */
return 0;
case -1:
/* Error opening revoked_keys_file: refuse all keys */
error("Revoked keys file is unreadable: refusing public key "
"authentication");
return 1;
case 1:
/* Key revoked */
key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
error("WARNING: authentication attempt with a revoked "
"%s key %s ", key_type(key), key_fp);
xfree(key_fp);
return 1;
if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
error("%s: fingerprint key: %s", __func__, ssh_err(r));
goto out;
}
fatal("key_in_file returned junk");
r = sshkey_check_revoked(key, options.revoked_keys_file);
switch (r) {
case 0:
break; /* not revoked */
case SSH_ERR_KEY_REVOKED:
error("Authentication key %s %s revoked by file %s",
sshkey_type(key), fp, options.revoked_keys_file);
goto out;
default:
error("Error checking authentication key %s %s in "
"revoked keys file %s: %s", sshkey_type(key), fp,
options.revoked_keys_file, ssh_err(r));
goto out;
}
/* Success */
r = 0;
out:
free(fp);
return r == 0 ? 0 : 1;
}
void
@ -756,7 +835,7 @@ auth_debug_send(void)
while (buffer_len(&auth_debug)) {
msg = buffer_get_string(&auth_debug, NULL);
packet_send_debug("%s", msg);
xfree(msg);
free(msg);
}
}
@ -780,10 +859,12 @@ fakepw(void)
fake.pw_name = "NOUSER";
fake.pw_passwd =
"$2a$06$r3.juUaHZDlIbQaO2dS9FuYxL1W9M81R1Tc92PoSNmzvpEqLkLGrK";
#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
fake.pw_gecos = "NOUSER";
#endif
fake.pw_uid = privsep_pw == NULL ? (uid_t)-1 : privsep_pw->pw_uid;
fake.pw_gid = privsep_pw == NULL ? (gid_t)-1 : privsep_pw->pw_gid;
#ifdef HAVE_PW_CLASS_IN_PASSWD
#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
fake.pw_class = "";
#endif
fake.pw_dir = "/nonexist";

54
auth.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth.h,v 1.69 2011/05/23 03:30:07 djm Exp $ */
/* $OpenBSD: auth.h,v 1.84 2015/05/08 06:41:56 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -48,6 +48,9 @@
#endif
struct ssh;
struct sshkey;
typedef struct Authctxt Authctxt;
typedef struct Authmethod Authmethod;
typedef struct KbdintDevice KbdintDevice;
@ -59,17 +62,19 @@ struct Authctxt {
int valid; /* user exists and is allowed to login */
int attempt;
int failures;
int server_caused_failure;
int server_caused_failure;
int force_pwchange;
char *user; /* username sent by the client */
char *service;
struct passwd *pw; /* set if 'valid' */
char *style;
void *kbdintctxt;
void *jpake_ctx;
char *info; /* Extra info for next auth_log */
#ifdef BSD_AUTH
auth_session_t *as;
#endif
char **auth_methods; /* modified from server config */
u_int num_auth_methods;
#ifdef KRB5
krb5_context krb5_ctx;
krb5_ccache krb5_fwd_ccache;
@ -80,6 +85,8 @@ struct Authctxt {
Buffer *loginmsg;
void *methoddata;
struct sshkey **prev_userkeys;
u_int nprev_userkeys;
#ifdef WIN32_FIXME
HANDLE hTokenLsa_;
@ -131,7 +138,15 @@ int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
int user_key_allowed(struct passwd *, Key *);
int user_key_allowed(struct passwd *, Key *, int);
void pubkey_auth_info(Authctxt *, const Key *, const char *, ...)
__attribute__((__format__ (printf, 3, 4)));
void auth2_record_userkey(Authctxt *, struct sshkey *);
int auth2_userkey_already_used(Authctxt *, struct sshkey *);
struct stat;
int auth_secure_path(const char *, struct stat *, const char *, uid_t,
char *, size_t);
#ifdef KRB5
int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *);
@ -155,12 +170,21 @@ void disable_forwarding(void);
void do_authentication(Authctxt *);
void do_authentication2(Authctxt *);
void auth_log(Authctxt *, int, char *, char *);
void userauth_finish(Authctxt *, int, char *);
void auth_info(Authctxt *authctxt, const char *, ...)
__attribute__((__format__ (printf, 2, 3)))
__attribute__((__nonnull__ (2)));
void auth_log(Authctxt *, int, int, const char *, const char *);
void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn));
void userauth_finish(Authctxt *, int, const char *, const char *);
int auth_root_allowed(const char *);
void userauth_send_banner(const char *);
int auth_root_allowed(char *);
char *auth2_read_banner(void);
int auth2_methods_valid(const char *, int);
int auth2_update_methods_lists(Authctxt *, const char *, const char *);
int auth2_setup_methods_lists(Authctxt *);
int auth2_method_allowed(Authctxt *, const char *, const char *);
void privsep_challenge_enable(void);
@ -171,20 +195,19 @@ int bsdauth_respond(void *, u_int, char **);
int skey_query(void *, char **, char **, u_int *, char ***, u_int **);
int skey_respond(void *, u_int, char **);
void auth2_jpake_get_pwdata(Authctxt *, BIGNUM **, char **, char **);
void auth2_jpake_stop(Authctxt *);
int allowed_user(struct passwd *);
struct passwd * getpwnamallow(const char *user);
char *get_challenge(Authctxt *);
int verify_response(Authctxt *, const char *);
void abandon_challenge_response(Authctxt *);
#ifndef WIN32_FIXME
char *expand_authorized_keys(const char *, struct passwd *pw);
#else
wchar_t *expand_authorized_keys(const wchar_t *filename, struct passwd *pw);
#endif
char *authorized_principals_file(struct passwd *);
FILE *auth_openkeyfile(const char *, struct passwd *, int);
@ -197,10 +220,13 @@ check_key_in_hostfiles(struct passwd *, Key *, const char *,
/* hostkey handling */
Key *get_hostkey_by_index(int);
Key *get_hostkey_public_by_type(int);
Key *get_hostkey_private_by_type(int);
int get_hostkey_index(Key *);
Key *get_hostkey_public_by_index(int, struct ssh *);
Key *get_hostkey_public_by_type(int, int, struct ssh *);
Key *get_hostkey_private_by_type(int, int, struct ssh *);
int get_hostkey_index(Key *, int, struct ssh *);
int ssh1_session_key(BIGNUM *);
int sshd_hostkey_sign(Key *, Key *, u_char **, size_t *,
const u_char *, size_t, u_int);
/* debug messages during authentication */
void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
@ -211,8 +237,6 @@ struct passwd *fakepw(void);
int sys_auth_passwd(Authctxt *, const char *);
#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
#define SKEY_PROMPT "\nS/Key Password: "
#if defined(KRB5) && !defined(HEIMDAL)

64
auth1.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth1.c,v 1.75 2010/08/31 09:58:37 djm Exp $ */
/* $OpenBSD: auth1.c,v 1.82 2014/07/15 15:54:14 millert Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -21,6 +21,9 @@
#undef KRB5
#endif
#ifdef WITH_SSH1
#include <sys/types.h>
#include <stdarg.h>
@ -36,6 +39,7 @@
#include "packet.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "key.h"
@ -54,11 +58,11 @@
extern ServerOptions options;
extern Buffer loginmsg;
static int auth1_process_password(Authctxt *, char *, size_t);
static int auth1_process_rsa(Authctxt *, char *, size_t);
static int auth1_process_rhosts_rsa(Authctxt *, char *, size_t);
static int auth1_process_tis_challenge(Authctxt *, char *, size_t);
static int auth1_process_tis_response(Authctxt *, char *, size_t);
static int auth1_process_password(Authctxt *);
static int auth1_process_rsa(Authctxt *);
static int auth1_process_rhosts_rsa(Authctxt *);
static int auth1_process_tis_challenge(Authctxt *);
static int auth1_process_tis_response(Authctxt *);
static char *client_user = NULL; /* Used to fill in remote user for PAM */
@ -66,7 +70,7 @@ struct AuthMethod1 {
int type;
char *name;
int *enabled;
int (*method)(Authctxt *, char *, size_t);
int (*method)(Authctxt *);
};
const struct AuthMethod1 auth1_methods[] = {
@ -121,7 +125,7 @@ get_authname(int type)
/*ARGSUSED*/
static int
auth1_process_password(Authctxt *authctxt, char *info, size_t infolen)
auth1_process_password(Authctxt *authctxt)
{
int authenticated = 0;
char *password;
@ -138,15 +142,15 @@ auth1_process_password(Authctxt *authctxt, char *info, size_t infolen)
/* Try authentication with the password. */
authenticated = PRIVSEP(auth_password(authctxt, password));
memset(password, 0, dlen);
xfree(password);
explicit_bzero(password, dlen);
free(password);
return (authenticated);
}
/*ARGSUSED*/
static int
auth1_process_rsa(Authctxt *authctxt, char *info, size_t infolen)
auth1_process_rsa(Authctxt *authctxt)
{
int authenticated = 0;
BIGNUM *n;
@ -164,7 +168,7 @@ auth1_process_rsa(Authctxt *authctxt, char *info, size_t infolen)
/*ARGSUSED*/
static int
auth1_process_rhosts_rsa(Authctxt *authctxt, char *info, size_t infolen)
auth1_process_rhosts_rsa(Authctxt *authctxt)
{
int keybits, authenticated = 0;
u_int bits;
@ -196,14 +200,14 @@ auth1_process_rhosts_rsa(Authctxt *authctxt, char *info, size_t infolen)
client_host_key);
key_free(client_host_key);
snprintf(info, infolen, " ruser %.100s", client_user);
auth_info(authctxt, "ruser %.100s", client_user);
return (authenticated);
}
/*ARGSUSED*/
static int
auth1_process_tis_challenge(Authctxt *authctxt, char *info, size_t infolen)
auth1_process_tis_challenge(Authctxt *authctxt)
{
char *challenge;
@ -213,7 +217,7 @@ auth1_process_tis_challenge(Authctxt *authctxt, char *info, size_t infolen)
debug("sending challenge '%s'", challenge);
packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
packet_put_cstring(challenge);
xfree(challenge);
free(challenge);
packet_send();
packet_write_wait();
@ -222,7 +226,7 @@ auth1_process_tis_challenge(Authctxt *authctxt, char *info, size_t infolen)
/*ARGSUSED*/
static int
auth1_process_tis_response(Authctxt *authctxt, char *info, size_t infolen)
auth1_process_tis_response(Authctxt *authctxt)
{
int authenticated = 0;
char *response;
@ -231,8 +235,8 @@ auth1_process_tis_response(Authctxt *authctxt, char *info, size_t infolen)
response = packet_get_string(&dlen);
packet_check_eom();
authenticated = verify_response(authctxt, response);
memset(response, 'r', dlen);
xfree(response);
explicit_bzero(response, dlen);
free(response);
return (authenticated);
}
@ -245,7 +249,6 @@ static void
do_authloop(Authctxt *authctxt)
{
int authenticated = 0;
char info[1024];
int prev = 0, type = 0;
const struct AuthMethod1 *meth;
@ -262,7 +265,8 @@ do_authloop(Authctxt *authctxt)
if (options.use_pam && (PRIVSEP(do_pam_account())))
#endif
{
auth_log(authctxt, 1, "without authentication", "");
auth_log(authctxt, 1, 0, "without authentication",
NULL);
return;
}
}
@ -276,7 +280,6 @@ do_authloop(Authctxt *authctxt)
/* default to fail */
authenticated = 0;
info[0] = '\0';
/* Get a packet from the client. */
prev = type;
@ -306,7 +309,7 @@ do_authloop(Authctxt *authctxt)
goto skip;
}
authenticated = meth->method(authctxt, info, sizeof(info));
authenticated = meth->method(authctxt);
if (authenticated == -1)
continue; /* "postponed" */
@ -361,12 +364,10 @@ do_authloop(Authctxt *authctxt)
skip:
/* Log before sending the reply */
auth_log(authctxt, authenticated, get_authname(type), info);
auth_log(authctxt, authenticated, 0, get_authname(type), NULL);
if (client_user != NULL) {
xfree(client_user);
client_user = NULL;
}
free(client_user);
client_user = NULL;
if (authenticated)
return;
@ -375,7 +376,7 @@ do_authloop(Authctxt *authctxt)
#ifdef SSH_AUDIT_EVENTS
PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
#endif
packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
auth_maxtries_exceeded(authctxt);
}
packet_start(SSH_SMSG_FAILURE);
@ -415,6 +416,11 @@ do_authentication(Authctxt *authctxt)
authctxt->pw = fakepw();
}
/* Configuration may have changed as a result of Match */
if (options.num_auth_methods != 0)
fatal("AuthenticationMethods is not supported with SSH "
"protocol 1");
setproctitle("%s%s", authctxt->valid ? user : "unknown",
use_privsep ? " [net]" : "");
@ -444,3 +450,5 @@ do_authentication(Authctxt *authctxt)
packet_send();
packet_write_wait();
}
#endif /* WITH_SSH1 */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-chall.c,v 1.34 2008/12/09 04:32:22 djm Exp $ */
/* $OpenBSD: auth2-chall.c,v 1.43 2015/07/18 07:57:14 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2001 Per Allansson. All rights reserved.
@ -41,6 +41,7 @@
#include "packet.h"
#include "dispatch.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
/* import */
@ -48,7 +49,7 @@ extern ServerOptions options;
static int auth2_challenge_start(Authctxt *);
static int send_userauth_info_request(Authctxt *);
static void input_userauth_info_response(int, u_int32_t, void *);
static int input_userauth_info_response(int, u_int32_t, void *);
#ifdef BSD_AUTH
extern KbdintDevice bsdauth_device;
@ -82,6 +83,7 @@ struct KbdintAuthctxt
void *ctxt;
KbdintDevice *device;
u_int nreq;
u_int devices_done;
};
#ifdef USE_PAM
@ -111,7 +113,7 @@ kbdint_alloc(const char *devs)
remove_kbdint_device("pam");
#endif
kbdintctxt = xmalloc(sizeof(KbdintAuthctxt));
kbdintctxt = xcalloc(1, sizeof(KbdintAuthctxt));
if (strcmp(devs, "") == 0) {
buffer_init(&b);
for (i = 0; devices[i]; i++) {
@ -147,15 +149,13 @@ kbdint_free(KbdintAuthctxt *kbdintctxt)
{
if (kbdintctxt->device)
kbdint_reset_device(kbdintctxt);
if (kbdintctxt->devices) {
xfree(kbdintctxt->devices);
kbdintctxt->devices = NULL;
}
xfree(kbdintctxt);
free(kbdintctxt->devices);
explicit_bzero(kbdintctxt, sizeof(*kbdintctxt));
free(kbdintctxt);
}
/* get next device */
static int
kbdint_next_device(KbdintAuthctxt *kbdintctxt)
kbdint_next_device(Authctxt *authctxt, KbdintAuthctxt *kbdintctxt)
{
size_t len;
char *t;
@ -169,12 +169,20 @@ kbdint_next_device(KbdintAuthctxt *kbdintctxt)
if (len == 0)
break;
for (i = 0; devices[i]; i++)
if (strncmp(kbdintctxt->devices, devices[i]->name, len) == 0)
for (i = 0; devices[i]; i++) {
if ((kbdintctxt->devices_done & (1 << i)) != 0 ||
!auth2_method_allowed(authctxt,
"keyboard-interactive", devices[i]->name))
continue;
if (strncmp(kbdintctxt->devices, devices[i]->name,
len) == 0) {
kbdintctxt->device = devices[i];
kbdintctxt->devices_done |= 1 << i;
}
}
t = kbdintctxt->devices;
kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL;
xfree(t);
free(t);
debug2("kbdint_next_device: devices %s", kbdintctxt->devices ?
kbdintctxt->devices : "<empty>");
} while (kbdintctxt->devices && !kbdintctxt->device);
@ -221,7 +229,7 @@ auth2_challenge_start(Authctxt *authctxt)
debug2("auth2_challenge_start: devices %s",
kbdintctxt->devices ? kbdintctxt->devices : "<empty>");
if (kbdint_next_device(kbdintctxt) == 0) {
if (kbdint_next_device(authctxt, kbdintctxt) == 0) {
auth2_challenge_stop(authctxt);
return 0;
}
@ -268,22 +276,23 @@ send_userauth_info_request(Authctxt *authctxt)
packet_write_wait();
for (i = 0; i < kbdintctxt->nreq; i++)
xfree(prompts[i]);
xfree(prompts);
xfree(echo_on);
xfree(name);
xfree(instr);
free(prompts[i]);
free(prompts);
free(echo_on);
free(name);
free(instr);
return 1;
}
static void
static int
input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
{
Authctxt *authctxt = ctxt;
KbdintAuthctxt *kbdintctxt;
int authenticated = 0, res;
u_int i, nresp;
char **response = NULL, *method;
const char *devicename = NULL;
char **response = NULL;
if (authctxt == NULL)
fatal("input_userauth_info_response: no authctxt");
@ -309,11 +318,10 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
res = kbdintctxt->device->respond(kbdintctxt->ctxt, nresp, response);
for (i = 0; i < nresp; i++) {
memset(response[i], 'r', strlen(response[i]));
xfree(response[i]);
explicit_bzero(response[i], strlen(response[i]));
free(response[i]);
}
if (response)
xfree(response);
free(response);
switch (res) {
case 0:
@ -329,9 +337,7 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
/* Failure! */
break;
}
xasprintf(&method, "keyboard-interactive/%s", kbdintctxt->device->name);
devicename = kbdintctxt->device->name;
if (!authctxt->postponed) {
if (authenticated) {
auth2_challenge_stop(authctxt);
@ -341,8 +347,9 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
auth2_challenge_start(authctxt);
}
}
userauth_finish(authctxt, authenticated, method);
xfree(method);
userauth_finish(authctxt, authenticated, "keyboard-interactive",
devicename);
return 0;
}
void

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-gss.c,v 1.17 2011/03/10 02:52:57 djm Exp $ */
/* $OpenBSD: auth2-gss.c,v 1.22 2015/01/19 20:07:45 markus Exp $ */
/*
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
@ -49,6 +49,7 @@
#include "log.h"
#include "dispatch.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "packet.h"
#include "ssh-gss.h"
@ -56,10 +57,10 @@
extern ServerOptions options;
static void input_gssapi_token(int type, u_int32_t plen, void *ctxt);
static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt);
static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
static void input_gssapi_errtok(int, u_int32_t, void *);
static int input_gssapi_token(int type, u_int32_t plen, void *ctxt);
static int input_gssapi_mic(int type, u_int32_t plen, void *ctxt);
static int input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
static int input_gssapi_errtok(int, u_int32_t, void *);
/*
* We only support those mechanisms that we know about (ie ones that we know
@ -71,7 +72,6 @@ userauth_gssapi(Authctxt *authctxt)
gss_OID_desc goid = {0, NULL};
Gssctxt *ctxt = NULL;
int mechs;
gss_OID_set supported;
int present;
OM_uint32 ms;
u_int len;
@ -86,12 +86,10 @@ userauth_gssapi(Authctxt *authctxt)
return (0);
}
ssh_gssapi_supported_oids(&supported);
do {
mechs--;
if (doid)
xfree(doid);
free(doid);
present = 0;
doid = packet_get_string(&len);
@ -100,17 +98,14 @@ userauth_gssapi(Authctxt *authctxt)
doid[1] == len - 2) {
goid.elements = doid + 2;
goid.length = len - 2;
gss_test_oid_set_member(&ms, &goid, supported,
&present);
ssh_gssapi_test_oid_supported(&ms, &goid, &present);
} else {
logit("Badly formed OID received");
}
} while (mechs > 0 && !present);
gss_release_oid_set(&ms, &supported);
if (!present) {
xfree(doid);
free(doid);
authctxt->server_caused_failure = 1;
return (0);
}
@ -118,7 +113,7 @@ userauth_gssapi(Authctxt *authctxt)
if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
if (ctxt != NULL)
ssh_gssapi_delete_ctx(&ctxt);
xfree(doid);
free(doid);
authctxt->server_caused_failure = 1;
return (0);
}
@ -131,7 +126,7 @@ userauth_gssapi(Authctxt *authctxt)
packet_put_string(doid, len);
packet_send();
xfree(doid);
free(doid);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
@ -140,7 +135,7 @@ userauth_gssapi(Authctxt *authctxt)
return (0);
}
static void
static int
input_gssapi_token(int type, u_int32_t plen, void *ctxt)
{
Authctxt *authctxt = ctxt;
@ -162,7 +157,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
&send_tok, &flags));
xfree(recv_tok.value);
free(recv_tok.value);
if (GSS_ERROR(maj_status)) {
if (send_tok.length != 0) {
@ -172,7 +167,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
}
authctxt->postponed = 0;
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
userauth_finish(authctxt, 0, "gssapi-with-mic");
userauth_finish(authctxt, 0, "gssapi-with-mic", NULL);
} else {
if (send_tok.length != 0) {
packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
@ -192,9 +187,10 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
}
gss_release_buffer(&min_status, &send_tok);
return 0;
}
static void
static int
input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
{
Authctxt *authctxt = ctxt;
@ -217,7 +213,7 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok,
&send_tok, NULL));
xfree(recv_tok.value);
free(recv_tok.value);
/* We can't return anything to the client, even if we wanted to */
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
@ -226,6 +222,7 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
/* The client will have already moved on to the next auth */
gss_release_buffer(&maj_status, &send_tok);
return 0;
}
/*
@ -234,18 +231,15 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
* which only enables it once the GSSAPI exchange is complete.
*/
static void
static int
input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
{
Authctxt *authctxt = ctxt;
Gssctxt *gssctxt;
int authenticated;
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
fatal("No authentication or GSSAPI context");
gssctxt = authctxt->methoddata;
/*
* We don't need to check the status, because we're only enabled in
* the dispatcher once the exchange is complete
@ -260,10 +254,11 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
userauth_finish(authctxt, authenticated, "gssapi-with-mic");
userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
return 0;
}
static void
static int
input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
{
Authctxt *authctxt = ctxt;
@ -293,14 +288,15 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
logit("GSSAPI MIC check failed");
buffer_free(&b);
xfree(mic.value);
free(mic.value);
authctxt->postponed = 0;
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
userauth_finish(authctxt, authenticated, "gssapi-with-mic");
userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
return 0;
}
Authmethod method_gssapi = {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-hostbased.c,v 1.14 2010/08/04 05:42:47 djm Exp $ */
/* $OpenBSD: auth2-hostbased.c,v 1.25 2015/05/04 06:10:48 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -45,6 +45,7 @@
#include "packet.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "key.h"
@ -56,6 +57,7 @@
#endif
#include "monitor_wrap.h"
#include "pathnames.h"
#include "match.h"
/* import */
extern ServerOptions options;
@ -109,6 +111,19 @@ userauth_hostbased(Authctxt *authctxt)
"(received %d, expected %d)", key->type, pktype);
goto done;
}
if (key_type_plain(key->type) == KEY_RSA &&
(datafellows & SSH_BUG_RSASIGMD5) != 0) {
error("Refusing RSA key because peer uses unsafe "
"signature format");
goto done;
}
if (match_pattern_list(sshkey_ssh_name(key),
options.hostbased_key_types, 0) != 1) {
logit("%s: key type %s not in HostbasedAcceptedKeyTypes",
__func__, sshkey_type(key));
goto done;
}
service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
authctxt->service;
buffer_init(&b);
@ -125,6 +140,10 @@ userauth_hostbased(Authctxt *authctxt)
#ifdef DEBUG_PK
buffer_dump(&b);
#endif
pubkey_auth_info(authctxt, key,
"client user \"%.100s\", client host \"%.100s\"", cuser, chost);
/* test for allowed key and correct signature */
authenticated = 0;
if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
@ -137,11 +156,11 @@ done:
debug2("userauth_hostbased: authenticated %d", authenticated);
if (key != NULL)
key_free(key);
xfree(pkalg);
xfree(pkblob);
xfree(cuser);
xfree(chost);
xfree(sig);
free(pkalg);
free(pkblob);
free(cuser);
free(chost);
free(sig);
return authenticated;
}
@ -161,7 +180,7 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
resolvedname = get_canonical_hostname(options.use_dns);
ipaddr = get_remote_ipaddr();
debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
debug2("%s: chost %s resolvedname %s ipaddr %s", __func__,
chost, resolvedname, ipaddr);
if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
@ -170,19 +189,27 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
}
if (options.hostbased_uses_name_from_packet_only) {
if (auth_rhosts2(pw, cuser, chost, chost) == 0)
if (auth_rhosts2(pw, cuser, chost, chost) == 0) {
debug2("%s: auth_rhosts2 refused "
"user \"%.100s\" host \"%.100s\" (from packet)",
__func__, cuser, chost);
return 0;
}
lookup = chost;
} else {
if (strcasecmp(resolvedname, chost) != 0)
logit("userauth_hostbased mismatch: "
"client sends %s, but we resolve %s to %s",
chost, ipaddr, resolvedname);
if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0) {
debug2("%s: auth_rhosts2 refused "
"user \"%.100s\" host \"%.100s\" addr \"%.100s\"",
__func__, cuser, resolvedname, ipaddr);
return 0;
}
lookup = resolvedname;
}
debug2("userauth_hostbased: access allowed by auth_rhosts2");
debug2("%s: access allowed by auth_rhosts2", __func__);
if (key_is_cert(key) &&
key_cert_check_authority(key, 1, 0, lookup, &reason)) {
@ -205,18 +232,21 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
if (host_status == HOST_OK) {
if (key_is_cert(key)) {
fp = key_fingerprint(key->cert->signature_key,
SSH_FP_MD5, SSH_FP_HEX);
if ((fp = sshkey_fingerprint(key->cert->signature_key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
verbose("Accepted certificate ID \"%s\" signed by "
"%s CA %s from %s@%s", key->cert->key_id,
key_type(key->cert->signature_key), fp,
cuser, lookup);
} else {
fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
if ((fp = sshkey_fingerprint(key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
verbose("Accepted %s public key %s from %s@%s",
key_type(key), fp, cuser, lookup);
}
xfree(fp);
free(fp);
}
return (host_status == HOST_OK);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-kbdint.c,v 1.5 2006/08/03 03:34:41 deraadt Exp $ */
/* $OpenBSD: auth2-kbdint.c,v 1.7 2014/07/15 15:54:14 millert Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -36,6 +36,7 @@
#include "auth.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
/* import */
@ -56,8 +57,8 @@ userauth_kbdint(Authctxt *authctxt)
if (options.challenge_response_authentication)
authenticated = auth2_challenge(authctxt, devs);
xfree(devs);
xfree(lang);
free(devs);
free(lang);
return authenticated;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-none.c,v 1.16 2010/06/25 08:46:17 djm Exp $ */
/* $OpenBSD: auth2-none.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -39,9 +39,10 @@
#include <sys/uio.h>
#include <fcntl.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include "atomicio.h"
#include "xmalloc.h"
@ -51,6 +52,7 @@
#include "packet.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "ssh2.h"

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-passwd.c,v 1.9 2006/08/03 03:34:41 deraadt Exp $ */
/* $OpenBSD: auth2-passwd.c,v 1.12 2014/07/15 15:54:14 millert Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -41,6 +41,7 @@
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "misc.h"
#include "servconf.h"
/* import */
@ -59,8 +60,8 @@ userauth_passwd(Authctxt *authctxt)
if (change) {
/* discard new password from packet */
newpass = packet_get_string(&newlen);
memset(newpass, 0, newlen);
xfree(newpass);
explicit_bzero(newpass, newlen);
free(newpass);
}
packet_check_eom();
@ -68,8 +69,8 @@ userauth_passwd(Authctxt *authctxt)
logit("password change not supported");
else if (PRIVSEP(auth_password(authctxt, password)) == 1)
authenticated = 1;
memset(password, 0, len);
xfree(password);
explicit_bzero(password, len);
free(password);
return authenticated;
}

File diff suppressed because it is too large Load Diff

319
auth2.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2.c,v 1.123 2011/03/10 02:52:57 djm Exp $ */
/* $OpenBSD: auth2.c,v 1.135 2015/01/19 20:07:45 markus Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -50,6 +50,7 @@
#include "packet.h"
#include "log.h"
#include "buffer.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "key.h"
@ -80,18 +81,12 @@ extern Authmethod method_hostbased;
#ifdef GSSAPI
extern Authmethod method_gssapi;
#endif
#ifdef JPAKE
extern Authmethod method_jpake;
#endif
Authmethod *authmethods[] = {
&method_none,
&method_pubkey,
#ifdef GSSAPI
&method_gssapi,
#endif
#ifdef JPAKE
&method_jpake,
#endif
&method_passwd,
&method_kbdint,
@ -101,12 +96,18 @@ Authmethod *authmethods[] = {
/* protocol */
static void input_service_request(int, u_int32_t, void *);
static void input_userauth_request(int, u_int32_t, void *);
static int input_service_request(int, u_int32_t, void *);
static int input_userauth_request(int, u_int32_t, void *);
/* helper */
static Authmethod *authmethod_lookup(const char *);
static char *authmethods_get(void);
static Authmethod *authmethod_lookup(Authctxt *, const char *);
static char *authmethods_get(Authctxt *authctxt);
#define MATCH_NONE 0 /* method or submethod mismatch */
#define MATCH_METHOD 1 /* method matches (no submethod specified) */
#define MATCH_BOTH 2 /* method and submethod match */
#define MATCH_PARTIAL 3 /* method matches, submethod can't be checked */
static int list_starts_with(const char *, const char *, const char *);
char *
auth2_read_banner(void)
@ -122,7 +123,7 @@ auth2_read_banner(void)
close(fd);
return (NULL);
}
if (st.st_size > 1*1024*1024) {
if (st.st_size <= 0 || st.st_size > 1*1024*1024) {
close(fd);
return (NULL);
}
@ -133,7 +134,7 @@ auth2_read_banner(void)
close(fd);
if (n != len) {
xfree(banner);
free(banner);
return (NULL);
}
banner[n] = '\0';
@ -159,9 +160,7 @@ userauth_banner(void)
{
char *banner = NULL;
if (options.banner == NULL ||
strcasecmp(options.banner, "none") == 0 ||
(datafellows & SSH_BUG_BANNER) != 0)
if (options.banner == NULL || (datafellows & SSH_BUG_BANNER) != 0)
return;
if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
@ -169,8 +168,7 @@ userauth_banner(void)
userauth_send_banner(banner);
done:
if (banner)
xfree(banner);
free(banner);
}
/*
@ -185,7 +183,7 @@ do_authentication2(Authctxt *authctxt)
}
/*ARGSUSED*/
static void
static int
input_service_request(int type, u_int32_t seq, void *ctxt)
{
Authctxt *authctxt = ctxt;
@ -215,11 +213,12 @@ input_service_request(int type, u_int32_t seq, void *ctxt)
debug("bad service request %s", service);
packet_disconnect("bad service request %s", service);
}
xfree(service);
free(service);
return 0;
}
/*ARGSUSED*/
static void
static int
input_userauth_request(int type, u_int32_t seq, void *ctxt)
{
Authctxt *authctxt = ctxt;
@ -264,6 +263,8 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
if (use_privsep)
mm_inform_authserv(service, style);
userauth_banner();
if (auth2_setup_methods_lists(authctxt) != 0)
packet_disconnect("no authentication methods enabled");
} else if (strcmp(user, authctxt->user) != 0 ||
strcmp(service, authctxt->service) != 0) {
packet_disconnect("Change of username or service not allowed: "
@ -272,9 +273,6 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
}
/* reset state */
auth2_challenge_stop(authctxt);
#ifdef JPAKE
auth2_jpake_stop(authctxt);
#endif
#ifdef GSSAPI
/* XXX move to auth2_gssapi_stop() */
@ -286,26 +284,31 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
authctxt->server_caused_failure = 0;
/* try to authenticate user */
m = authmethod_lookup(method);
m = authmethod_lookup(authctxt, method);
if (m != NULL && authctxt->failures < options.max_authtries) {
debug2("input_userauth_request: try method %s", method);
authenticated = m->userauth(authctxt);
}
userauth_finish(authctxt, authenticated, method);
userauth_finish(authctxt, authenticated, method, NULL);
xfree(service);
xfree(user);
xfree(method);
free(service);
free(user);
free(method);
return 0;
}
void
userauth_finish(Authctxt *authctxt, int authenticated, char *method)
userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
const char *submethod)
{
char *methods;
int partial = 0;
if (!authctxt->valid && authenticated)
fatal("INTERNAL ERROR: authenticated invalid user %s",
authctxt->user);
if (authenticated && authctxt->postponed)
fatal("INTERNAL ERROR: authenticated and postponed");
/* Special handling for root */
if (authenticated && authctxt->pw->pw_uid == 0 &&
@ -316,6 +319,19 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
#endif
}
if (authenticated && options.num_auth_methods != 0) {
if (!auth2_update_methods_lists(authctxt, method, submethod)) {
authenticated = 0;
partial = 1;
}
}
/* Log before sending the reply */
auth_log(authctxt, authenticated, partial, method, submethod);
if (authctxt->postponed)
return;
#ifdef USE_PAM
if (options.use_pam && authenticated) {
if (!PRIVSEP(do_pam_account())) {
@ -334,17 +350,10 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
#ifdef _UNICOS
if (authenticated && cray_access_denied(authctxt->user)) {
authenticated = 0;
fatal("Access denied for user %s.",authctxt->user);
fatal("Access denied for user %s.", authctxt->user);
}
#endif /* _UNICOS */
/* Log before sending the reply */
auth_log(authctxt, authenticated, method, " ssh2");
if (authctxt->postponed)
return;
/* XXX todo: check if multiple auth methods are needed */
if (authenticated == 1) {
/* turn off userauth */
dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
@ -356,43 +365,73 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
} else {
/* Allow initial try of "none" auth without failure penalty */
if (!authctxt->server_caused_failure &&
if (!partial && !authctxt->server_caused_failure &&
(authctxt->attempt > 1 || strcmp(method, "none") != 0))
authctxt->failures++;
if (authctxt->failures >= options.max_authtries) {
#ifdef SSH_AUDIT_EVENTS
PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
#endif
packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
auth_maxtries_exceeded(authctxt);
}
methods = authmethods_get();
methods = authmethods_get(authctxt);
debug3("%s: failure partial=%d next methods=\"%s\"", __func__,
partial, methods);
packet_start(SSH2_MSG_USERAUTH_FAILURE);
packet_put_cstring(methods);
packet_put_char(0); /* XXX partial success, unused */
packet_put_char(partial);
packet_send();
packet_write_wait();
xfree(methods);
free(methods);
}
}
/*
* Checks whether method is allowed by at least one AuthenticationMethods
* methods list. Returns 1 if allowed, or no methods lists configured.
* 0 otherwise.
*/
int
auth2_method_allowed(Authctxt *authctxt, const char *method,
const char *submethod)
{
u_int i;
/*
* NB. authctxt->num_auth_methods might be zero as a result of
* auth2_setup_methods_lists(), so check the configuration.
*/
if (options.num_auth_methods == 0)
return 1;
for (i = 0; i < authctxt->num_auth_methods; i++) {
if (list_starts_with(authctxt->auth_methods[i], method,
submethod) != MATCH_NONE)
return 1;
}
return 0;
}
static char *
authmethods_get(void)
authmethods_get(Authctxt *authctxt)
{
Buffer b;
char *list;
int i;
u_int i;
buffer_init(&b);
for (i = 0; authmethods[i] != NULL; i++) {
if (strcmp(authmethods[i]->name, "none") == 0)
continue;
if (authmethods[i]->enabled != NULL &&
*(authmethods[i]->enabled) != 0) {
if (buffer_len(&b) > 0)
buffer_append(&b, ",", 1);
buffer_append(&b, authmethods[i]->name,
strlen(authmethods[i]->name));
}
if (authmethods[i]->enabled == NULL ||
*(authmethods[i]->enabled) == 0)
continue;
if (!auth2_method_allowed(authctxt, authmethods[i]->name,
NULL))
continue;
if (buffer_len(&b) > 0)
buffer_append(&b, ",", 1);
buffer_append(&b, authmethods[i]->name,
strlen(authmethods[i]->name));
}
buffer_append(&b, "\0", 1);
list = xstrdup(buffer_ptr(&b));
@ -401,7 +440,7 @@ authmethods_get(void)
}
static Authmethod *
authmethod_lookup(const char *name)
authmethod_lookup(Authctxt *authctxt, const char *name)
{
int i;
@ -409,9 +448,181 @@ authmethod_lookup(const char *name)
for (i = 0; authmethods[i] != NULL; i++)
if (authmethods[i]->enabled != NULL &&
*(authmethods[i]->enabled) != 0 &&
strcmp(name, authmethods[i]->name) == 0)
strcmp(name, authmethods[i]->name) == 0 &&
auth2_method_allowed(authctxt,
authmethods[i]->name, NULL))
return authmethods[i];
debug2("Unrecognized authentication method name: %s",
name ? name : "NULL");
return NULL;
}
/*
* Check a comma-separated list of methods for validity. Is need_enable is
* non-zero, then also require that the methods are enabled.
* Returns 0 on success or -1 if the methods list is invalid.
*/
int
auth2_methods_valid(const char *_methods, int need_enable)
{
char *methods, *omethods, *method, *p;
u_int i, found;
int ret = -1;
if (*_methods == '\0') {
error("empty authentication method list");
return -1;
}
omethods = methods = xstrdup(_methods);
while ((method = strsep(&methods, ",")) != NULL) {
for (found = i = 0; !found && authmethods[i] != NULL; i++) {
if ((p = strchr(method, ':')) != NULL)
*p = '\0';
if (strcmp(method, authmethods[i]->name) != 0)
continue;
if (need_enable) {
if (authmethods[i]->enabled == NULL ||
*(authmethods[i]->enabled) == 0) {
error("Disabled method \"%s\" in "
"AuthenticationMethods list \"%s\"",
method, _methods);
goto out;
}
}
found = 1;
break;
}
if (!found) {
error("Unknown authentication method \"%s\" in list",
method);
goto out;
}
}
ret = 0;
out:
free(omethods);
return ret;
}
/*
* Prune the AuthenticationMethods supplied in the configuration, removing
* any methods lists that include disabled methods. Note that this might
* leave authctxt->num_auth_methods == 0, even when multiple required auth
* has been requested. For this reason, all tests for whether multiple is
* enabled should consult options.num_auth_methods directly.
*/
int
auth2_setup_methods_lists(Authctxt *authctxt)
{
u_int i;
if (options.num_auth_methods == 0)
return 0;
debug3("%s: checking methods", __func__);
authctxt->auth_methods = xcalloc(options.num_auth_methods,
sizeof(*authctxt->auth_methods));
authctxt->num_auth_methods = 0;
for (i = 0; i < options.num_auth_methods; i++) {
if (auth2_methods_valid(options.auth_methods[i], 1) != 0) {
logit("Authentication methods list \"%s\" contains "
"disabled method, skipping",
options.auth_methods[i]);
continue;
}
debug("authentication methods list %d: %s",
authctxt->num_auth_methods, options.auth_methods[i]);
authctxt->auth_methods[authctxt->num_auth_methods++] =
xstrdup(options.auth_methods[i]);
}
if (authctxt->num_auth_methods == 0) {
error("No AuthenticationMethods left after eliminating "
"disabled methods");
return -1;
}
return 0;
}
static int
list_starts_with(const char *methods, const char *method,
const char *submethod)
{
size_t l = strlen(method);
int match;
const char *p;
if (strncmp(methods, method, l) != 0)
return MATCH_NONE;
p = methods + l;
match = MATCH_METHOD;
if (*p == ':') {
if (!submethod)
return MATCH_PARTIAL;
l = strlen(submethod);
p += 1;
if (strncmp(submethod, p, l))
return MATCH_NONE;
p += l;
match = MATCH_BOTH;
}
if (*p != ',' && *p != '\0')
return MATCH_NONE;
return match;
}
/*
* Remove method from the start of a comma-separated list of methods.
* Returns 0 if the list of methods did not start with that method or 1
* if it did.
*/
static int
remove_method(char **methods, const char *method, const char *submethod)
{
char *omethods = *methods, *p;
size_t l = strlen(method);
int match;
match = list_starts_with(omethods, method, submethod);
if (match != MATCH_METHOD && match != MATCH_BOTH)
return 0;
p = omethods + l;
if (submethod && match == MATCH_BOTH)
p += 1 + strlen(submethod); /* include colon */
if (*p == ',')
p++;
*methods = xstrdup(p);
free(omethods);
return 1;
}
/*
* Called after successful authentication. Will remove the successful method
* from the start of each list in which it occurs. If it was the last method
* in any list, then authentication is deemed successful.
* Returns 1 if the method completed any authentication list or 0 otherwise.
*/
int
auth2_update_methods_lists(Authctxt *authctxt, const char *method,
const char *submethod)
{
u_int i, found = 0;
debug3("%s: updating methods list after \"%s\"", __func__, method);
for (i = 0; i < authctxt->num_auth_methods; i++) {
if (!remove_method(&(authctxt->auth_methods[i]), method,
submethod))
continue;
found = 1;
if (*authctxt->auth_methods[i] == '\0') {
debug2("authentication methods list %d complete", i);
return 1;
}
debug3("authentication methods list %d remaining: \"%s\"",
i, authctxt->auth_methods[i]);
}
/* This should not happen, but would be bad if it did */
if (!found)
fatal("%s: method not in AuthenticationMethods", __func__);
return 0;
}

913
authfd.c

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $OpenBSD: authfd.h,v 1.37 2009/08/27 17:44:52 djm Exp $ */
/* $OpenBSD: authfd.h,v 1.38 2015/01/14 20:05:27 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -16,6 +16,33 @@
#ifndef AUTHFD_H
#define AUTHFD_H
/* List of identities returned by ssh_fetch_identitylist() */
struct ssh_identitylist {
size_t nkeys;
struct sshkey **keys;
char **comments;
};
int ssh_get_authentication_socket(int *fdp);
void ssh_close_authentication_socket(int sock);
int ssh_lock_agent(int sock, int lock, const char *password);
int ssh_fetch_identitylist(int sock, int version,
struct ssh_identitylist **idlp);
void ssh_free_identitylist(struct ssh_identitylist *idl);
int ssh_add_identity_constrained(int sock, struct sshkey *key,
const char *comment, u_int life, u_int confirm);
int ssh_remove_identity(int sock, struct sshkey *key);
int ssh_update_card(int sock, int add, const char *reader_id,
const char *pin, u_int life, u_int confirm);
int ssh_remove_all_identities(int sock, int version);
int ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge,
u_char session_id[16], u_char response[16]);
int ssh_agent_sign(int sock, struct sshkey *key,
u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat);
/* Messages for the authentication agent connection. */
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
@ -60,35 +87,4 @@
#define SSH_AGENT_OLD_SIGNATURE 0x01
typedef struct {
int fd;
Buffer identities;
int howmany;
} AuthenticationConnection;
int ssh_agent_present(void);
int ssh_get_authentication_socket(void);
void ssh_close_authentication_socket(int);
AuthenticationConnection *ssh_get_authentication_connection(void);
void ssh_close_authentication_connection(AuthenticationConnection *);
int ssh_get_num_identities(AuthenticationConnection *, int);
Key *ssh_get_first_identity(AuthenticationConnection *, char **, int);
Key *ssh_get_next_identity(AuthenticationConnection *, char **, int);
int ssh_add_identity_constrained(AuthenticationConnection *, Key *,
const char *, u_int, u_int);
int ssh_remove_identity(AuthenticationConnection *, Key *);
int ssh_remove_all_identities(AuthenticationConnection *, int);
int ssh_lock_agent(AuthenticationConnection *, int, const char *);
int ssh_update_card(AuthenticationConnection *, int, const char *,
const char *, u_int, u_int);
int
ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16],
u_int, u_char[16]);
int
ssh_agent_sign(AuthenticationConnection *, Key *, u_char **, u_int *, u_char *,
u_int);
#endif /* AUTHFD_H */

1089
authfile.c

File diff suppressed because it is too large Load Diff

View File

@ -1,31 +1,52 @@
/* $OpenBSD: authfile.h,v 1.16 2011/05/04 21:15:29 djm Exp $ */
/* $OpenBSD: authfile.h,v 1.21 2015/01/08 10:14:08 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef AUTHFILE_H
#define AUTHFILE_H
int key_save_private(Key *, const char *, const char *, const char *);
int key_load_file(int, const char *, Buffer *);
Key *key_load_cert(const char *);
Key *key_load_public(const char *, char **);
Key *key_load_public_type(int, const char *, char **);
Key *key_parse_private(Buffer *, const char *, const char *, char **);
Key *key_load_private(const char *, const char *, char **);
Key *key_load_private_cert(int, const char *, const char *, int *);
Key *key_load_private_type(int, const char *, const char *, char **, int *);
Key *key_load_private_pem(int, int, const char *, char **);
int key_perm_ok(int, const char *);
int key_in_file(Key *, const char *, int);
struct sshbuf;
struct sshkey;
/* XXX document these */
/* XXX some of these could probably be merged/retired */
int sshkey_save_private(struct sshkey *, const char *,
const char *, const char *, int, const char *, int);
int sshkey_load_file(int, struct sshbuf *);
int sshkey_load_cert(const char *, struct sshkey **);
int sshkey_load_public(const char *, struct sshkey **, char **);
int sshkey_load_private(const char *, const char *, struct sshkey **, char **);
int sshkey_load_private_cert(int, const char *, const char *,
struct sshkey **, int *);
int sshkey_load_private_type(int, const char *, const char *,
struct sshkey **, char **, int *);
int sshkey_load_private_type_fd(int fd, int type, const char *passphrase,
struct sshkey **keyp, char **commentp);
int sshkey_perm_ok(int, const char *);
int sshkey_in_file(struct sshkey *, const char *, int, int);
int sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file);
#endif

212
bitmap.c Normal file
View File

@ -0,0 +1,212 @@
/*
* Copyright (c) 2015 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include "bitmap.h"
#define BITMAP_WTYPE u_int
#define BITMAP_MAX (1<<24)
#define BITMAP_BYTES (sizeof(BITMAP_WTYPE))
#define BITMAP_BITS (sizeof(BITMAP_WTYPE) * 8)
#define BITMAP_WMASK ((BITMAP_WTYPE)BITMAP_BITS - 1)
struct bitmap {
BITMAP_WTYPE *d;
size_t len; /* number of words allocated */
size_t top; /* index of top word allocated */
};
struct bitmap *
bitmap_new(void)
{
struct bitmap *ret;
if ((ret = calloc(1, sizeof(*ret))) == NULL)
return NULL;
if ((ret->d = calloc(1, BITMAP_BYTES)) == NULL) {
free(ret);
return NULL;
}
ret->len = 1;
ret->top = 0;
return ret;
}
void
bitmap_free(struct bitmap *b)
{
if (b != NULL && b->d != NULL) {
memset(b->d, 0, b->len);
free(b->d);
}
free(b);
}
void
bitmap_zero(struct bitmap *b)
{
memset(b->d, 0, b->len * BITMAP_BYTES);
b->top = 0;
}
int
bitmap_test_bit(struct bitmap *b, u_int n)
{
if (b->top >= b->len)
return 0; /* invalid */
if (b->len == 0 || (n / BITMAP_BITS) > b->top)
return 0;
return (b->d[n / BITMAP_BITS] >> (n & BITMAP_WMASK)) & 1;
}
static int
reserve(struct bitmap *b, u_int n)
{
BITMAP_WTYPE *tmp;
size_t nlen;
if (b->top >= b->len || n > BITMAP_MAX)
return -1; /* invalid */
nlen = (n / BITMAP_BITS) + 1;
if (b->len < nlen) {
if ((tmp = reallocarray(b->d, nlen, BITMAP_BYTES)) == NULL)
return -1;
b->d = tmp;
memset(b->d + b->len, 0, (nlen - b->len) * BITMAP_BYTES);
b->len = nlen;
}
return 0;
}
int
bitmap_set_bit(struct bitmap *b, u_int n)
{
int r;
size_t offset;
if ((r = reserve(b, n)) != 0)
return r;
offset = n / BITMAP_BITS;
if (offset > b->top)
b->top = offset;
b->d[offset] |= (BITMAP_WTYPE)1 << (n & BITMAP_WMASK);
return 0;
}
/* Resets b->top to point to the most significant bit set in b->d */
static void
retop(struct bitmap *b)
{
if (b->top >= b->len)
return;
while (b->top > 0 && b->d[b->top] == 0)
b->top--;
}
void
bitmap_clear_bit(struct bitmap *b, u_int n)
{
size_t offset;
if (b->top >= b->len || n > BITMAP_MAX)
return; /* invalid */
offset = n / BITMAP_BITS;
if (offset > b->top)
return;
b->d[offset] &= ~((BITMAP_WTYPE)1 << (n & BITMAP_WMASK));
/* The top may have changed as a result of the clear */
retop(b);
}
size_t
bitmap_nbits(struct bitmap *b)
{
size_t bits;
BITMAP_WTYPE w;
retop(b);
if (b->top >= b->len)
return 0; /* invalid */
if (b->len == 0 || (b->top == 0 && b->d[0] == 0))
return 0;
/* Find MSB set */
w = b->d[b->top];
bits = (b->top + 1) * BITMAP_BITS;
while (!(w & ((BITMAP_WTYPE)1 << (BITMAP_BITS - 1)))) {
w <<= 1;
bits--;
}
return bits;
}
size_t
bitmap_nbytes(struct bitmap *b)
{
return (bitmap_nbits(b) + 7) / 8;
}
int
bitmap_to_string(struct bitmap *b, void *p, size_t l)
{
u_char *s = (u_char *)p;
size_t i, j, k, need = bitmap_nbytes(b);
if (l < need || b->top >= b->len)
return -1;
if (l > need)
l = need;
/* Put the bytes from LSB backwards */
for (i = k = 0; i < b->top + 1; i++) {
for (j = 0; j < BITMAP_BYTES; j++) {
if (k >= l)
break;
s[need - 1 - k++] = (b->d[i] >> (j * 8)) & 0xff;
}
}
return 0;
}
int
bitmap_from_string(struct bitmap *b, const void *p, size_t l)
{
int r;
size_t i, offset, shift;
u_char *s = (u_char *)p;
if (l > BITMAP_MAX / 8)
return -1;
if ((r = reserve(b, l * 8)) != 0)
return r;
bitmap_zero(b);
if (l == 0)
return 0;
b->top = offset = ((l + (BITMAP_BYTES - 1)) / BITMAP_BYTES) - 1;
shift = ((l + (BITMAP_BYTES - 1)) % BITMAP_BYTES) * 8;
for (i = 0; i < l; i++) {
b->d[offset] |= (BITMAP_WTYPE)s[i] << shift;
if (shift == 0) {
offset--;
shift = BITMAP_BITS - 8;
} else
shift -= 8;
}
retop(b);
return 0;
}

56
bitmap.h Normal file
View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2015 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BITMAP_H
#define _BITMAP_H
#include <sys/types.h>
/* Simple bit vector routines */
struct bitmap;
/* Allocate a new bitmap. Returns NULL on allocation failure. */
struct bitmap *bitmap_new(void);
/* Free a bitmap */
void bitmap_free(struct bitmap *b);
/* Zero an existing bitmap */
void bitmap_zero(struct bitmap *b);
/* Test whether a bit is set in a bitmap. */
int bitmap_test_bit(struct bitmap *b, u_int n);
/* Set a bit in a bitmap. Returns 0 on success or -1 on error */
int bitmap_set_bit(struct bitmap *b, u_int n);
/* Clear a bit in a bitmap */
void bitmap_clear_bit(struct bitmap *b, u_int n);
/* Return the number of bits in a bitmap (i.e. the position of the MSB) */
size_t bitmap_nbits(struct bitmap *b);
/* Return the number of bytes needed to represent a bitmap */
size_t bitmap_nbytes(struct bitmap *b);
/* Convert a bitmap to a big endian byte string */
int bitmap_to_string(struct bitmap *b, void *p, size_t l);
/* Convert a big endian byte string to a bitmap */
int bitmap_from_string(struct bitmap *b, const void *p, size_t l);
#endif /* _BITMAP_H */

248
blocks.c Normal file
View File

@ -0,0 +1,248 @@
/* $OpenBSD: blocks.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */
/*
* Public Domain, Author: Daniel J. Bernstein
* Copied from nacl-20110221/crypto_hashblocks/sha512/ref/blocks.c
*/
#include "includes.h"
#include "crypto_api.h"
typedef unsigned long long uint64;
static uint64 load_bigendian(const unsigned char *x)
{
return
(uint64) (x[7]) \
| (((uint64) (x[6])) << 8) \
| (((uint64) (x[5])) << 16) \
| (((uint64) (x[4])) << 24) \
| (((uint64) (x[3])) << 32) \
| (((uint64) (x[2])) << 40) \
| (((uint64) (x[1])) << 48) \
| (((uint64) (x[0])) << 56)
;
}
static void store_bigendian(unsigned char *x,uint64 u)
{
x[7] = u; u >>= 8;
x[6] = u; u >>= 8;
x[5] = u; u >>= 8;
x[4] = u; u >>= 8;
x[3] = u; u >>= 8;
x[2] = u; u >>= 8;
x[1] = u; u >>= 8;
x[0] = u;
}
#define SHR(x,c) ((x) >> (c))
#define ROTR(x,c) (((x) >> (c)) | ((x) << (64 - (c))))
#define Ch(x,y,z) ((x & y) ^ (~x & z))
#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z))
#define Sigma0(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
#define Sigma1(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
#define sigma0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x,7))
#define sigma1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x,6))
#define M(w0,w14,w9,w1) w0 = sigma1(w14) + w9 + sigma0(w1) + w0;
#define EXPAND \
M(w0 ,w14,w9 ,w1 ) \
M(w1 ,w15,w10,w2 ) \
M(w2 ,w0 ,w11,w3 ) \
M(w3 ,w1 ,w12,w4 ) \
M(w4 ,w2 ,w13,w5 ) \
M(w5 ,w3 ,w14,w6 ) \
M(w6 ,w4 ,w15,w7 ) \
M(w7 ,w5 ,w0 ,w8 ) \
M(w8 ,w6 ,w1 ,w9 ) \
M(w9 ,w7 ,w2 ,w10) \
M(w10,w8 ,w3 ,w11) \
M(w11,w9 ,w4 ,w12) \
M(w12,w10,w5 ,w13) \
M(w13,w11,w6 ,w14) \
M(w14,w12,w7 ,w15) \
M(w15,w13,w8 ,w0 )
#define F(w,k) \
T1 = h + Sigma1(e) + Ch(e,f,g) + k + w; \
T2 = Sigma0(a) + Maj(a,b,c); \
h = g; \
g = f; \
f = e; \
e = d + T1; \
d = c; \
c = b; \
b = a; \
a = T1 + T2;
int crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen)
{
uint64 state[8];
uint64 a;
uint64 b;
uint64 c;
uint64 d;
uint64 e;
uint64 f;
uint64 g;
uint64 h;
uint64 T1;
uint64 T2;
a = load_bigendian(statebytes + 0); state[0] = a;
b = load_bigendian(statebytes + 8); state[1] = b;
c = load_bigendian(statebytes + 16); state[2] = c;
d = load_bigendian(statebytes + 24); state[3] = d;
e = load_bigendian(statebytes + 32); state[4] = e;
f = load_bigendian(statebytes + 40); state[5] = f;
g = load_bigendian(statebytes + 48); state[6] = g;
h = load_bigendian(statebytes + 56); state[7] = h;
while (inlen >= 128) {
uint64 w0 = load_bigendian(in + 0);
uint64 w1 = load_bigendian(in + 8);
uint64 w2 = load_bigendian(in + 16);
uint64 w3 = load_bigendian(in + 24);
uint64 w4 = load_bigendian(in + 32);
uint64 w5 = load_bigendian(in + 40);
uint64 w6 = load_bigendian(in + 48);
uint64 w7 = load_bigendian(in + 56);
uint64 w8 = load_bigendian(in + 64);
uint64 w9 = load_bigendian(in + 72);
uint64 w10 = load_bigendian(in + 80);
uint64 w11 = load_bigendian(in + 88);
uint64 w12 = load_bigendian(in + 96);
uint64 w13 = load_bigendian(in + 104);
uint64 w14 = load_bigendian(in + 112);
uint64 w15 = load_bigendian(in + 120);
F(w0 ,0x428a2f98d728ae22ULL)
F(w1 ,0x7137449123ef65cdULL)
F(w2 ,0xb5c0fbcfec4d3b2fULL)
F(w3 ,0xe9b5dba58189dbbcULL)
F(w4 ,0x3956c25bf348b538ULL)
F(w5 ,0x59f111f1b605d019ULL)
F(w6 ,0x923f82a4af194f9bULL)
F(w7 ,0xab1c5ed5da6d8118ULL)
F(w8 ,0xd807aa98a3030242ULL)
F(w9 ,0x12835b0145706fbeULL)
F(w10,0x243185be4ee4b28cULL)
F(w11,0x550c7dc3d5ffb4e2ULL)
F(w12,0x72be5d74f27b896fULL)
F(w13,0x80deb1fe3b1696b1ULL)
F(w14,0x9bdc06a725c71235ULL)
F(w15,0xc19bf174cf692694ULL)
EXPAND
F(w0 ,0xe49b69c19ef14ad2ULL)
F(w1 ,0xefbe4786384f25e3ULL)
F(w2 ,0x0fc19dc68b8cd5b5ULL)
F(w3 ,0x240ca1cc77ac9c65ULL)
F(w4 ,0x2de92c6f592b0275ULL)
F(w5 ,0x4a7484aa6ea6e483ULL)
F(w6 ,0x5cb0a9dcbd41fbd4ULL)
F(w7 ,0x76f988da831153b5ULL)
F(w8 ,0x983e5152ee66dfabULL)
F(w9 ,0xa831c66d2db43210ULL)
F(w10,0xb00327c898fb213fULL)
F(w11,0xbf597fc7beef0ee4ULL)
F(w12,0xc6e00bf33da88fc2ULL)
F(w13,0xd5a79147930aa725ULL)
F(w14,0x06ca6351e003826fULL)
F(w15,0x142929670a0e6e70ULL)
EXPAND
F(w0 ,0x27b70a8546d22ffcULL)
F(w1 ,0x2e1b21385c26c926ULL)
F(w2 ,0x4d2c6dfc5ac42aedULL)
F(w3 ,0x53380d139d95b3dfULL)
F(w4 ,0x650a73548baf63deULL)
F(w5 ,0x766a0abb3c77b2a8ULL)
F(w6 ,0x81c2c92e47edaee6ULL)
F(w7 ,0x92722c851482353bULL)
F(w8 ,0xa2bfe8a14cf10364ULL)
F(w9 ,0xa81a664bbc423001ULL)
F(w10,0xc24b8b70d0f89791ULL)
F(w11,0xc76c51a30654be30ULL)
F(w12,0xd192e819d6ef5218ULL)
F(w13,0xd69906245565a910ULL)
F(w14,0xf40e35855771202aULL)
F(w15,0x106aa07032bbd1b8ULL)
EXPAND
F(w0 ,0x19a4c116b8d2d0c8ULL)
F(w1 ,0x1e376c085141ab53ULL)
F(w2 ,0x2748774cdf8eeb99ULL)
F(w3 ,0x34b0bcb5e19b48a8ULL)
F(w4 ,0x391c0cb3c5c95a63ULL)
F(w5 ,0x4ed8aa4ae3418acbULL)
F(w6 ,0x5b9cca4f7763e373ULL)
F(w7 ,0x682e6ff3d6b2b8a3ULL)
F(w8 ,0x748f82ee5defb2fcULL)
F(w9 ,0x78a5636f43172f60ULL)
F(w10,0x84c87814a1f0ab72ULL)
F(w11,0x8cc702081a6439ecULL)
F(w12,0x90befffa23631e28ULL)
F(w13,0xa4506cebde82bde9ULL)
F(w14,0xbef9a3f7b2c67915ULL)
F(w15,0xc67178f2e372532bULL)
EXPAND
F(w0 ,0xca273eceea26619cULL)
F(w1 ,0xd186b8c721c0c207ULL)
F(w2 ,0xeada7dd6cde0eb1eULL)
F(w3 ,0xf57d4f7fee6ed178ULL)
F(w4 ,0x06f067aa72176fbaULL)
F(w5 ,0x0a637dc5a2c898a6ULL)
F(w6 ,0x113f9804bef90daeULL)
F(w7 ,0x1b710b35131c471bULL)
F(w8 ,0x28db77f523047d84ULL)
F(w9 ,0x32caab7b40c72493ULL)
F(w10,0x3c9ebe0a15c9bebcULL)
F(w11,0x431d67c49c100d4cULL)
F(w12,0x4cc5d4becb3e42b6ULL)
F(w13,0x597f299cfc657e2aULL)
F(w14,0x5fcb6fab3ad6faecULL)
F(w15,0x6c44198c4a475817ULL)
a += state[0];
b += state[1];
c += state[2];
d += state[3];
e += state[4];
f += state[5];
g += state[6];
h += state[7];
state[0] = a;
state[1] = b;
state[2] = c;
state[3] = d;
state[4] = e;
state[5] = f;
state[6] = g;
state[7] = h;
in += 128;
inlen -= 128;
}
store_bigendian(statebytes + 0,state[0]);
store_bigendian(statebytes + 8,state[1]);
store_bigendian(statebytes + 16,state[2]);
store_bigendian(statebytes + 24,state[3]);
store_bigendian(statebytes + 32,state[4]);
store_bigendian(statebytes + 40,state[5]);
store_bigendian(statebytes + 48,state[6]);
store_bigendian(statebytes + 56,state[7]);
return inlen;
}

271
bufaux.c
View File

@ -1,69 +1,40 @@
/* $OpenBSD: bufaux.c,v 1.50 2010/08/31 09:58:37 djm Exp $ */
/* $OpenBSD: bufaux.c,v 1.60 2014/04/30 05:29:56 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Auxiliary functions for storing and retrieving various data types to/from
* Buffers.
* Copyright (c) 2012 Damien Miller <djm@mindrot.org>
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
*
* SSH2 packet format added by Markus Friedl
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
#include "includes.h"
#include <sys/types.h>
#include <openssl/bn.h>
#include <string.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
/*
* Returns integers from the buffer (msb first).
*/
#include "ssherr.h"
int
buffer_get_short_ret(u_short *ret, Buffer *buffer)
buffer_get_short_ret(u_short *v, Buffer *buffer)
{
u_char buf[2];
int ret;
if (buffer_get_ret(buffer, (char *) buf, 2) == -1)
return (-1);
*ret = get_u16(buf);
return (0);
if ((ret = sshbuf_get_u16(buffer, v)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
return 0;
}
u_short
@ -72,21 +43,21 @@ buffer_get_short(Buffer *buffer)
u_short ret;
if (buffer_get_short_ret(&ret, buffer) == -1)
fatal("buffer_get_short: buffer error");
fatal("%s: buffer error", __func__);
return (ret);
}
int
buffer_get_int_ret(u_int *ret, Buffer *buffer)
buffer_get_int_ret(u_int *v, Buffer *buffer)
{
u_char buf[4];
int ret;
if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
return (-1);
if (ret != NULL)
*ret = get_u32(buf);
return (0);
if ((ret = sshbuf_get_u32(buffer, v)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
return 0;
}
u_int
@ -95,21 +66,21 @@ buffer_get_int(Buffer *buffer)
u_int ret;
if (buffer_get_int_ret(&ret, buffer) == -1)
fatal("buffer_get_int: buffer error");
fatal("%s: buffer error", __func__);
return (ret);
}
int
buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer)
buffer_get_int64_ret(u_int64_t *v, Buffer *buffer)
{
u_char buf[8];
int ret;
if (buffer_get_ret(buffer, (char *) buf, 8) == -1)
return (-1);
if (ret != NULL)
*ret = get_u64(buf);
return (0);
if ((ret = sshbuf_get_u64(buffer, v)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
return 0;
}
u_int64_t
@ -118,78 +89,52 @@ buffer_get_int64(Buffer *buffer)
u_int64_t ret;
if (buffer_get_int64_ret(&ret, buffer) == -1)
fatal("buffer_get_int: buffer error");
fatal("%s: buffer error", __func__);
return (ret);
}
/*
* Stores integers in the buffer, msb first.
*/
void
buffer_put_short(Buffer *buffer, u_short value)
{
char buf[2];
int ret;
put_u16(buf, value);
buffer_append(buffer, buf, 2);
if ((ret = sshbuf_put_u16(buffer, value)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
}
void
buffer_put_int(Buffer *buffer, u_int value)
{
char buf[4];
int ret;
put_u32(buf, value);
buffer_append(buffer, buf, 4);
if ((ret = sshbuf_put_u32(buffer, value)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
}
void
buffer_put_int64(Buffer *buffer, u_int64_t value)
{
char buf[8];
int ret;
put_u64(buf, value);
buffer_append(buffer, buf, 8);
if ((ret = sshbuf_put_u64(buffer, value)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
}
/*
* 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.
*/
void *
buffer_get_string_ret(Buffer *buffer, u_int *length_ptr)
{
size_t len;
int ret;
u_char *value;
u_int len;
/* Get the length. */
if (buffer_get_int_ret(&len, buffer) != 0) {
error("buffer_get_string_ret: cannot extract length");
return (NULL);
if ((ret = sshbuf_get_string(buffer, &value, &len)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return NULL;
}
if (len > 256 * 1024) {
error("buffer_get_string_ret: bad string length %u", len);
return (NULL);
}
/* Allocate space for the string. Add one byte for a null character. */
value = xmalloc(len + 1);
/* Get the string. */
if (buffer_get_ret(buffer, value, len) == -1) {
error("buffer_get_string_ret: buffer_get failed");
xfree(value);
return (NULL);
}
/* 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);
if (length_ptr != NULL)
*length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */
return value;
}
void *
@ -198,31 +143,24 @@ buffer_get_string(Buffer *buffer, u_int *length_ptr)
void *ret;
if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL)
fatal("buffer_get_string: buffer error");
fatal("%s: buffer error", __func__);
return (ret);
}
char *
buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr)
{
u_int length;
char *cp, *ret = buffer_get_string_ret(buffer, &length);
size_t len;
int ret;
char *value;
if (ret == NULL)
if ((ret = sshbuf_get_cstring(buffer, &value, &len)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return NULL;
if ((cp = memchr(ret, '\0', length)) != NULL) {
/* XXX allow \0 at end-of-string for a while, remove later */
if (cp == ret + length - 1)
error("buffer_get_cstring_ret: string contains \\0");
else {
bzero(ret, length);
xfree(ret);
return NULL;
}
}
if (length_ptr != NULL)
*length_ptr = length;
return ret;
*length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */
return value;
}
char *
@ -231,67 +169,64 @@ buffer_get_cstring(Buffer *buffer, u_int *length_ptr)
char *ret;
if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL)
fatal("buffer_get_cstring: buffer error");
fatal("%s: buffer error", __func__);
return ret;
}
void *
const void *
buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr)
{
void *ptr;
u_int len;
size_t len;
int ret;
const u_char *value;
if (buffer_get_int_ret(&len, buffer) != 0)
return NULL;
if (len > 256 * 1024) {
error("buffer_get_string_ptr: bad string length %u", len);
if ((ret = sshbuf_get_string_direct(buffer, &value, &len)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return NULL;
}
ptr = buffer_ptr(buffer);
buffer_consume(buffer, len);
if (length_ptr)
*length_ptr = len;
return (ptr);
if (length_ptr != NULL)
*length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */
return value;
}
void *
const void *
buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr)
{
void *ret;
const void *ret;
if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL)
fatal("buffer_get_string_ptr: buffer error");
fatal("%s: buffer error", __func__);
return (ret);
}
/*
* Stores and arbitrary binary string in the buffer.
*/
void
buffer_put_string(Buffer *buffer, const void *buf, u_int len)
{
buffer_put_int(buffer, len);
buffer_append(buffer, buf, len);
int ret;
if ((ret = sshbuf_put_string(buffer, buf, len)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
}
void
buffer_put_cstring(Buffer *buffer, const char *s)
{
if (s == NULL)
fatal("buffer_put_cstring: s == NULL");
buffer_put_string(buffer, s, strlen(s));
int ret;
if ((ret = sshbuf_put_cstring(buffer, s)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
}
/*
* Returns a character from the buffer (0 - 255).
*/
int
buffer_get_char_ret(char *ret, Buffer *buffer)
buffer_get_char_ret(char *v, Buffer *buffer)
{
if (buffer_get_ret(buffer, ret, 1) == -1) {
error("buffer_get_char_ret: buffer_get_ret failed");
return (-1);
int ret;
if ((ret = sshbuf_get_u8(buffer, (u_char *)v)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
return (0);
return 0;
}
int
@ -300,19 +235,26 @@ buffer_get_char(Buffer *buffer)
char ch;
if (buffer_get_char_ret(&ch, buffer) == -1)
fatal("buffer_get_char: buffer error");
fatal("%s: buffer error", __func__);
return (u_char) ch;
}
/*
* Stores a character in the buffer.
*/
void
buffer_put_char(Buffer *buffer, int value)
{
char ch = value;
int ret;
buffer_append(buffer, &ch, 1);
if ((ret = sshbuf_put_u8(buffer, value)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
}
void
buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l)
{
int ret;
if ((ret = sshbuf_put_bignum2_bytes(buffer, s, l)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
}
#ifdef WIN32_FIXME
@ -373,3 +315,4 @@ void buffer_put_string_local8_to_utf8(Buffer *b, const void *str, u_int len)
#endif /* WIN32_FIXME */

206
bufbn.c
View File

@ -1,223 +1,109 @@
/* $OpenBSD: bufbn.c,v 1.6 2007/06/02 09:04:58 djm Exp $*/
/* $OpenBSD: bufbn.c,v 1.12 2014/04/30 05:29:56 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Auxiliary functions for storing and retrieving various data types to/from
* Buffers.
* Copyright (c) 2012 Damien Miller <djm@mindrot.org>
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
*
* SSH2 packet format added by Markus Friedl
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
#include "includes.h"
#ifdef WITH_OPENSSL
#include <sys/types.h>
#include <openssl/bn.h>
#include <string.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
#include "ssherr.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.
*/
#ifdef WITH_SSH1
int
buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value)
{
int bits = BN_num_bits(value);
int bin_size = (bits + 7) / 8;
u_char *buf = xmalloc(bin_size);
int oi;
char msg[2];
int ret;
/* Get the value of in binary */
oi = BN_bn2bin(value, buf);
if (oi != bin_size) {
error("buffer_put_bignum_ret: BN_bn2bin() failed: oi %d != bin_size %d",
oi, bin_size);
xfree(buf);
return (-1);
if ((ret = sshbuf_put_bignum1(buffer, value)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
/* Store the number of bits in the buffer in two bytes, msb first. */
put_u16(msg, bits);
buffer_append(buffer, msg, 2);
/* Store the binary data. */
buffer_append(buffer, buf, oi);
memset(buf, 0, bin_size);
xfree(buf);
return (0);
return 0;
}
void
buffer_put_bignum(Buffer *buffer, const BIGNUM *value)
{
if (buffer_put_bignum_ret(buffer, value) == -1)
fatal("buffer_put_bignum: buffer error");
fatal("%s: buffer error", __func__);
}
/*
* Retrieves a BIGNUM from the buffer.
*/
int
buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value)
{
u_int bits, bytes;
u_char buf[2], *bin;
int ret;
/* Get the number of bits. */
if (buffer_get_ret(buffer, (char *) buf, 2) == -1) {
error("buffer_get_bignum_ret: invalid length");
return (-1);
if ((ret = sshbuf_get_bignum1(buffer, value)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
bits = get_u16(buf);
/* Compute the number of binary bytes that follow. */
bytes = (bits + 7) / 8;
if (bytes > 8 * 1024) {
error("buffer_get_bignum_ret: cannot handle BN of size %d", bytes);
return (-1);
}
if (buffer_len(buffer) < bytes) {
error("buffer_get_bignum_ret: input buffer too small");
return (-1);
}
bin = buffer_ptr(buffer);
if (BN_bin2bn(bin, bytes, value) == NULL) {
error("buffer_get_bignum_ret: BN_bin2bn failed");
return (-1);
}
if (buffer_consume_ret(buffer, bytes) == -1) {
error("buffer_get_bignum_ret: buffer_consume failed");
return (-1);
}
return (0);
return 0;
}
void
buffer_get_bignum(Buffer *buffer, BIGNUM *value)
{
if (buffer_get_bignum_ret(buffer, value) == -1)
fatal("buffer_get_bignum: buffer error");
fatal("%s: buffer error", __func__);
}
#endif /* WITH_SSH1 */
/*
* Stores a BIGNUM in the buffer in SSH2 format.
*/
int
buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value)
{
u_int bytes;
u_char *buf;
int oi;
u_int hasnohigh = 0;
int ret;
if (BN_is_zero(value)) {
buffer_put_int(buffer, 0);
return 0;
if ((ret = sshbuf_put_bignum2(buffer, value)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
if (value->neg) {
error("buffer_put_bignum2_ret: negative numbers not supported");
return (-1);
}
bytes = BN_num_bytes(value) + 1; /* extra padding byte */
if (bytes < 2) {
error("buffer_put_bignum2_ret: BN too small");
return (-1);
}
buf = xmalloc(bytes);
buf[0] = 0x00;
/* Get the value of in binary */
oi = BN_bn2bin(value, buf+1);
if (oi < 0 || (u_int)oi != bytes - 1) {
error("buffer_put_bignum2_ret: BN_bn2bin() failed: "
"oi %d != bin_size %d", oi, bytes);
xfree(buf);
return (-1);
}
hasnohigh = (buf[1] & 0x80) ? 0 : 1;
buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh);
memset(buf, 0, bytes);
xfree(buf);
return (0);
return 0;
}
void
buffer_put_bignum2(Buffer *buffer, const BIGNUM *value)
{
if (buffer_put_bignum2_ret(buffer, value) == -1)
fatal("buffer_put_bignum2: buffer error");
fatal("%s: buffer error", __func__);
}
int
buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value)
{
u_int len;
u_char *bin;
int ret;
if ((bin = buffer_get_string_ret(buffer, &len)) == NULL) {
error("buffer_get_bignum2_ret: invalid bignum");
return (-1);
if ((ret = sshbuf_get_bignum2(buffer, value)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
if (len > 0 && (bin[0] & 0x80)) {
error("buffer_get_bignum2_ret: negative numbers not supported");
xfree(bin);
return (-1);
}
if (len > 8 * 1024) {
error("buffer_get_bignum2_ret: cannot handle BN of size %d",
len);
xfree(bin);
return (-1);
}
if (BN_bin2bn(bin, len, value) == NULL) {
error("buffer_get_bignum2_ret: BN_bin2bn failed");
xfree(bin);
return (-1);
}
xfree(bin);
return (0);
return 0;
}
void
buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
{
if (buffer_get_bignum2_ret(buffer, value) == -1)
fatal("buffer_get_bignum2: buffer error");
fatal("%s: buffer error", __func__);
}
#endif /* WITH_OPENSSL */

106
bufec.c
View File

@ -1,6 +1,7 @@
/* $OpenBSD: bufec.c,v 1.1 2010/08/31 11:54:45 djm Exp $ */
/* $OpenBSD: bufec.c,v 1.4 2014/04/30 05:29:56 djm Exp $ */
/*
* Copyright (c) 2010 Damien Miller <djm@mindrot.org>
* Copyright (c) 2012 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -15,73 +16,29 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
#ifdef OPENSSL_HAS_ECC
#include "includes.h"
#include <sys/types.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <string.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
#include "ssherr.h"
/*
* Maximum supported EC GFp field length is 528 bits. SEC1 uncompressed
* encoding represents this as two bitstring points that should each
* be no longer than the field length, SEC1 specifies a 1 byte
* point type header.
* Being paranoid here may insulate us to parsing problems in
* EC_POINT_oct2point.
*/
#define BUFFER_MAX_ECPOINT_LEN ((528*2 / 8) + 1)
#ifdef OPENSSL_HAS_ECC
/*
* Append an EC_POINT to the buffer as a string containing a SEC1 encoded
* uncompressed point. Fortunately OpenSSL handles the gory details for us.
*/
int
buffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
const EC_POINT *point)
{
u_char *buf = NULL;
size_t len;
BN_CTX *bnctx;
int ret = -1;
int ret;
/* Determine length */
if ((bnctx = BN_CTX_new()) == NULL)
fatal("%s: BN_CTX_new failed", __func__);
len = EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
NULL, 0, bnctx);
if (len > BUFFER_MAX_ECPOINT_LEN) {
error("%s: giant EC point: len = %lu (max %u)",
__func__, (u_long)len, BUFFER_MAX_ECPOINT_LEN);
goto out;
if ((ret = sshbuf_put_ec(buffer, point, curve)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
/* Convert */
buf = xmalloc(len);
if (EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
buf, len, bnctx) != len) {
error("%s: EC_POINT_point2oct length mismatch", __func__);
goto out;
}
/* Append */
buffer_put_string(buffer, buf, len);
ret = 0;
out:
if (buf != NULL) {
bzero(buf, len);
xfree(buf);
}
BN_CTX_free(bnctx);
return ret;
return 0;
}
void
@ -96,43 +53,13 @@ int
buffer_get_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
EC_POINT *point)
{
u_char *buf;
u_int len;
BN_CTX *bnctx;
int ret = -1;
int ret;
if ((buf = buffer_get_string_ret(buffer, &len)) == NULL) {
error("%s: invalid point", __func__);
if ((ret = sshbuf_get_ec(buffer, point, curve)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
if ((bnctx = BN_CTX_new()) == NULL)
fatal("%s: BN_CTX_new failed", __func__);
if (len > BUFFER_MAX_ECPOINT_LEN) {
error("%s: EC_POINT too long: %u > max %u", __func__,
len, BUFFER_MAX_ECPOINT_LEN);
goto out;
}
if (len == 0) {
error("%s: EC_POINT buffer is empty", __func__);
goto out;
}
if (buf[0] != POINT_CONVERSION_UNCOMPRESSED) {
error("%s: EC_POINT is in an incorrect form: "
"0x%02x (want 0x%02x)", __func__, buf[0],
POINT_CONVERSION_UNCOMPRESSED);
goto out;
}
if (EC_POINT_oct2point(curve, point, buf, len, bnctx) != 1) {
error("buffer_get_bignum2_ret: BN_bin2bn failed");
goto out;
}
/* EC_POINT_oct2point verifies that the point is on the curve for us */
ret = 0;
out:
BN_CTX_free(bnctx);
bzero(buf, len);
xfree(buf);
return ret;
return 0;
}
void
@ -144,3 +71,4 @@ buffer_get_ecpoint(Buffer *buffer, const EC_GROUP *curve,
}
#endif /* OPENSSL_HAS_ECC */

246
buffer.c
View File

@ -1,252 +1,118 @@
/* $OpenBSD: buffer.c,v 1.32 2010/02/09 03:56:28 djm Exp $ */
/* $OpenBSD: buffer.c,v 1.36 2014/04/30 05:29:56 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Functions for manipulating fifo buffers (that can grow if needed).
* Copyright (c) 2012 Damien Miller <djm@mindrot.org>
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
#include "includes.h"
#include <sys/param.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "buffer.h"
#include "log.h"
#define BUFFER_MAX_CHUNK 0x100000
#define BUFFER_MAX_LEN 0xa00000
#define BUFFER_ALLOCSZ 0x008000
/* Initializes the buffer structure. */
void
buffer_init(Buffer *buffer)
{
const u_int len = 4096;
buffer->alloc = 0;
buffer->buf = xmalloc(len);
buffer->alloc = len;
buffer->offset = 0;
buffer->end = 0;
}
/* Frees any memory used for the buffer. */
void
buffer_free(Buffer *buffer)
{
if (buffer->alloc > 0) {
memset(buffer->buf, 0, buffer->alloc);
buffer->alloc = 0;
xfree(buffer->buf);
}
}
/*
* Clears any data from the buffer, making it empty. This does not actually
* zero the memory.
*/
void
buffer_clear(Buffer *buffer)
{
buffer->offset = 0;
buffer->end = 0;
}
/* Appends data to the buffer, expanding it if necessary. */
#include "ssherr.h"
void
buffer_append(Buffer *buffer, const void *data, u_int len)
{
void *p;
p = buffer_append_space(buffer, len);
memcpy(p, data, len);
}
int ret;
static int
buffer_compact(Buffer *buffer)
{
/*
* If the buffer is quite empty, but all data is at the end, move the
* data to the beginning.
*/
if (buffer->offset > MIN(buffer->alloc, BUFFER_MAX_CHUNK)) {
memmove(buffer->buf, buffer->buf + buffer->offset,
buffer->end - buffer->offset);
buffer->end -= buffer->offset;
buffer->offset = 0;
return (1);
}
return (0);
if ((ret = sshbuf_put(buffer, data, len)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
}
/*
* 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, u_int len)
{
u_int newlen;
void *p;
int ret;
u_char *p;
if (len > BUFFER_MAX_CHUNK)
fatal("buffer_append_space: len %u not supported", 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) {
p = buffer->buf + buffer->end;
buffer->end += len;
return p;
}
/* Compact data back to the start of the buffer if necessary */
if (buffer_compact(buffer))
goto restart;
/* Increase the size of the buffer and retry. */
newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ);
if (newlen > BUFFER_MAX_LEN)
fatal("buffer_append_space: alloc %u not supported",
newlen);
buffer->buf = xrealloc(buffer->buf, 1, newlen);
buffer->alloc = newlen;
goto restart;
/* NOTREACHED */
if ((ret = sshbuf_reserve(buffer, len, &p)) != 0)
fatal("%s: %s", __func__, ssh_err(ret));
return p;
}
/*
* Check whether an allocation of 'len' will fit in the buffer
* This must follow the same math as buffer_append_space
*/
int
buffer_check_alloc(Buffer *buffer, u_int len)
{
if (buffer->offset == buffer->end) {
buffer->offset = 0;
buffer->end = 0;
}
restart:
if (buffer->end + len < buffer->alloc)
return (1);
if (buffer_compact(buffer))
goto restart;
if (roundup(buffer->alloc + len, BUFFER_ALLOCSZ) <= BUFFER_MAX_LEN)
return (1);
return (0);
int ret = sshbuf_check_reserve(buffer, len);
if (ret == 0)
return 1;
if (ret == SSH_ERR_NO_BUFFER_SPACE)
return 0;
fatal("%s: %s", __func__, ssh_err(ret));
}
/* Returns the number of bytes of data in the buffer. */
u_int
buffer_len(const Buffer *buffer)
{
return buffer->end - buffer->offset;
}
/* Gets data from the beginning of the buffer. */
int
buffer_get_ret(Buffer *buffer, void *buf, u_int len)
{
if (len > buffer->end - buffer->offset) {
error("buffer_get_ret: trying to get more bytes %d than in buffer %d",
len, buffer->end - buffer->offset);
return (-1);
int ret;
if ((ret = sshbuf_get(buffer, buf, len)) != 0) {
error("%s: %s", __func__, ssh_err(ret));
return -1;
}
memcpy(buf, buffer->buf + buffer->offset, len);
buffer->offset += len;
return (0);
return 0;
}
void
buffer_get(Buffer *buffer, void *buf, u_int len)
{
if (buffer_get_ret(buffer, buf, len) == -1)
fatal("buffer_get: buffer error");
fatal("%s: buffer error", __func__);
}
/* Consumes the given number of bytes from the beginning of the buffer. */
int
buffer_consume_ret(Buffer *buffer, u_int bytes)
{
if (bytes > buffer->end - buffer->offset) {
error("buffer_consume_ret: trying to get more bytes than in buffer");
return (-1);
}
buffer->offset += bytes;
return (0);
int ret = sshbuf_consume(buffer, bytes);
if (ret == 0)
return 0;
if (ret == SSH_ERR_MESSAGE_INCOMPLETE)
return -1;
fatal("%s: %s", __func__, ssh_err(ret));
}
void
buffer_consume(Buffer *buffer, u_int bytes)
{
if (buffer_consume_ret(buffer, bytes) == -1)
fatal("buffer_consume: buffer error");
fatal("%s: buffer error", __func__);
}
/* Consumes the given number of bytes from the end of the buffer. */
int
buffer_consume_end_ret(Buffer *buffer, u_int bytes)
{
if (bytes > buffer->end - buffer->offset)
return (-1);
buffer->end -= bytes;
return (0);
int ret = sshbuf_consume_end(buffer, bytes);
if (ret == 0)
return 0;
if (ret == SSH_ERR_MESSAGE_INCOMPLETE)
return -1;
fatal("%s: %s", __func__, ssh_err(ret));
}
void
buffer_consume_end(Buffer *buffer, u_int bytes)
{
if (buffer_consume_end_ret(buffer, bytes) == -1)
fatal("buffer_consume_end: trying to get more bytes than in buffer");
fatal("%s: buffer error", __func__);
}
/* Returns a pointer to the first used byte in the buffer. */
void *
buffer_ptr(const Buffer *buffer)
{
return buffer->buf + buffer->offset;
}
/* Dumps the contents of the buffer to stderr. */
void
buffer_dump(const Buffer *buffer)
{
u_int i;
u_char *ucp = buffer->buf;
for (i = buffer->offset; i < buffer->end; i++) {
fprintf(stderr, "%02x", ucp[i]);
if ((i-buffer->offset)%16==15)
fprintf(stderr, "\r\n");
else if ((i-buffer->offset)%2==1)
fprintf(stderr, " ");
}
fprintf(stderr, "\r\n");
}

View File

@ -1,57 +1,59 @@
/* $OpenBSD: buffer.h,v 1.21 2010/08/31 11:54:45 djm Exp $ */
/* $OpenBSD: buffer.h,v 1.25 2014/04/30 05:29:56 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Code for manipulating FIFO buffers.
* Copyright (c) 2012 Damien Miller <djm@mindrot.org>
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
#ifndef BUFFER_H
#define BUFFER_H
typedef struct {
u_char *buf; /* Buffer for data. */
u_int alloc; /* Number of bytes allocated for data. */
u_int offset; /* Offset of first byte containing data. */
u_int end; /* Offset of last byte containing data. */
} Buffer;
#include "sshbuf.h"
void buffer_init(Buffer *);
void buffer_clear(Buffer *);
void buffer_free(Buffer *);
typedef struct sshbuf Buffer;
u_int buffer_len(const Buffer *);
void *buffer_ptr(const Buffer *);
#define buffer_init(b) sshbuf_init(b)
#define buffer_clear(b) sshbuf_reset(b)
#define buffer_free(b) sshbuf_free(b)
#define buffer_dump(b) sshbuf_dump(b, stderr)
/* XXX cast is safe: sshbuf never stores more than len 2^31 */
#define buffer_len(b) ((u_int) sshbuf_len(b))
#define buffer_ptr(b) sshbuf_mutable_ptr(b)
void buffer_append(Buffer *, const void *, u_int);
void *buffer_append_space(Buffer *, u_int);
int buffer_check_alloc(Buffer *, u_int);
void buffer_get(Buffer *, void *, u_int);
void buffer_consume(Buffer *, u_int);
void buffer_consume_end(Buffer *, u_int);
void buffer_dump(const Buffer *);
int buffer_get_ret(Buffer *, void *, u_int);
int buffer_consume_ret(Buffer *, u_int);
int buffer_consume_end_ret(Buffer *, u_int);
#include <openssl/objects.h>
#include <openssl/bn.h>
void buffer_put_bignum(Buffer *, const BIGNUM *);
void buffer_put_bignum2(Buffer *, const BIGNUM *);
void buffer_get_bignum(Buffer *, BIGNUM *);
void buffer_get_bignum2(Buffer *, BIGNUM *);
void buffer_put_bignum2_from_string(Buffer *, const u_char *, u_int);
u_short buffer_get_short(Buffer *);
void buffer_put_short(Buffer *, u_short);
@ -66,7 +68,7 @@ int buffer_get_char(Buffer *);
void buffer_put_char(Buffer *, int);
void *buffer_get_string(Buffer *, u_int *);
void *buffer_get_string_ptr(Buffer *, u_int *);
const void *buffer_get_string_ptr(Buffer *, u_int *);
void buffer_put_string(Buffer *, const void *, u_int);
char *buffer_get_cstring(Buffer *, u_int *);
void buffer_put_cstring(Buffer *, const char *);
@ -79,8 +81,7 @@ void buffer_put_cstring(Buffer *, const char *);
#endif /* WIN32_FIXME */
#define buffer_skip_string(b) \
do { u_int l = buffer_get_int(b); buffer_consume(b, l); } while (0)
#define buffer_skip_string(b) (void)buffer_get_string_ptr(b, NULL);
int buffer_put_bignum_ret(Buffer *, const BIGNUM *);
int buffer_get_bignum_ret(Buffer *, BIGNUM *);
@ -91,16 +92,16 @@ int buffer_get_int_ret(u_int *, Buffer *);
int buffer_get_int64_ret(u_int64_t *, Buffer *);
void *buffer_get_string_ret(Buffer *, u_int *);
char *buffer_get_cstring_ret(Buffer *, u_int *);
void *buffer_get_string_ptr_ret(Buffer *, u_int *);
const void *buffer_get_string_ptr_ret(Buffer *, u_int *);
int buffer_get_char_ret(char *, Buffer *);
#ifdef OPENSSL_HAS_ECC
#include <openssl/ec.h>
int buffer_put_ecpoint_ret(Buffer *, const EC_GROUP *, const EC_POINT *);
void buffer_put_ecpoint(Buffer *, const EC_GROUP *, const EC_POINT *);
int buffer_get_ecpoint_ret(Buffer *, const EC_GROUP *, EC_POINT *);
void buffer_get_ecpoint(Buffer *, const EC_GROUP *, EC_POINT *);
#endif
#endif /* BUFFER_H */
#endif /* BUFFER_H */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: canohost.c,v 1.66 2010/01/13 01:20:20 dtucker Exp $ */
/* $OpenBSD: canohost.c,v 1.72 2015/03/01 15:44:40 millert Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -16,11 +16,11 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
@ -41,14 +41,13 @@ static int cached_port = -1;
/*
* Return the canonical name of the host at the other end of the socket. The
* caller should free the returned string with xfree.
* caller should free the returned string.
*/
static char *
get_remote_hostname(int sock, int use_dns)
{
struct sockaddr_storage from;
int i;
socklen_t fromlen;
struct addrinfo hints, *ai, *aitop;
char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
@ -99,13 +98,9 @@ get_remote_hostname(int sock, int use_dns)
return xstrdup(ntop);
}
/*
* 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] = (char)tolower(name[i]);
/* Names are stores in lowercase. */
lowercase(name);
/*
* Map it back to an IP address and check that the given
* address actually is an address of this host. This is
@ -160,8 +155,7 @@ check_ip_options(int sock, char *ipaddr)
#ifdef IP_OPTIONS
u_char options[200];
char text[sizeof(options) * 3 + 1];
socklen_t option_size;
u_int i;
socklen_t option_size, i;
int ipproto;
struct protoent *ip;
@ -199,7 +193,7 @@ ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len)
memcpy(&inaddr, ((char *)&a6->sin6_addr) + 12, sizeof(inaddr));
port = a6->sin6_port;
bzero(a4, sizeof(*a4));
memset(a4, 0, sizeof(*a4));
a4->sin_family = AF_INET;
*len = sizeof(*a4);
@ -266,19 +260,29 @@ get_socket_address(int sock, int remote, int flags)
}
/* Work around Linux IPv6 weirdness */
if (addr.ss_family == AF_INET6)
if (addr.ss_family == AF_INET6) {
addrlen = sizeof(struct sockaddr_in6);
ipv64_normalise_mapped(&addr, &addrlen);
}
ipv64_normalise_mapped(&addr, &addrlen);
/* Get the address in ascii. */
if ((r = getnameinfo((struct sockaddr *)&addr, addrlen, ntop,
sizeof(ntop), NULL, 0, flags)) != 0) {
error("get_socket_address: getnameinfo %d failed: %s", flags,
ssh_gai_strerror(r));
switch (addr.ss_family) {
case AF_INET:
case AF_INET6:
/* Get the address in ascii. */
if ((r = getnameinfo((struct sockaddr *)&addr, addrlen, ntop,
sizeof(ntop), NULL, 0, flags)) != 0) {
error("get_socket_address: getnameinfo %d failed: %s",
flags, ssh_gai_strerror(r));
return NULL;
}
return xstrdup(ntop);
case AF_UNIX:
/* Get the Unix domain socket path. */
return xstrdup(((struct sockaddr_un *)&addr)->sun_path);
default:
/* We can't look up remote Unix domain sockets. */
return NULL;
}
return xstrdup(ntop);
}
char *
@ -323,10 +327,8 @@ get_local_name(int fd)
void
clear_cached_addr(void)
{
if (canonical_host_ip != NULL) {
xfree(canonical_host_ip);
canonical_host_ip = NULL;
}
free(canonical_host_ip);
canonical_host_ip = NULL;
cached_port = -1;
}
@ -393,6 +395,10 @@ get_sock_port(int sock, int local)
if (from.ss_family == AF_INET6)
fromlen = sizeof(struct sockaddr_in6);
/* Non-inet sockets don't have a port number. */
if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
return 0;
/* Return port number. */
if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
strport, sizeof(strport), NI_NUMERICSERV)) != 0)

219
chacha.c Normal file
View File

@ -0,0 +1,219 @@
/*
chacha-merged.c version 20080118
D. J. Bernstein
Public domain.
*/
#include "includes.h"
#include "chacha.h"
/* $OpenBSD: chacha.c,v 1.1 2013/11/21 00:45:44 djm Exp $ */
typedef unsigned char u8;
typedef unsigned int u32;
typedef struct chacha_ctx chacha_ctx;
#define U8C(v) (v##U)
#define U32C(v) (v##U)
#define U8V(v) ((u8)(v) & U8C(0xFF))
#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
#define ROTL32(v, n) \
(U32V((v) << (n)) | ((v) >> (32 - (n))))
#define U8TO32_LITTLE(p) \
(((u32)((p)[0]) ) | \
((u32)((p)[1]) << 8) | \
((u32)((p)[2]) << 16) | \
((u32)((p)[3]) << 24))
#define U32TO8_LITTLE(p, v) \
do { \
(p)[0] = U8V((v) ); \
(p)[1] = U8V((v) >> 8); \
(p)[2] = U8V((v) >> 16); \
(p)[3] = U8V((v) >> 24); \
} while (0)
#define ROTATE(v,c) (ROTL32(v,c))
#define XOR(v,w) ((v) ^ (w))
#define PLUS(v,w) (U32V((v) + (w)))
#define PLUSONE(v) (PLUS((v),1))
#define QUARTERROUND(a,b,c,d) \
a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
static const char sigma[16] = "expand 32-byte k";
static const char tau[16] = "expand 16-byte k";
void
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
{
const char *constants;
x->input[4] = U8TO32_LITTLE(k + 0);
x->input[5] = U8TO32_LITTLE(k + 4);
x->input[6] = U8TO32_LITTLE(k + 8);
x->input[7] = U8TO32_LITTLE(k + 12);
if (kbits == 256) { /* recommended */
k += 16;
constants = sigma;
} else { /* kbits == 128 */
constants = tau;
}
x->input[8] = U8TO32_LITTLE(k + 0);
x->input[9] = U8TO32_LITTLE(k + 4);
x->input[10] = U8TO32_LITTLE(k + 8);
x->input[11] = U8TO32_LITTLE(k + 12);
x->input[0] = U8TO32_LITTLE(constants + 0);
x->input[1] = U8TO32_LITTLE(constants + 4);
x->input[2] = U8TO32_LITTLE(constants + 8);
x->input[3] = U8TO32_LITTLE(constants + 12);
}
void
chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter)
{
x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4);
x->input[14] = U8TO32_LITTLE(iv + 0);
x->input[15] = U8TO32_LITTLE(iv + 4);
}
void
chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
{
u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
u8 *ctarget = NULL;
u8 tmp[64];
u_int i;
if (!bytes) return;
j0 = x->input[0];
j1 = x->input[1];
j2 = x->input[2];
j3 = x->input[3];
j4 = x->input[4];
j5 = x->input[5];
j6 = x->input[6];
j7 = x->input[7];
j8 = x->input[8];
j9 = x->input[9];
j10 = x->input[10];
j11 = x->input[11];
j12 = x->input[12];
j13 = x->input[13];
j14 = x->input[14];
j15 = x->input[15];
for (;;) {
if (bytes < 64) {
for (i = 0;i < bytes;++i) tmp[i] = m[i];
m = tmp;
ctarget = c;
c = tmp;
}
x0 = j0;
x1 = j1;
x2 = j2;
x3 = j3;
x4 = j4;
x5 = j5;
x6 = j6;
x7 = j7;
x8 = j8;
x9 = j9;
x10 = j10;
x11 = j11;
x12 = j12;
x13 = j13;
x14 = j14;
x15 = j15;
for (i = 20;i > 0;i -= 2) {
QUARTERROUND( x0, x4, x8,x12)
QUARTERROUND( x1, x5, x9,x13)
QUARTERROUND( x2, x6,x10,x14)
QUARTERROUND( x3, x7,x11,x15)
QUARTERROUND( x0, x5,x10,x15)
QUARTERROUND( x1, x6,x11,x12)
QUARTERROUND( x2, x7, x8,x13)
QUARTERROUND( x3, x4, x9,x14)
}
x0 = PLUS(x0,j0);
x1 = PLUS(x1,j1);
x2 = PLUS(x2,j2);
x3 = PLUS(x3,j3);
x4 = PLUS(x4,j4);
x5 = PLUS(x5,j5);
x6 = PLUS(x6,j6);
x7 = PLUS(x7,j7);
x8 = PLUS(x8,j8);
x9 = PLUS(x9,j9);
x10 = PLUS(x10,j10);
x11 = PLUS(x11,j11);
x12 = PLUS(x12,j12);
x13 = PLUS(x13,j13);
x14 = PLUS(x14,j14);
x15 = PLUS(x15,j15);
x0 = XOR(x0,U8TO32_LITTLE(m + 0));
x1 = XOR(x1,U8TO32_LITTLE(m + 4));
x2 = XOR(x2,U8TO32_LITTLE(m + 8));
x3 = XOR(x3,U8TO32_LITTLE(m + 12));
x4 = XOR(x4,U8TO32_LITTLE(m + 16));
x5 = XOR(x5,U8TO32_LITTLE(m + 20));
x6 = XOR(x6,U8TO32_LITTLE(m + 24));
x7 = XOR(x7,U8TO32_LITTLE(m + 28));
x8 = XOR(x8,U8TO32_LITTLE(m + 32));
x9 = XOR(x9,U8TO32_LITTLE(m + 36));
x10 = XOR(x10,U8TO32_LITTLE(m + 40));
x11 = XOR(x11,U8TO32_LITTLE(m + 44));
x12 = XOR(x12,U8TO32_LITTLE(m + 48));
x13 = XOR(x13,U8TO32_LITTLE(m + 52));
x14 = XOR(x14,U8TO32_LITTLE(m + 56));
x15 = XOR(x15,U8TO32_LITTLE(m + 60));
j12 = PLUSONE(j12);
if (!j12) {
j13 = PLUSONE(j13);
/* stopping at 2^70 bytes per nonce is user's responsibility */
}
U32TO8_LITTLE(c + 0,x0);
U32TO8_LITTLE(c + 4,x1);
U32TO8_LITTLE(c + 8,x2);
U32TO8_LITTLE(c + 12,x3);
U32TO8_LITTLE(c + 16,x4);
U32TO8_LITTLE(c + 20,x5);
U32TO8_LITTLE(c + 24,x6);
U32TO8_LITTLE(c + 28,x7);
U32TO8_LITTLE(c + 32,x8);
U32TO8_LITTLE(c + 36,x9);
U32TO8_LITTLE(c + 40,x10);
U32TO8_LITTLE(c + 44,x11);
U32TO8_LITTLE(c + 48,x12);
U32TO8_LITTLE(c + 52,x13);
U32TO8_LITTLE(c + 56,x14);
U32TO8_LITTLE(c + 60,x15);
if (bytes <= 64) {
if (bytes < 64) {
for (i = 0;i < bytes;++i) ctarget[i] = c[i];
}
x->input[12] = j12;
x->input[13] = j13;
return;
}
bytes -= 64;
c += 64;
m += 64;
}
}

35
chacha.h Normal file
View File

@ -0,0 +1,35 @@
/* $OpenBSD: chacha.h,v 1.3 2014/05/02 03:27:54 djm Exp $ */
/*
chacha-merged.c version 20080118
D. J. Bernstein
Public domain.
*/
#ifndef CHACHA_H
#define CHACHA_H
#include <sys/types.h>
struct chacha_ctx {
u_int input[16];
};
#define CHACHA_MINKEYLEN 16
#define CHACHA_NONCELEN 8
#define CHACHA_CTRLEN 8
#define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN)
#define CHACHA_BLOCKLEN 64
void chacha_keysetup(struct chacha_ctx *x, const u_char *k, u_int kbits)
__attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN)));
void chacha_ivsetup(struct chacha_ctx *x, const u_char *iv, const u_char *ctr)
__attribute__((__bounded__(__minbytes__, 2, CHACHA_NONCELEN)))
__attribute__((__bounded__(__minbytes__, 3, CHACHA_CTRLEN)));
void chacha_encrypt_bytes(struct chacha_ctx *x, const u_char *m,
u_char *c, u_int bytes)
__attribute__((__bounded__(__buffer__, 2, 4)))
__attribute__((__bounded__(__buffer__, 3, 4)));
#endif /* CHACHA_H */

1248
channels.c

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.h,v 1.105 2011/06/22 22:08:42 djm Exp $ */
/* $OpenBSD: channels.h,v 1.118 2015/07/01 02:26:31 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -55,7 +55,12 @@
#define SSH_CHANNEL_ZOMBIE 14 /* Almost dead. */
#define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */
#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */
#define SSH_CHANNEL_MAX_TYPE 17
#define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */
#define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */
#define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */
#define SSH_CHANNEL_MAX_TYPE 20
#define CHANNEL_CANCEL_PORT_STATIC -1
struct Channel;
typedef struct Channel Channel;
@ -100,14 +105,17 @@ struct Channel {
int sock; /* sock fd */
int ctl_chan; /* control channel (multiplexed connections) */
int isatty; /* rfd is a tty */
#ifdef _AIX
int wfd_isatty; /* wfd is a tty */
#endif
int client_tty; /* (client) TTY has been requested */
int force_drain; /* force close on iEOF */
time_t notbefore; /* Pause IO until deadline (time_t) */
int delayed; /* post-select handlers for newly created
* channels are delayed until the first call
* to a matching pre-select handler.
* to a matching pre-select handler.
* this way post-select handlers are not
* accidenly called if a FD gets reused */
* accidentally called if a FD gets reused */
Buffer input; /* data read from socket, to be sent over
* encrypted connection */
Buffer output; /* data received over encrypted connection for
@ -116,6 +124,7 @@ struct Channel {
char *path;
/* path for unix domain sockets, or host name for forwards */
int listening_port; /* port being listened for forwards */
char *listening_addr; /* addr being listened for forwards */
int host_port; /* remote port to connect for forwards */
char *remote_name; /* remote hostname */
@ -221,21 +230,22 @@ void channel_send_window_changes(void);
/* protocol handler */
void channel_input_close(int, u_int32_t, void *);
void channel_input_close_confirmation(int, u_int32_t, void *);
void channel_input_data(int, u_int32_t, void *);
void channel_input_extended_data(int, u_int32_t, void *);
void channel_input_ieof(int, u_int32_t, void *);
void channel_input_oclose(int, u_int32_t, void *);
void channel_input_open_confirmation(int, u_int32_t, void *);
void channel_input_open_failure(int, u_int32_t, void *);
void channel_input_port_open(int, u_int32_t, void *);
void channel_input_window_adjust(int, u_int32_t, void *);
void channel_input_status_confirm(int, u_int32_t, void *);
int channel_input_close(int, u_int32_t, void *);
int channel_input_close_confirmation(int, u_int32_t, void *);
int channel_input_data(int, u_int32_t, void *);
int channel_input_extended_data(int, u_int32_t, void *);
int channel_input_ieof(int, u_int32_t, void *);
int channel_input_oclose(int, u_int32_t, void *);
int channel_input_open_confirmation(int, u_int32_t, void *);
int channel_input_open_failure(int, u_int32_t, void *);
int channel_input_port_open(int, u_int32_t, void *);
int channel_input_window_adjust(int, u_int32_t, void *);
int channel_input_status_confirm(int, u_int32_t, void *);
/* file descriptor handling (read/write) */
void channel_prepare_select(fd_set **, fd_set **, int *, u_int*, int);
void channel_prepare_select(fd_set **, fd_set **, int *, u_int*,
time_t*, int);
void channel_after_select(fd_set *, fd_set *);
void channel_output_poll(void);
@ -246,33 +256,41 @@ char *channel_open_message(void);
int channel_find_open(void);
/* tcp forwarding */
struct Forward;
struct ForwardOptions;
void channel_set_af(int af);
void channel_permit_all_opens(void);
void channel_add_permitted_opens(char *, int);
int channel_add_adm_permitted_opens(char *, int);
void channel_disable_adm_local_opens(void);
void channel_update_permitted_opens(int, int);
void channel_clear_permitted_opens(void);
void channel_clear_adm_permitted_opens(void);
void channel_print_adm_permitted_opens(void);
int channel_input_port_forward_request(int, int);
Channel *channel_connect_to(const char *, u_short, char *, char *);
int channel_input_port_forward_request(int, struct ForwardOptions *);
Channel *channel_connect_to_port(const char *, u_short, char *, char *);
Channel *channel_connect_to_path(const char *, char *, char *);
Channel *channel_connect_stdio_fwd(const char*, u_short, int, int);
Channel *channel_connect_by_listen_address(u_short, char *, char *);
int channel_request_remote_forwarding(const char *, u_short,
const char *, u_short);
int channel_setup_local_fwd_listener(const char *, u_short,
const char *, u_short, int);
void channel_request_rforward_cancel(const char *host, u_short port);
int channel_setup_remote_fwd_listener(const char *, u_short, int *, int);
int channel_cancel_rport_listener(const char *, u_short);
Channel *channel_connect_by_listen_address(const char *, u_short,
char *, char *);
Channel *channel_connect_by_listen_path(const char *, char *, char *);
int channel_request_remote_forwarding(struct Forward *);
int channel_setup_local_fwd_listener(struct Forward *, struct ForwardOptions *);
int channel_request_rforward_cancel(struct Forward *);
int channel_setup_remote_fwd_listener(struct Forward *, int *, struct ForwardOptions *);
int channel_cancel_rport_listener(struct Forward *);
int channel_cancel_lport_listener(struct Forward *, int, struct ForwardOptions *);
int permitopen_port(const char *);
/* x11 forwarding */
void channel_set_x11_refuse_time(u_int);
int x11_connect_display(void);
int x11_create_display_inet(int, int, int, u_int *, int **);
void x11_input_open(int, u_int32_t, void *);
int x11_input_open(int, u_int32_t, void *);
void x11_request_forwarding_with_spoofing(int, const char *, const char *,
const char *, int);
void deny_input_open(int, u_int32_t, void *);
int deny_input_open(int, u_int32_t, void *);
/* agent forwarding */

View File

@ -1,15 +1,10 @@
/* $OpenBSD: cipher-3des1.c,v 1.7 2010/10/01 23:05:32 djm Exp $ */
/* $OpenBSD: cipher-3des1.c,v 1.12 2015/01/14 10:24:42 markus Exp $ */
/*
* Copyright (c) 2003 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@ -26,16 +21,10 @@
#include "includes.h"
#include <sys/types.h>
#include <string.h>
#include <openssl/evp.h>
#include <stdarg.h>
#include <string.h>
#include "xmalloc.h"
#include "log.h"
#include "openbsd-compat/openssl-compat.h"
#include "ssherr.h"
/*
* This is used by SSH1:
@ -57,7 +46,7 @@ struct ssh1_3des_ctx
};
const EVP_CIPHER * evp_ssh1_3des(void);
void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
static int
ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
@ -67,11 +56,12 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
u_char *k1, *k2, *k3;
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
c = xmalloc(sizeof(*c));
if ((c = calloc(1, sizeof(*c))) == NULL)
return 0;
EVP_CIPHER_CTX_set_app_data(ctx, c);
}
if (key == NULL)
return (1);
return 1;
if (enc == -1)
enc = ctx->encrypt;
k1 = k2 = k3 = (u_char *) key;
@ -85,44 +75,29 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
EVP_CIPHER_CTX_init(&c->k1);
EVP_CIPHER_CTX_init(&c->k2);
EVP_CIPHER_CTX_init(&c->k3);
#ifdef SSH_OLD_EVP
EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc);
EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc);
EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc);
#else
if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
memset(c, 0, sizeof(*c));
xfree(c);
explicit_bzero(c, sizeof(*c));
free(c);
EVP_CIPHER_CTX_set_app_data(ctx, NULL);
return (0);
return 0;
}
#endif
return (1);
return 1;
}
static int
ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
LIBCRYPTO_EVP_INL_TYPE len)
ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, size_t len)
{
struct ssh1_3des_ctx *c;
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
error("ssh1_3des_cbc: no context");
return (0);
}
#ifdef SSH_OLD_EVP
EVP_Cipher(&c->k1, dest, (u_char *)src, len);
EVP_Cipher(&c->k2, dest, dest, len);
EVP_Cipher(&c->k3, dest, dest, len);
#else
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
return 0;
if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
EVP_Cipher(&c->k3, dest, dest, len) == 0)
return (0);
#endif
return (1);
return 0;
return 1;
}
static int
@ -134,33 +109,32 @@ ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
EVP_CIPHER_CTX_cleanup(&c->k1);
EVP_CIPHER_CTX_cleanup(&c->k2);
EVP_CIPHER_CTX_cleanup(&c->k3);
memset(c, 0, sizeof(*c));
xfree(c);
explicit_bzero(c, sizeof(*c));
free(c);
EVP_CIPHER_CTX_set_app_data(ctx, NULL);
}
return (1);
return 1;
}
void
int
ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
{
struct ssh1_3des_ctx *c;
if (len != 24)
fatal("%s: bad 3des iv length: %d", __func__, len);
return SSH_ERR_INVALID_ARGUMENT;
if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
fatal("%s: no 3des context", __func__);
return SSH_ERR_INTERNAL_ERROR;
if (doset) {
debug3("%s: Installed 3DES IV", __func__);
memcpy(c->k1.iv, iv, 8);
memcpy(c->k2.iv, iv + 8, 8);
memcpy(c->k3.iv, iv + 16, 8);
} else {
debug3("%s: Copying 3DES IV", __func__);
memcpy(iv, c->k1.iv, 8);
memcpy(iv + 8, c->k2.iv, 8);
memcpy(iv + 16, c->k3.iv, 8);
}
return 0;
}
const EVP_CIPHER *
@ -168,7 +142,7 @@ evp_ssh1_3des(void)
{
static EVP_CIPHER ssh1_3des;
memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
memset(&ssh1_3des, 0, sizeof(ssh1_3des));
ssh1_3des.nid = NID_undef;
ssh1_3des.block_size = 8;
ssh1_3des.iv_len = 0;
@ -176,8 +150,6 @@ evp_ssh1_3des(void)
ssh1_3des.init = ssh1_3des_init;
ssh1_3des.cleanup = ssh1_3des_cleanup;
ssh1_3des.do_cipher = ssh1_3des_cbc;
#ifndef SSH_OLD_EVP
ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
#endif
return (&ssh1_3des);
return &ssh1_3des;
}

View File

@ -46,9 +46,6 @@ struct ssh_rijndael_ctx
u_char r_iv[RIJNDAEL_BLOCKSIZE];
};
const EVP_CIPHER * evp_rijndael(void);
void ssh_rijndael_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
static int
ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
int enc)
@ -123,7 +120,7 @@ ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx)
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
memset(c, 0, sizeof(*c));
xfree(c);
free(c);
EVP_CIPHER_CTX_set_app_data(ctx, NULL);
}
return (1);

83
cipher-aesctr.c Normal file
View File

@ -0,0 +1,83 @@
/* $OpenBSD: cipher-aesctr.c,v 1.2 2015/01/14 10:24:42 markus Exp $ */
/*
* Copyright (c) 2003 Markus Friedl. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#include <string.h>
#ifndef WITH_OPENSSL
#include "cipher-aesctr.h"
/*
* increment counter 'ctr',
* the counter is of size 'len' bytes and stored in network-byte-order.
* (LSB at ctr[len-1], MSB at ctr[0])
*/
static inline void
aesctr_inc(u8 *ctr, u32 len)
{
ssize_t i;
#ifndef CONSTANT_TIME_INCREMENT
for (i = len - 1; i >= 0; i--)
if (++ctr[i]) /* continue on overflow */
return;
#else
u8 x, add = 1;
for (i = len - 1; i >= 0; i--) {
ctr[i] += add;
/* constant time for: x = ctr[i] ? 1 : 0 */
x = ctr[i];
x = (x | (x >> 4)) & 0xf;
x = (x | (x >> 2)) & 0x3;
x = (x | (x >> 1)) & 0x1;
add *= (x^1);
}
#endif
}
void
aesctr_keysetup(aesctr_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
{
x->rounds = rijndaelKeySetupEnc(x->ek, k, kbits);
}
void
aesctr_ivsetup(aesctr_ctx *x,const u8 *iv)
{
memcpy(x->ctr, iv, AES_BLOCK_SIZE);
}
void
aesctr_encrypt_bytes(aesctr_ctx *x,const u8 *m,u8 *c,u32 bytes)
{
u32 n = 0;
u8 buf[AES_BLOCK_SIZE];
while ((bytes--) > 0) {
if (n == 0) {
rijndaelEncrypt(x->ek, x->rounds, x->ctr, buf);
aesctr_inc(x->ctr, AES_BLOCK_SIZE);
}
*(c++) = *(m++) ^ buf[n];
n = (n + 1) % AES_BLOCK_SIZE;
}
}
#endif /* !WITH_OPENSSL */

35
cipher-aesctr.h Normal file
View File

@ -0,0 +1,35 @@
/* $OpenBSD: cipher-aesctr.h,v 1.1 2014/04/29 15:39:33 markus Exp $ */
/*
* Copyright (c) 2014 Markus Friedl
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef OPENSSH_AESCTR_H
#define OPENSSH_AESCTR_H
#include "rijndael.h"
#define AES_BLOCK_SIZE 16
typedef struct aesctr_ctx {
int rounds; /* keylen-dependent #rounds */
u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */
u8 ctr[AES_BLOCK_SIZE]; /* counter */
} aesctr_ctx;
void aesctr_keysetup(aesctr_ctx *x,const u8 *k,u32 kbits,u32 ivbits);
void aesctr_ivsetup(aesctr_ctx *x,const u8 *iv);
void aesctr_encrypt_bytes(aesctr_ctx *x,const u8 *m,u8 *c,u32 bytes);
#endif

View File

@ -1,15 +1,10 @@
/* $OpenBSD: cipher-bf1.c,v 1.6 2010/10/01 23:05:32 djm Exp $ */
/* $OpenBSD: cipher-bf1.c,v 1.7 2015/01/14 10:24:42 markus Exp $ */
/*
* Copyright (c) 2003 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@ -25,15 +20,14 @@
#include "includes.h"
#include <sys/types.h>
#ifdef WITH_OPENSSL
#include <openssl/evp.h>
#include <sys/types.h>
#include <stdarg.h>
#include <string.h>
#include "xmalloc.h"
#include "log.h"
#include <openssl/evp.h>
#include "openbsd-compat/openssl-compat.h"
@ -106,3 +100,4 @@ evp_ssh1_bf(void)
ssh1_bf.key_len = 32;
return (&ssh1_bf);
}
#endif /* WITH_OPENSSL */

118
cipher-chachapoly.c Normal file
View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $OpenBSD: cipher-chachapoly.c,v 1.7 2015/01/14 10:24:42 markus Exp $ */
#include "includes.h"
#include <sys/types.h>
#include <stdarg.h> /* needed for log.h */
#include <string.h>
#include <stdio.h> /* needed for misc.h */
#include "log.h"
#include "sshbuf.h"
#include "ssherr.h"
#include "cipher-chachapoly.h"
int chachapoly_init(struct chachapoly_ctx *ctx,
const u_char *key, u_int keylen)
{
if (keylen != (32 + 32)) /* 2 x 256 bit keys */
return SSH_ERR_INVALID_ARGUMENT;
chacha_keysetup(&ctx->main_ctx, key, 256);
chacha_keysetup(&ctx->header_ctx, key + 32, 256);
return 0;
}
/*
* chachapoly_crypt() operates as following:
* En/decrypt with header key 'aadlen' bytes from 'src', storing result
* to 'dest'. The ciphertext here is treated as additional authenticated
* data for MAC calculation.
* En/decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. Use
* POLY1305_TAGLEN bytes at offset 'len'+'aadlen' as the authentication
* tag. This tag is written on encryption and verified on decryption.
*/
int
chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
const u_char *src, u_int len, u_int aadlen, u_int authlen, int do_encrypt)
{
u_char seqbuf[8];
const u_char one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];
int r = SSH_ERR_INTERNAL_ERROR;
/*
* Run ChaCha20 once to generate the Poly1305 key. The IV is the
* packet sequence number.
*/
memset(poly_key, 0, sizeof(poly_key));
POKE_U64(seqbuf, seqnr);
chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
chacha_encrypt_bytes(&ctx->main_ctx,
poly_key, poly_key, sizeof(poly_key));
/* If decrypting, check tag before anything else */
if (!do_encrypt) {
const u_char *tag = src + aadlen + len;
poly1305_auth(expected_tag, src, aadlen + len, poly_key);
if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) {
r = SSH_ERR_MAC_INVALID;
goto out;
}
}
/* Crypt additional data */
if (aadlen) {
chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL);
chacha_encrypt_bytes(&ctx->header_ctx, src, dest, aadlen);
}
/* Set Chacha's block counter to 1 */
chacha_ivsetup(&ctx->main_ctx, seqbuf, one);
chacha_encrypt_bytes(&ctx->main_ctx, src + aadlen,
dest + aadlen, len);
/* If encrypting, calculate and append tag */
if (do_encrypt) {
poly1305_auth(dest + aadlen + len, dest, aadlen + len,
poly_key);
}
r = 0;
out:
explicit_bzero(expected_tag, sizeof(expected_tag));
explicit_bzero(seqbuf, sizeof(seqbuf));
explicit_bzero(poly_key, sizeof(poly_key));
return r;
}
/* Decrypt and extract the encrypted packet length */
int
chachapoly_get_length(struct chachapoly_ctx *ctx,
u_int *plenp, u_int seqnr, const u_char *cp, u_int len)
{
u_char buf[4], seqbuf[8];
if (len < 4)
return SSH_ERR_MESSAGE_INCOMPLETE;
POKE_U64(seqbuf, seqnr);
chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL);
chacha_encrypt_bytes(&ctx->header_ctx, cp, buf, 4);
*plenp = PEEK_U32(buf);
return 0;
}

41
cipher-chachapoly.h Normal file
View File

@ -0,0 +1,41 @@
/* $OpenBSD: cipher-chachapoly.h,v 1.4 2014/06/24 01:13:21 djm Exp $ */
/*
* Copyright (c) Damien Miller 2013 <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef CHACHA_POLY_AEAD_H
#define CHACHA_POLY_AEAD_H
#include <sys/types.h>
#include "chacha.h"
#include "poly1305.h"
#define CHACHA_KEYLEN 32 /* Only 256 bit keys used here */
struct chachapoly_ctx {
struct chacha_ctx main_ctx, header_ctx;
};
int chachapoly_init(struct chachapoly_ctx *cpctx,
const u_char *key, u_int keylen)
__attribute__((__bounded__(__buffer__, 2, 3)));
int chachapoly_crypt(struct chachapoly_ctx *cpctx, u_int seqnr,
u_char *dest, const u_char *src, u_int len, u_int aadlen, u_int authlen,
int do_encrypt);
int chachapoly_get_length(struct chachapoly_ctx *cpctx,
u_int *plenp, u_int seqnr, const u_char *cp, u_int len)
__attribute__((__bounded__(__buffer__, 4, 5)));
#endif /* CHACHA_POLY_AEAD_H */

View File

@ -16,6 +16,7 @@
*/
#include "includes.h"
#if defined(WITH_OPENSSL) && !defined(OPENSSL_HAVE_EVPCTR)
#include <sys/types.h>
#include <stdarg.h>
@ -33,9 +34,6 @@
#include <openssl/aes.h>
#endif
const EVP_CIPHER *evp_aes_128_ctr(void);
void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t);
struct ssh_aes_ctr_ctx
{
AES_KEY aes_ctx;
@ -106,7 +104,7 @@ ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx)
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
memset(c, 0, sizeof(*c));
xfree(c);
free(c);
EVP_CIPHER_CTX_set_app_data(ctx, NULL);
}
return (1);
@ -144,3 +142,5 @@ evp_aes_128_ctr(void)
#endif
return (&aes_ctr);
}
#endif /* defined(WITH_OPENSSL) && !defined(OPENSSL_HAVE_EVPCTR) */

592
cipher.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: cipher.c,v 1.82 2009/01/26 09:58:15 markus Exp $ */
/* $OpenBSD: cipher.c,v 1.100 2015/01/14 10:29:45 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -39,82 +39,162 @@
#include <sys/types.h>
#include <openssl/md5.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "xmalloc.h"
#include "log.h"
#include "cipher.h"
#include "misc.h"
#include "sshbuf.h"
#include "ssherr.h"
#include "digest.h"
/* compatibility with old or broken OpenSSL versions */
#include "openbsd-compat/openssl-compat.h"
#ifdef WITH_SSH1
extern const EVP_CIPHER *evp_ssh1_bf(void);
extern const EVP_CIPHER *evp_ssh1_3des(void);
extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
extern const EVP_CIPHER *evp_aes_128_ctr(void);
extern void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
extern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
#endif
struct Cipher {
struct sshcipher {
char *name;
int number; /* for ssh1 only */
u_int block_size;
u_int key_len;
u_int iv_len; /* defaults to block_size */
u_int auth_len;
u_int discard_len;
u_int cbc_mode;
u_int flags;
#define CFLAG_CBC (1<<0)
#define CFLAG_CHACHAPOLY (1<<1)
#define CFLAG_AESCTR (1<<2)
#define CFLAG_NONE (1<<3)
#ifdef WITH_OPENSSL
const EVP_CIPHER *(*evptype)(void);
} ciphers[] = {
{ "none", SSH_CIPHER_NONE, 8, 0, 0, 0, EVP_enc_null },
{ "des", SSH_CIPHER_DES, 8, 8, 0, 1, EVP_des_cbc },
{ "3des", SSH_CIPHER_3DES, 8, 16, 0, 1, evp_ssh1_3des },
{ "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 1, evp_ssh1_bf },
{ "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 1, EVP_des_ede3_cbc },
{ "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, 0, 1, EVP_bf_cbc },
{ "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, 0, 1, EVP_cast5_cbc },
{ "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, 0, EVP_rc4 },
{ "arcfour128", SSH_CIPHER_SSH2, 8, 16, 1536, 0, EVP_rc4 },
{ "arcfour256", SSH_CIPHER_SSH2, 8, 32, 1536, 0, EVP_rc4 },
{ "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 1, EVP_aes_128_cbc },
{ "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 1, EVP_aes_192_cbc },
{ "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc },
{ "rijndael-cbc@lysator.liu.se",
SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc },
{ "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, evp_aes_128_ctr },
{ "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, evp_aes_128_ctr },
{ "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, evp_aes_128_ctr },
#ifdef USE_CIPHER_ACSS
{ "acss@openssh.org", SSH_CIPHER_SSH2, 16, 5, 0, 0, EVP_acss },
#else
void *ignored;
#endif
{ NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL }
};
static const struct sshcipher ciphers[] = {
#ifdef WITH_SSH1
{ "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc },
{ "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des },
{ "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf },
#endif /* WITH_SSH1 */
#ifdef WITH_OPENSSL
{ "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null },
{ "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc },
{ "blowfish-cbc",
SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc },
{ "cast128-cbc",
SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_cast5_cbc },
{ "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 0, EVP_rc4 },
{ "arcfour128", SSH_CIPHER_SSH2, 8, 16, 0, 0, 1536, 0, EVP_rc4 },
{ "arcfour256", SSH_CIPHER_SSH2, 8, 32, 0, 0, 1536, 0, EVP_rc4 },
{ "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 1, EVP_aes_128_cbc },
{ "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 1, EVP_aes_192_cbc },
{ "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc },
{ "rijndael-cbc@lysator.liu.se",
SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc },
{ "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr },
{ "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr },
{ "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr },
# ifdef OPENSSL_HAVE_EVPGCM
{ "aes128-gcm@openssh.com",
SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm },
{ "aes256-gcm@openssh.com",
SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm },
# endif /* OPENSSL_HAVE_EVPGCM */
#else /* WITH_OPENSSL */
{ "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, CFLAG_AESCTR, NULL },
{ "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, CFLAG_AESCTR, NULL },
{ "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, CFLAG_AESCTR, NULL },
{ "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, CFLAG_NONE, NULL },
#endif /* WITH_OPENSSL */
{ "chacha20-poly1305@openssh.com",
SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL },
{ NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL }
};
/*--*/
/* Returns a comma-separated list of supported ciphers. */
char *
cipher_alg_list(char sep, int auth_only)
{
char *tmp, *ret = NULL;
size_t nlen, rlen = 0;
const struct sshcipher *c;
for (c = ciphers; c->name != NULL; c++) {
if (c->number != SSH_CIPHER_SSH2)
continue;
if (auth_only && c->auth_len == 0)
continue;
if (ret != NULL)
ret[rlen++] = sep;
nlen = strlen(c->name);
if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
free(ret);
return NULL;
}
ret = tmp;
memcpy(ret + rlen, c->name, nlen + 1);
rlen += nlen;
}
return ret;
}
u_int
cipher_blocksize(const Cipher *c)
cipher_blocksize(const struct sshcipher *c)
{
return (c->block_size);
}
u_int
cipher_keylen(const Cipher *c)
cipher_keylen(const struct sshcipher *c)
{
return (c->key_len);
}
u_int
cipher_get_number(const Cipher *c)
cipher_seclen(const struct sshcipher *c)
{
if (strcmp("3des-cbc", c->name) == 0)
return 14;
return cipher_keylen(c);
}
u_int
cipher_authlen(const struct sshcipher *c)
{
return (c->auth_len);
}
u_int
cipher_ivlen(const struct sshcipher *c)
{
/*
* Default is cipher block size, except for chacha20+poly1305 that
* needs no IV. XXX make iv_len == -1 default?
*/
return (c->iv_len != 0 || (c->flags & CFLAG_CHACHAPOLY) != 0) ?
c->iv_len : c->block_size;
}
u_int
cipher_get_number(const struct sshcipher *c)
{
return (c->number);
}
u_int
cipher_is_cbc(const Cipher *c)
cipher_is_cbc(const struct sshcipher *c)
{
return (c->cbc_mode);
return (c->flags & CFLAG_CBC) != 0;
}
u_int
@ -129,20 +209,20 @@ cipher_mask_ssh1(int client)
return mask;
}
Cipher *
const struct sshcipher *
cipher_by_name(const char *name)
{
Cipher *c;
const struct sshcipher *c;
for (c = ciphers; c->name != NULL; c++)
if (strcmp(c->name, name) == 0)
return c;
return NULL;
}
Cipher *
const struct sshcipher *
cipher_by_number(int id)
{
Cipher *c;
const struct sshcipher *c;
for (c = ciphers; c->name != NULL; c++)
if (c->number == id)
return c;
@ -153,26 +233,23 @@ cipher_by_number(int id)
int
ciphers_valid(const char *names)
{
Cipher *c;
const struct sshcipher *c;
char *cipher_list, *cp;
char *p;
if (names == NULL || strcmp(names, "") == 0)
return 0;
cipher_list = cp = xstrdup(names);
if ((cipher_list = cp = strdup(names)) == NULL)
return 0;
for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
(p = strsep(&cp, CIPHER_SEP))) {
c = cipher_by_name(p);
if (c == NULL || c->number != SSH_CIPHER_SSH2) {
debug("bad cipher %s [%s]", p, names);
xfree(cipher_list);
free(cipher_list);
return 0;
} else {
debug3("cipher ok: %s [%s]", p, names);
}
}
debug3("ciphers ok: [%s]", names);
xfree(cipher_list);
free(cipher_list);
return 1;
}
@ -184,7 +261,7 @@ ciphers_valid(const char *names)
int
cipher_number(const char *name)
{
Cipher *c;
const struct sshcipher *c;
if (name == NULL)
return -1;
for (c = ciphers; c->name != NULL; c++)
@ -196,236 +273,385 @@ cipher_number(const char *name)
char *
cipher_name(int id)
{
Cipher *c = cipher_by_number(id);
const struct sshcipher *c = cipher_by_number(id);
return (c==NULL) ? "<unknown>" : c->name;
}
void
cipher_init(CipherContext *cc, Cipher *cipher,
const char *
cipher_warning_message(const struct sshcipher_ctx *cc)
{
if (cc == NULL || cc->cipher == NULL)
return NULL;
if (cc->cipher->number == SSH_CIPHER_DES)
return "use of DES is strongly discouraged due to "
"cryptographic weaknesses";
return NULL;
}
int
cipher_init(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
int do_encrypt)
{
static int dowarn = 1;
#ifdef SSH_OLD_EVP
EVP_CIPHER *type;
#else
#ifdef WITH_OPENSSL
int ret = SSH_ERR_INTERNAL_ERROR;
const EVP_CIPHER *type;
int klen;
#endif
u_char *junk, *discard;
if (cipher->number == SSH_CIPHER_DES) {
if (dowarn) {
error("Warning: use of DES is strongly discouraged "
"due to cryptographic weaknesses");
dowarn = 0;
}
if (keylen > 8)
keylen = 8;
}
#endif
cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
cc->encrypt = do_encrypt;
if (keylen < cipher->key_len ||
(iv != NULL && ivlen < cipher_ivlen(cipher)))
return SSH_ERR_INVALID_ARGUMENT;
if (keylen < cipher->key_len)
fatal("cipher_init: key length %d is insufficient for %s.",
keylen, cipher->name);
if (iv != NULL && ivlen < cipher->block_size)
fatal("cipher_init: iv length %d is insufficient for %s.",
ivlen, cipher->name);
cc->cipher = cipher;
type = (*cipher->evptype)();
EVP_CIPHER_CTX_init(&cc->evp);
#ifdef SSH_OLD_EVP
if (type->key_len > 0 && type->key_len != keylen) {
debug("cipher_init: set keylen (%d -> %d)",
type->key_len, keylen);
type->key_len = keylen;
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
return chachapoly_init(&cc->cp_ctx, key, keylen);
}
EVP_CipherInit(&cc->evp, type, (u_char *)key, (u_char *)iv,
(do_encrypt == CIPHER_ENCRYPT));
#ifndef WITH_OPENSSL
if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen);
aesctr_ivsetup(&cc->ac_ctx, iv);
return 0;
}
if ((cc->cipher->flags & CFLAG_NONE) != 0)
return 0;
return SSH_ERR_INVALID_ARGUMENT;
#else
type = (*cipher->evptype)();
EVP_CIPHER_CTX_init(&cc->evp);
if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv,
(do_encrypt == CIPHER_ENCRYPT)) == 0)
fatal("cipher_init: EVP_CipherInit failed for %s",
cipher->name);
(do_encrypt == CIPHER_ENCRYPT)) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto bad;
}
if (cipher_authlen(cipher) &&
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED,
-1, (u_char *)iv)) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto bad;
}
klen = EVP_CIPHER_CTX_key_length(&cc->evp);
if (klen > 0 && keylen != (u_int)klen) {
debug2("cipher_init: set keylen (%d -> %d)", klen, keylen);
if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0)
fatal("cipher_init: set keylen failed (%d -> %d)",
klen, keylen);
if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto bad;
}
}
if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto bad;
}
if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0)
fatal("cipher_init: EVP_CipherInit: set key failed for %s",
cipher->name);
#endif
if (cipher->discard_len > 0) {
junk = xmalloc(cipher->discard_len);
discard = xmalloc(cipher->discard_len);
if (EVP_Cipher(&cc->evp, discard, junk,
cipher->discard_len) == 0)
fatal("evp_crypt: EVP_Cipher failed during discard");
memset(discard, 0, cipher->discard_len);
xfree(junk);
xfree(discard);
if ((junk = malloc(cipher->discard_len)) == NULL ||
(discard = malloc(cipher->discard_len)) == NULL) {
if (junk != NULL)
free(junk);
ret = SSH_ERR_ALLOC_FAIL;
goto bad;
}
ret = EVP_Cipher(&cc->evp, discard, junk, cipher->discard_len);
explicit_bzero(discard, cipher->discard_len);
free(junk);
free(discard);
if (ret != 1) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
bad:
EVP_CIPHER_CTX_cleanup(&cc->evp);
return ret;
}
}
#endif
return 0;
}
void
cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
/*
* cipher_crypt() operates as following:
* Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'.
* Theses bytes are treated as additional authenticated data for
* authenticated encryption modes.
* En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'.
* Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag.
* This tag is written on encryption and verified on decryption.
* Both 'aadlen' and 'authlen' can be set to 0.
*/
int
cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest,
const u_char *src, u_int len, u_int aadlen, u_int authlen)
{
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src,
len, aadlen, authlen, cc->encrypt);
}
#ifndef WITH_OPENSSL
if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
if (aadlen)
memcpy(dest, src, aadlen);
aesctr_encrypt_bytes(&cc->ac_ctx, src + aadlen,
dest + aadlen, len);
return 0;
}
if ((cc->cipher->flags & CFLAG_NONE) != 0) {
memcpy(dest, src, aadlen + len);
return 0;
}
return SSH_ERR_INVALID_ARGUMENT;
#else
if (authlen) {
u_char lastiv[1];
if (authlen != cipher_authlen(cc->cipher))
return SSH_ERR_INVALID_ARGUMENT;
/* increment IV */
if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN,
1, lastiv))
return SSH_ERR_LIBCRYPTO_ERROR;
/* set tag on decyption */
if (!cc->encrypt &&
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG,
authlen, (u_char *)src + aadlen + len))
return SSH_ERR_LIBCRYPTO_ERROR;
}
if (aadlen) {
if (authlen &&
EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0)
return SSH_ERR_LIBCRYPTO_ERROR;
memcpy(dest, src, aadlen);
}
if (len % cc->cipher->block_size)
fatal("cipher_encrypt: bad plaintext length %d", len);
if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0)
fatal("evp_crypt: EVP_Cipher failed");
return SSH_ERR_INVALID_ARGUMENT;
if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen,
len) < 0)
return SSH_ERR_LIBCRYPTO_ERROR;
if (authlen) {
/* compute tag (on encrypt) or verify tag (on decrypt) */
if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0)
return cc->encrypt ?
SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID;
if (cc->encrypt &&
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG,
authlen, dest + aadlen + len))
return SSH_ERR_LIBCRYPTO_ERROR;
}
return 0;
#endif
}
void
cipher_cleanup(CipherContext *cc)
/* Extract the packet length, including any decryption necessary beforehand */
int
cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr,
const u_char *cp, u_int len)
{
if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed");
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr,
cp, len);
if (len < 4)
return SSH_ERR_MESSAGE_INCOMPLETE;
*plenp = get_u32(cp);
return 0;
}
int
cipher_cleanup(struct sshcipher_ctx *cc)
{
if (cc == NULL || cc->cipher == NULL)
return 0;
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx));
else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx));
#ifdef WITH_OPENSSL
else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
return SSH_ERR_LIBCRYPTO_ERROR;
#endif
return 0;
}
/*
* 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 *cc, Cipher *cipher,
int
cipher_set_key_string(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
const char *passphrase, int do_encrypt)
{
MD5_CTX md;
u_char digest[16];
int r = SSH_ERR_INTERNAL_ERROR;
MD5_Init(&md);
MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
MD5_Final(digest, &md);
if ((r = ssh_digest_memory(SSH_DIGEST_MD5,
passphrase, strlen(passphrase),
digest, sizeof(digest))) != 0)
goto out;
cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt);
memset(digest, 0, sizeof(digest));
memset(&md, 0, sizeof(md));
r = cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt);
out:
explicit_bzero(digest, sizeof(digest));
return r;
}
/*
* Exports an IV from the CipherContext required to export the key
* Exports an IV from the sshcipher_ctx required to export the key
* state back from the unprivileged child to the privileged parent
* process.
*/
int
cipher_get_keyiv_len(const CipherContext *cc)
cipher_get_keyiv_len(const struct sshcipher_ctx *cc)
{
Cipher *c = cc->cipher;
int ivlen;
const struct sshcipher *c = cc->cipher;
int ivlen = 0;
if (c->number == SSH_CIPHER_3DES)
ivlen = 24;
else if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
ivlen = 0;
else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
ivlen = sizeof(cc->ac_ctx.ctr);
#ifdef WITH_OPENSSL
else
ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp);
#endif /* WITH_OPENSSL */
return (ivlen);
}
void
cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
int
cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
{
Cipher *c = cc->cipher;
int evplen;
switch (c->number) {
case SSH_CIPHER_SSH2:
case SSH_CIPHER_DES:
case SSH_CIPHER_BLOWFISH:
evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
if (evplen <= 0)
return;
if ((u_int)evplen != len)
fatal("%s: wrong iv length %d != %d", __func__,
evplen, len);
#ifdef USE_BUILTIN_RIJNDAEL
if (c->evptype == evp_rijndael)
ssh_rijndael_iv(&cc->evp, 0, iv, len);
else
const struct sshcipher *c = cc->cipher;
#ifdef WITH_OPENSSL
int evplen;
#endif
if (c->evptype == evp_aes_128_ctr)
ssh_aes_ctr_iv(&cc->evp, 0, iv, len);
else
memcpy(iv, cc->evp.iv, len);
break;
case SSH_CIPHER_3DES:
ssh1_3des_iv(&cc->evp, 0, iv, 24);
break;
default:
fatal("%s: bad cipher %d", __func__, c->number);
}
}
void
cipher_set_keyiv(CipherContext *cc, u_char *iv)
{
Cipher *c = cc->cipher;
int evplen = 0;
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
if (len != 0)
return SSH_ERR_INVALID_ARGUMENT;
return 0;
}
if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
if (len != sizeof(cc->ac_ctx.ctr))
return SSH_ERR_INVALID_ARGUMENT;
memcpy(iv, cc->ac_ctx.ctr, len);
return 0;
}
if ((cc->cipher->flags & CFLAG_NONE) != 0)
return 0;
switch (c->number) {
#ifdef WITH_OPENSSL
case SSH_CIPHER_SSH2:
case SSH_CIPHER_DES:
case SSH_CIPHER_BLOWFISH:
evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
if (evplen == 0)
return;
#ifdef USE_BUILTIN_RIJNDAEL
if (c->evptype == evp_rijndael)
ssh_rijndael_iv(&cc->evp, 1, iv, evplen);
return 0;
else if (evplen < 0)
return SSH_ERR_LIBCRYPTO_ERROR;
if ((u_int)evplen != len)
return SSH_ERR_INVALID_ARGUMENT;
#ifndef OPENSSL_HAVE_EVPCTR
if (c->evptype == evp_aes_128_ctr)
ssh_aes_ctr_iv(&cc->evp, 0, iv, len);
else
#endif
if (c->evptype == evp_aes_128_ctr)
ssh_aes_ctr_iv(&cc->evp, 1, iv, evplen);
else
memcpy(cc->evp.iv, iv, evplen);
if (cipher_authlen(c)) {
if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN,
len, iv))
return SSH_ERR_LIBCRYPTO_ERROR;
} else
memcpy(iv, cc->evp.iv, len);
break;
#endif
#ifdef WITH_SSH1
case SSH_CIPHER_3DES:
ssh1_3des_iv(&cc->evp, 1, iv, 24);
break;
return ssh1_3des_iv(&cc->evp, 0, iv, 24);
#endif
default:
fatal("%s: bad cipher %d", __func__, c->number);
return SSH_ERR_INVALID_ARGUMENT;
}
return 0;
}
#if OPENSSL_VERSION_NUMBER < 0x00907000L
#define EVP_X_STATE(evp) &(evp).c
#define EVP_X_STATE_LEN(evp) sizeof((evp).c)
#else
int
cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
{
const struct sshcipher *c = cc->cipher;
#ifdef WITH_OPENSSL
int evplen = 0;
#endif
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
return 0;
if ((cc->cipher->flags & CFLAG_NONE) != 0)
return 0;
switch (c->number) {
#ifdef WITH_OPENSSL
case SSH_CIPHER_SSH2:
case SSH_CIPHER_DES:
case SSH_CIPHER_BLOWFISH:
evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
if (evplen <= 0)
return SSH_ERR_LIBCRYPTO_ERROR;
if (cipher_authlen(c)) {
/* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */
if (!EVP_CIPHER_CTX_ctrl(&cc->evp,
EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv))
return SSH_ERR_LIBCRYPTO_ERROR;
} else
memcpy(cc->evp.iv, iv, evplen);
break;
#endif
#ifdef WITH_SSH1
case SSH_CIPHER_3DES:
return ssh1_3des_iv(&cc->evp, 1, (u_char *)iv, 24);
#endif
default:
return SSH_ERR_INVALID_ARGUMENT;
}
return 0;
}
#ifdef WITH_OPENSSL
#define EVP_X_STATE(evp) (evp).cipher_data
#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size
#endif
int
cipher_get_keycontext(const CipherContext *cc, u_char *dat)
cipher_get_keycontext(const struct sshcipher_ctx *cc, u_char *dat)
{
Cipher *c = cc->cipher;
#ifdef WITH_OPENSSL
const struct sshcipher *c = cc->cipher;
int plen = 0;
if (c->evptype == EVP_rc4 || c->evptype == EVP_acss) {
if (c->evptype == EVP_rc4) {
plen = EVP_X_STATE_LEN(cc->evp);
if (dat == NULL)
return (plen);
memcpy(dat, EVP_X_STATE(cc->evp), plen);
}
return (plen);
#else
return 0;
#endif
}
void
cipher_set_keycontext(CipherContext *cc, u_char *dat)
cipher_set_keycontext(struct sshcipher_ctx *cc, const u_char *dat)
{
Cipher *c = cc->cipher;
#ifdef WITH_OPENSSL
const struct sshcipher *c = cc->cipher;
int plen;
if (c->evptype == EVP_rc4 || c->evptype == EVP_acss) {
if (c->evptype == EVP_rc4) {
plen = EVP_X_STATE_LEN(cc->evp);
memcpy(EVP_X_STATE(cc->evp), dat, plen);
}
#endif
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: cipher.h,v 1.37 2009/01/26 09:58:15 markus Exp $ */
/* $OpenBSD: cipher.h,v 1.48 2015/07/08 19:09:25 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -37,7 +37,11 @@
#ifndef CIPHER_H
#define CIPHER_H
#include <sys/types.h>
#include <openssl/evp.h>
#include "cipher-chachapoly.h"
#include "cipher-aesctr.h"
/*
* Cipher types for SSH-1. New types can be added, but old types should not
* be removed for compatibility. The maximum allowed value is 31.
@ -58,35 +62,44 @@
#define CIPHER_ENCRYPT 1
#define CIPHER_DECRYPT 0
typedef struct Cipher Cipher;
typedef struct CipherContext CipherContext;
struct Cipher;
struct CipherContext {
struct sshcipher;
struct sshcipher_ctx {
int plaintext;
int encrypt;
EVP_CIPHER_CTX evp;
Cipher *cipher;
struct chachapoly_ctx cp_ctx; /* XXX union with evp? */
struct aesctr_ctx ac_ctx; /* XXX union with evp? */
const struct sshcipher *cipher;
};
u_int cipher_mask_ssh1(int);
Cipher *cipher_by_name(const char *);
Cipher *cipher_by_number(int);
const struct sshcipher *cipher_by_name(const char *);
const struct sshcipher *cipher_by_number(int);
int cipher_number(const char *);
char *cipher_name(int);
const char *cipher_warning_message(const struct sshcipher_ctx *);
int ciphers_valid(const char *);
void cipher_init(CipherContext *, Cipher *, const u_char *, u_int,
const u_char *, u_int, int);
void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int);
void cipher_cleanup(CipherContext *);
void cipher_set_key_string(CipherContext *, Cipher *, const char *, int);
u_int cipher_blocksize(const Cipher *);
u_int cipher_keylen(const Cipher *);
u_int cipher_is_cbc(const Cipher *);
char *cipher_alg_list(char, int);
int cipher_init(struct sshcipher_ctx *, const struct sshcipher *,
const u_char *, u_int, const u_char *, u_int, int);
int cipher_crypt(struct sshcipher_ctx *, u_int, u_char *, const u_char *,
u_int, u_int, u_int);
int cipher_get_length(struct sshcipher_ctx *, u_int *, u_int,
const u_char *, u_int);
int cipher_cleanup(struct sshcipher_ctx *);
int cipher_set_key_string(struct sshcipher_ctx *, const struct sshcipher *,
const char *, int);
u_int cipher_blocksize(const struct sshcipher *);
u_int cipher_keylen(const struct sshcipher *);
u_int cipher_seclen(const struct sshcipher *);
u_int cipher_authlen(const struct sshcipher *);
u_int cipher_ivlen(const struct sshcipher *);
u_int cipher_is_cbc(const struct sshcipher *);
u_int cipher_get_number(const Cipher *);
void cipher_get_keyiv(CipherContext *, u_char *, u_int);
void cipher_set_keyiv(CipherContext *, u_char *);
int cipher_get_keyiv_len(const CipherContext *);
int cipher_get_keycontext(const CipherContext *, u_char *);
void cipher_set_keycontext(CipherContext *, u_char *);
u_int cipher_get_number(const struct sshcipher *);
int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, u_int);
int cipher_set_keyiv(struct sshcipher_ctx *, const u_char *);
int cipher_get_keyiv_len(const struct sshcipher_ctx *);
int cipher_get_keycontext(const struct sshcipher_ctx *, u_char *);
void cipher_set_keycontext(struct sshcipher_ctx *, const u_char *);
#endif /* CIPHER_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.h,v 1.28 2011/06/22 22:08:42 djm Exp $ */
/* $OpenBSD: clientloop.h,v 1.31 2013/06/02 23:36:29 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -70,6 +70,7 @@ void client_expect_confirm(int, const char *, enum confirm_action);
#define SSHMUX_COMMAND_STDIO_FWD 4 /* Open stdio fwd (ssh -W) */
#define SSHMUX_COMMAND_FORWARD 5 /* Forward only, no command */
#define SSHMUX_COMMAND_STOP 6 /* Disable mux but not conn */
#define SSHMUX_COMMAND_CANCEL_FWD 7 /* Cancel forwarding(s) */
void muxserver_listen(void);
void muxclient(const char *);

156
compat.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: compat.c,v 1.78 2008/09/11 14:22:37 markus Exp $ */
/* $OpenBSD: compat.c,v 1.97 2015/08/19 23:21:42 djm Exp $ */
/*
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
*
@ -45,6 +45,8 @@ int datafellows = 0;
void
enable_compat20(void)
{
if (compat20)
return;
debug("Enabling compatibility mode for protocol 2.0");
compat20 = 1;
}
@ -55,7 +57,7 @@ enable_compat13(void)
compat13 = 1;
}
/* datafellows bug compatibility */
void
u_int
compat_datafellows(const char *version)
{
int i;
@ -92,6 +94,10 @@ compat_datafellows(const char *version)
{ "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR },
{ "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
{ "OpenSSH_4*", 0 },
{ "OpenSSH_5*", SSH_NEW_OPENSSH|SSH_BUG_DYNAMIC_RPORT},
{ "OpenSSH_6.6.1*", SSH_NEW_OPENSSH},
{ "OpenSSH_6.5*,"
"OpenSSH_6.6*", SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD},
{ "OpenSSH*", SSH_NEW_OPENSSH },
{ "*MindTerm*", 0 },
{ "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
@ -146,6 +152,8 @@ compat_datafellows(const char *version)
"1.2.22*", SSH_BUG_IGNOREMSG },
{ "1.3.2*", /* F-Secure */
SSH_BUG_IGNOREMSG },
{ "Cisco-1.*", SSH_BUG_DHGEX_LARGE|
SSH_BUG_HOSTKEYS },
{ "*SSH Compatible Server*", /* Netscreen */
SSH_BUG_PASSWORDPAD },
{ "*OSU_0*,"
@ -159,21 +167,54 @@ compat_datafellows(const char *version)
"OSU_1.5alpha3*", SSH_BUG_PASSWORDPAD },
{ "*SSH_Version_Mapper*",
SSH_BUG_SCANNER },
{ "PuTTY_Local:*," /* dev versions < Sep 2014 */
"PuTTY-Release-0.5*," /* 0.50-0.57, DH-GEX in >=0.52 */
"PuTTY_Release_0.5*," /* 0.58-0.59 */
"PuTTY_Release_0.60*,"
"PuTTY_Release_0.61*,"
"PuTTY_Release_0.62*,"
"PuTTY_Release_0.63*,"
"PuTTY_Release_0.64*",
SSH_OLD_DHGEX },
{ "FuTTY*", SSH_OLD_DHGEX }, /* Putty Fork */
{ "Probe-*",
SSH_BUG_PROBE },
{ "TeraTerm SSH*,"
"TTSSH/1.5.*,"
"TTSSH/2.1*,"
"TTSSH/2.2*,"
"TTSSH/2.3*,"
"TTSSH/2.4*,"
"TTSSH/2.5*,"
"TTSSH/2.6*,"
"TTSSH/2.70*,"
"TTSSH/2.71*,"
"TTSSH/2.72*", SSH_BUG_HOSTKEYS },
{ "WinSCP_release_4*,"
"WinSCP_release_5.0*,"
"WinSCP_release_5.1*,"
"WinSCP_release_5.5*,"
"WinSCP_release_5.6*,"
"WinSCP_release_5.7,"
"WinSCP_release_5.7.1,"
"WinSCP_release_5.7.2,"
"WinSCP_release_5.7.3,"
"WinSCP_release_5.7.4",
SSH_OLD_DHGEX },
{ NULL, 0 }
};
/* process table, return first match */
for (i = 0; check[i].pat; i++) {
if (match_pattern_list(version, check[i].pat,
strlen(check[i].pat), 0) == 1) {
debug("match: %s pat %s", version, check[i].pat);
datafellows = check[i].bugs;
return;
if (match_pattern_list(version, check[i].pat, 0) == 1) {
debug("match: %s pat %s compat 0x%08x",
version, check[i].pat, check[i].bugs);
datafellows = check[i].bugs; /* XXX for now */
return check[i].bugs;
}
}
debug("no match: %s", version);
return 0;
}
#define SEP ","
@ -185,13 +226,17 @@ proto_spec(const char *spec)
if (spec == NULL)
return ret;
q = s = xstrdup(spec);
q = s = strdup(spec);
if (s == NULL)
return ret;
for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) {
switch (atoi(p)) {
case 1:
#ifdef WITH_SSH1
if (ret == SSH_PROTO_UNKNOWN)
ret |= SSH_PROTO_1_PREFERRED;
ret |= SSH_PROTO_1;
#endif
break;
case 2:
ret |= SSH_PROTO_2;
@ -201,37 +246,80 @@ proto_spec(const char *spec)
break;
}
}
xfree(s);
free(s);
return ret;
}
/*
* Filters a proposal string, excluding any algorithm matching the 'filter'
* pattern list.
*/
static char *
filter_proposal(char *proposal, const char *filter)
{
Buffer b;
char *orig_prop, *fix_prop;
char *cp, *tmp;
buffer_init(&b);
tmp = orig_prop = xstrdup(proposal);
while ((cp = strsep(&tmp, ",")) != NULL) {
if (match_pattern_list(cp, filter, 0) != 1) {
if (buffer_len(&b) > 0)
buffer_append(&b, ",", 1);
buffer_append(&b, cp, strlen(cp));
} else
debug2("Compat: skipping algorithm \"%s\"", cp);
}
buffer_append(&b, "\0", 1);
fix_prop = xstrdup((char *)buffer_ptr(&b));
buffer_free(&b);
free(orig_prop);
return fix_prop;
}
char *
compat_cipher_proposal(char *cipher_prop)
{
Buffer b;
char *orig_prop, *fix_ciphers;
char *cp, *tmp;
if (!(datafellows & SSH_BUG_BIGENDIANAES))
return(cipher_prop);
buffer_init(&b);
tmp = orig_prop = xstrdup(cipher_prop);
while ((cp = strsep(&tmp, ",")) != NULL) {
if (strncmp(cp, "aes", 3) != 0) {
if (buffer_len(&b) > 0)
buffer_append(&b, ",", 1);
buffer_append(&b, cp, strlen(cp));
}
}
buffer_append(&b, "\0", 1);
fix_ciphers = xstrdup(buffer_ptr(&b));
buffer_free(&b);
xfree(orig_prop);
debug2("Original cipher proposal: %s", cipher_prop);
debug2("Compat cipher proposal: %s", fix_ciphers);
if (!*fix_ciphers)
fatal("No available ciphers found.");
return(fix_ciphers);
return cipher_prop;
debug2("%s: original cipher proposal: %s", __func__, cipher_prop);
cipher_prop = filter_proposal(cipher_prop, "aes*");
debug2("%s: compat cipher proposal: %s", __func__, cipher_prop);
if (*cipher_prop == '\0')
fatal("No supported ciphers found");
return cipher_prop;
}
char *
compat_pkalg_proposal(char *pkalg_prop)
{
if (!(datafellows & SSH_BUG_RSASIGMD5))
return pkalg_prop;
debug2("%s: original public key proposal: %s", __func__, pkalg_prop);
pkalg_prop = filter_proposal(pkalg_prop, "ssh-rsa");
debug2("%s: compat public key proposal: %s", __func__, pkalg_prop);
if (*pkalg_prop == '\0')
fatal("No supported PK algorithms found");
return pkalg_prop;
}
char *
compat_kex_proposal(char *p)
{
if ((datafellows & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0)
return p;
debug2("%s: original KEX proposal: %s", __func__, p);
if ((datafellows & SSH_BUG_CURVE25519PAD) != 0)
p = filter_proposal(p, "curve25519-sha256@libssh.org");
if ((datafellows & SSH_OLD_DHGEX) != 0) {
p = filter_proposal(p, "diffie-hellman-group-exchange-sha256");
p = filter_proposal(p, "diffie-hellman-group-exchange-sha1");
}
debug2("%s: compat KEX proposal: %s", __func__, p);
if (*p == '\0')
fatal("No supported key exchange algorithms found");
return p;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: compat.h,v 1.42 2008/09/11 14:22:37 markus Exp $ */
/* $OpenBSD: compat.h,v 1.48 2015/05/26 23:23:40 dtucker Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
@ -58,12 +58,18 @@
#define SSH_OLD_FORWARD_ADDR 0x01000000
#define SSH_BUG_RFWD_ADDR 0x02000000
#define SSH_NEW_OPENSSH 0x04000000
#define SSH_BUG_DYNAMIC_RPORT 0x08000000
#define SSH_BUG_CURVE25519PAD 0x10000000
#define SSH_BUG_HOSTKEYS 0x20000000
#define SSH_BUG_DHGEX_LARGE 0x40000000
void enable_compat13(void);
void enable_compat20(void);
void compat_datafellows(const char *);
u_int compat_datafellows(const char *);
int proto_spec(const char *);
char *compat_cipher_proposal(char *);
char *compat_pkalg_proposal(char *);
char *compat_kex_proposal(char *);
extern int compat13;
extern int compat20;

1644
config.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -88,3 +88,15 @@
#define BROKEN_SYS_TERMIO_H
#define strerror strerror_win32
#define strerror strerror_win32
// PRAGMA SYS PORT
#define WITH_OPENSSL 1
#define HAVE_KRB5_GET_ERROR_MESSAGE 1
#define HAVE_KRB5_FREE_ERROR_MESSAGE 1
#define HAVE_DECL_NFDBITS 0
#define HAVE_DECL_HOWMANY 0
//#define HAVE_ARC4RANDOM_UNIFORM 1

View File

@ -1,4 +1,4 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libssh", "libssh\libssh.vcproj", "{EBDE90BD-BD30-4128-8E79-50224624628E}"

44
crypto_api.h Normal file
View File

@ -0,0 +1,44 @@
/* $OpenBSD: crypto_api.h,v 1.3 2013/12/17 10:36:38 markus Exp $ */
/*
* Assembled from generated headers and source files by Markus Friedl.
* Placed in the public domain.
*/
#ifndef crypto_api_h
#define crypto_api_h
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include <stdlib.h>
typedef int32_t crypto_int32;
typedef uint32_t crypto_uint32;
#define randombytes(buf, buf_len) arc4random_buf((buf), (buf_len))
#define crypto_hashblocks_sha512_STATEBYTES 64U
#define crypto_hashblocks_sha512_BLOCKBYTES 128U
int crypto_hashblocks_sha512(unsigned char *, const unsigned char *,
unsigned long long);
#define crypto_hash_sha512_BYTES 64U
int crypto_hash_sha512(unsigned char *, const unsigned char *,
unsigned long long);
int crypto_verify_32(const unsigned char *, const unsigned char *);
#define crypto_sign_ed25519_SECRETKEYBYTES 64U
#define crypto_sign_ed25519_PUBLICKEYBYTES 32U
#define crypto_sign_ed25519_BYTES 64U
int crypto_sign_ed25519(unsigned char *, unsigned long long *,
const unsigned char *, unsigned long long, const unsigned char *);
int crypto_sign_ed25519_open(unsigned char *, unsigned long long *,
const unsigned char *, unsigned long long, const unsigned char *);
int crypto_sign_ed25519_keypair(unsigned char *, unsigned char *);
#endif /* crypto_api_h */

1
d2utmpa00408 Normal file
View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6mQW39+Uvy7DPCJd6aHJ0RXDnL+NC7VsC+SUAvosyMwb3PrxjFobyJ24yl6HEpdHvmlbNkipObew3T/drNQ0QK/H4Wt/7mkIdxN6IbF9hpFaLt8Fyd0yd7cpdxGHjYVEjuUBHgsOI/2k2V3zZx/c31X87Zjwb18JM8DKNk/ewKBj1MZVDcBdIWQT5WORPmpCVV7CeLE1TiXc5b2/2wNOOBdKPuDYBDGdPShqD91IaXmIs9KFUo4jFBE/V+K6fesUngudnouKdhFzSokoXbIpFNyi5L2TURtS9ebwm0Zkaz2xW86DJ6bSMtuMqhUDsJOZFmHh8NnTwuSDPUVXhlzbZ @oasis

1
d2utmpa00420 Normal file
View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCci4oy7TlKHy9d8+4slhm66MzE9haGbasI3Wwt6LqrvK6X0jtVCA+04nBWoBH7m+8UJrd6mqldSsOVETiZFLm4sNl95MmKirWHmoSeJy12wyovQXYkyYRH0T4J2lDna6JbgCPuaZpgIq88sxb/Z8RVf9fjStd6aNIyM95BalRnL839mYJxXpfPNMBkXGED3w/m5S6GgxX8VrP1cC6N+kXao5nyctZqFZAQbtj122LAeFNWN6W0Ehy5mx1VETFII+h9vSJ2LwDNHNrYBPV2IOtJ/tQ8ajSoc60bNvJjJtgld/he3KlmrgjtKcC4Akr1Bmegm+iI4pg2VgUnpocTdDfb @oasis

12
d2utmpa00672 Normal file
View File

@ -0,0 +1,12 @@
-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQC8GRz9p5YiVi9BA7jNO3MXV2NkPlMfCv2xjieBE6bflmHKoKhC
ewlyrk1SfLJQgVbOZvdrgtsuYGgKfpqu8qWlVnEHOLYSa6f6CDcjRXa5X+T2+tBZ
zYZ7UBlEFuDLoCEpSOopsDzPz+wvyGBH7/DPtHhbLB/ipIZYXMe/QXcyFwIVAIA9
pz8MNAL+c9x9cNW9V40GIlnBAoGAWXg5YYAHb/+ZRHXBTTULmY8LT8Mhp8JDrIWY
TE+JHlFmGtHJsajoQNo5yFCj6ep1YqeKSZdj3x0JXSJDLLQNuiaGL74MdEasYt3g
rG04HE7k3tXfSwSM0cKhSFU/MKo9rhXStRcKdG5ZN4d+pTnoyV/ncfooiRJprqXH
l4yv2vMCgYEAp8OaX5N4UtY0KID34SNj5b3hsAoK5IZ3mBsX7Ngg6Rbnr7h2s5sK
sus5FiMtmymVssY84YZTRVP6oZWSShG/WOcUQrzo8zxKH9cj6pc/haSraTakSXLK
bbsI2Bj1nMYmXZxSelLUZS0Xwsp3EVxxLYmrzduXyV3ewvrHFZ1q6jsCFH3IbB4V
XAMosp5QzPxxeQQtAjVD
-----END DSA PRIVATE KEY-----

7
d2utmpa01232 Normal file
View File

@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACDsm6kHU3O2x/KuzcbAUhZGYsoc4Gn6YiFcuulsx4gsyAAAAJAJSj5MCUo+
TAAAAAtzc2gtZWQyNTUxOQAAACDsm6kHU3O2x/KuzcbAUhZGYsoc4Gn6YiFcuulsx4gsyA
AAAECGe69spV/5acdoNqiARzB79o5ASCy2SQ6Ng7SWENmDguybqQdTc7bH8q7NxsBSFkZi
yhzgafpiIVy66WzHiCzIAAAABkBvYXNpcwECAwQFBgc=
-----END OPENSSH PRIVATE KEY-----

1
d2utmpa01324 Normal file
View File

@ -0,0 +1 @@
ssh-dss AAAAB3NzaC1kc3MAAACBALwZHP2nliJWL0EDuM07cxdXY2Q+Ux8K/bGOJ4ETpt+WYcqgqEJ7CXKuTVJ8slCBVs5m92uC2y5gaAp+mq7ypaVWcQc4thJrp/oINyNFdrlf5Pb60FnNhntQGUQW4MugISlI6imwPM/P7C/IYEfv8M+0eFssH+Kkhlhcx79BdzIXAAAAFQCAPac/DDQC/nPcfXDVvVeNBiJZwQAAAIBZeDlhgAdv/5lEdcFNNQuZjwtPwyGnwkOshZhMT4keUWYa0cmxqOhA2jnIUKPp6nVip4pJl2PfHQldIkMstA26JoYvvgx0Rqxi3eCsbTgcTuTe1d9LBIzRwqFIVT8wqj2uFdK1Fwp0blk3h36lOejJX+dx+iiJEmmupceXjK/a8wAAAIEAp8OaX5N4UtY0KID34SNj5b3hsAoK5IZ3mBsX7Ngg6Rbnr7h2s5sKsus5FiMtmymVssY84YZTRVP6oZWSShG/WOcUQrzo8zxKH9cj6pc/haSraTakSXLKbbsI2Bj1nMYmXZxSelLUZS0Xwsp3EVxxLYmrzduXyV3ewvrHFZ1q6js= @oasis

1
d2utmpa01468 Normal file
View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCci4oy7TlKHy9d8+4slhm66MzE9haGbasI3Wwt6LqrvK6X0jtVCA+04nBWoBH7m+8UJrd6mqldSsOVETiZFLm4sNl95MmKirWHmoSeJy12wyovQXYkyYRH0T4J2lDna6JbgCPuaZpgIq88sxb/Z8RVf9fjStd6aNIyM95BalRnL839mYJxXpfPNMBkXGED3w/m5S6GgxX8VrP1cC6N+kXao5nyctZqFZAQbtj122LAeFNWN6W0Ehy5mx1VETFII+h9vSJ2LwDNHNrYBPV2IOtJ/tQ8ajSoc60bNvJjJtgld/he3KlmrgjtKcC4Akr1Bmegm+iI4pg2VgUnpocTdDfb @oasis

27
d2utmpa02828 Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAupkFt/flL8uwzwiXemhydEVw5y/jQu1bAvklAL6LMjMG9z68
YxaG8iduMpehxKXR75pWzZIqTm3sN0/3azUNECvx+Frf+5pCHcTeiGxfYaRWi7fB
cndMne3KXcRh42FRI7lAR4LDiP9pNld82cf3N9V/O2Y8G9fCTPAyjZP3sCgY9TGV
Q3AXSFkE+VjkT5qQlVewnixNU4l3OW9v9sDTjgXSj7g2AQxnT0oag/dSGl5iLPSh
VKOIxQRP1fiun3rFJ4LnZ6LinYRc0qJKF2yKRTcouS9k1EbUvXm8JtGZGs9sVvOg
yem0jLbjKoVA7CTmRZh4fDZ08Lkgz1FV4Zc22QIDAQABAoIBAGkkUFSZGksUO0xt
Su1ubQ+XEUczdJsBo4bJXFBPDZ/7oLEwaHZs+xz3muBnEH/9741TKhYrhisrRS7l
oESIYBP8rxuCGTNseFTN2ZaFejlKoHmZ0Sbukf1rP9wWDBJTg6TdfZrN0+AeCurT
4UXVpzeO1WJi+Pu3V4SC0/lypt5aw2F1urfoWSaUR43xiYpnjMNQ6dDvVoXA4R2X
lMvvdAimTyA3XFDQILlUz6UHH01nEDO6n3T7VjB8UxiJrV5Oyy/aREBIJRiEHf5t
dkZjVmtoKhAxKsOCyne/BZ3G1dYIGAhEM/SPqMQtPWy7U95ZaKQbF/Y5BhZb+5d6
88HG6QECgYEA3VXddhNh8Ore1rrmlG/5/hwFg9BfP74Gt+lZcmT1Gwh9EBdcn3he
xn4kBiw3m1kYyJw3wUfg/zINerqPz57EV669aVaDOVXbqTsFHOsFa74wMERYfV+/
eBn7lFdwxOXq4vfDMzq0Ph+wtFvA+C2IkQVk60PR94dJMTn5VLm26nsCgYEA19Jm
Hfvm/P/9oc4+rtkTUrs5BDHloBJ28TydZ84bI4B4n1/pJOWKrZ4y4kATic00+otW
sncOVAeFq7Nj8yJ1XRCxKnjbhR2q/FZQf8f0c5xVWh4iXRt6Zf5hVcCmkle8SV6M
vQb5zpRbzQTx+nrbut6RMbQPVHy5BIXhdzIeHbsCgYAik41bKr/8INTa+quWuL93
AO2jn+OhU5A9HskIY9kedf8DioK/rtAvdfkuta2iKRMEE9Np8E6nzyvn5kkdCBJo
GDYixI8PX+hG0Z+E2von0Lg6chLY0yJYIsb4b4iAWeKNvmLSF/OcWNsD8el9W6+f
6BXR4vBkGNBITmQy5ig7DQKBgQCcfVLOKvkyOewOhx2sano4YsjU4dk+WCUmhm0b
97Z155GO/lxvBIGpoiwDIbMJGGJxyNb0UJ9zDoE+HrU6dqHi+Vd9FGUYAIsarPtx
q+r0aUb6MR95o5L8oZayNx6Qvk0oZgZmichYofpujkdm9+6bcQaWo5j6CfWd8fWq
GAz+QQKBgHBOyyzXC7HSy+IAu/Jo3kpkgTqjYUIsmig5QKamHo/5FP8FCq4ZVR1L
CYrpCVzbvjAjBnSm1/3UngjS3PPldUYjGIbez3gK/jJTfnzfsVghnQsZOd97YxuX
TusifzCTcDZEUIZSdxL72EpbGtkYqVeDl4SjU0ZMfSIyiEsfyDFw
-----END RSA PRIVATE KEY-----

5
d2utmpa03344 Normal file
View File

@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOrwk5LCELxzRGufJcI3ogOmaqYwNGYg0KIZqnQysKsPoAoGCCqGSM49
AwEHoUQDQgAEXkGf9akhGRCleBfum8S5D11uWdOngABaPtFj7OHGk4u8gncSGf3g
uQj9j5MSCt9BV57GXKXgb0Xu0TH0wXbNqA==
-----END EC PRIVATE KEY-----

1
d2utmpa03516 Normal file
View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6mQW39+Uvy7DPCJd6aHJ0RXDnL+NC7VsC+SUAvosyMwb3PrxjFobyJ24yl6HEpdHvmlbNkipObew3T/drNQ0QK/H4Wt/7mkIdxN6IbF9hpFaLt8Fyd0yd7cpdxGHjYVEjuUBHgsOI/2k2V3zZx/c31X87Zjwb18JM8DKNk/ewKBj1MZVDcBdIWQT5WORPmpCVV7CeLE1TiXc5b2/2wNOOBdKPuDYBDGdPShqD91IaXmIs9KFUo4jFBE/V+K6fesUngudnouKdhFzSokoXbIpFNyi5L2TURtS9ebwm0Zkaz2xW86DJ6bSMtuMqhUDsJOZFmHh8NnTwuSDPUVXhlzbZ @oasis

1
d2utmpa04376 Normal file
View File

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOybqQdTc7bH8q7NxsBSFkZiyhzgafpiIVy66WzHiCzI @oasis

1
d2utmpa04792 Normal file
View File

@ -0,0 +1 @@
ssh-dss AAAAB3NzaC1kc3MAAACBALwZHP2nliJWL0EDuM07cxdXY2Q+Ux8K/bGOJ4ETpt+WYcqgqEJ7CXKuTVJ8slCBVs5m92uC2y5gaAp+mq7ypaVWcQc4thJrp/oINyNFdrlf5Pb60FnNhntQGUQW4MugISlI6imwPM/P7C/IYEfv8M+0eFssH+Kkhlhcx79BdzIXAAAAFQCAPac/DDQC/nPcfXDVvVeNBiJZwQAAAIBZeDlhgAdv/5lEdcFNNQuZjwtPwyGnwkOshZhMT4keUWYa0cmxqOhA2jnIUKPp6nVip4pJl2PfHQldIkMstA26JoYvvgx0Rqxi3eCsbTgcTuTe1d9LBIzRwqFIVT8wqj2uFdK1Fwp0blk3h36lOejJX+dx+iiJEmmupceXjK/a8wAAAIEAp8OaX5N4UtY0KID34SNj5b3hsAoK5IZ3mBsX7Ngg6Rbnr7h2s5sKsus5FiMtmymVssY84YZTRVP6oZWSShG/WOcUQrzo8zxKH9cj6pc/haSraTakSXLKbbsI2Bj1nMYmXZxSelLUZS0Xwsp3EVxxLYmrzduXyV3ewvrHFZ1q6js= @oasis

1
d2utmpa04800 Normal file
View File

@ -0,0 +1 @@
ssh-dss AAAAB3NzaC1kc3MAAACBALwZHP2nliJWL0EDuM07cxdXY2Q+Ux8K/bGOJ4ETpt+WYcqgqEJ7CXKuTVJ8slCBVs5m92uC2y5gaAp+mq7ypaVWcQc4thJrp/oINyNFdrlf5Pb60FnNhntQGUQW4MugISlI6imwPM/P7C/IYEfv8M+0eFssH+Kkhlhcx79BdzIXAAAAFQCAPac/DDQC/nPcfXDVvVeNBiJZwQAAAIBZeDlhgAdv/5lEdcFNNQuZjwtPwyGnwkOshZhMT4keUWYa0cmxqOhA2jnIUKPp6nVip4pJl2PfHQldIkMstA26JoYvvgx0Rqxi3eCsbTgcTuTe1d9LBIzRwqFIVT8wqj2uFdK1Fwp0blk3h36lOejJX+dx+iiJEmmupceXjK/a8wAAAIEAp8OaX5N4UtY0KID34SNj5b3hsAoK5IZ3mBsX7Ngg6Rbnr7h2s5sKsus5FiMtmymVssY84YZTRVP6oZWSShG/WOcUQrzo8zxKH9cj6pc/haSraTakSXLKbbsI2Bj1nMYmXZxSelLUZS0Xwsp3EVxxLYmrzduXyV3ewvrHFZ1q6js= @oasis

12
d2utmpa05272 Normal file
View File

@ -0,0 +1,12 @@
-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQC8GRz9p5YiVi9BA7jNO3MXV2NkPlMfCv2xjieBE6bflmHKoKhC
ewlyrk1SfLJQgVbOZvdrgtsuYGgKfpqu8qWlVnEHOLYSa6f6CDcjRXa5X+T2+tBZ
zYZ7UBlEFuDLoCEpSOopsDzPz+wvyGBH7/DPtHhbLB/ipIZYXMe/QXcyFwIVAIA9
pz8MNAL+c9x9cNW9V40GIlnBAoGAWXg5YYAHb/+ZRHXBTTULmY8LT8Mhp8JDrIWY
TE+JHlFmGtHJsajoQNo5yFCj6ep1YqeKSZdj3x0JXSJDLLQNuiaGL74MdEasYt3g
rG04HE7k3tXfSwSM0cKhSFU/MKo9rhXStRcKdG5ZN4d+pTnoyV/ncfooiRJprqXH
l4yv2vMCgYEAp8OaX5N4UtY0KID34SNj5b3hsAoK5IZ3mBsX7Ngg6Rbnr7h2s5sK
sus5FiMtmymVssY84YZTRVP6oZWSShG/WOcUQrzo8zxKH9cj6pc/haSraTakSXLK
bbsI2Bj1nMYmXZxSelLUZS0Xwsp3EVxxLYmrzduXyV3ewvrHFZ1q6jsCFH3IbB4V
XAMosp5QzPxxeQQtAjVD
-----END DSA PRIVATE KEY-----

1
d2utmpa06292 Normal file
View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6mQW39+Uvy7DPCJd6aHJ0RXDnL+NC7VsC+SUAvosyMwb3PrxjFobyJ24yl6HEpdHvmlbNkipObew3T/drNQ0QK/H4Wt/7mkIdxN6IbF9hpFaLt8Fyd0yd7cpdxGHjYVEjuUBHgsOI/2k2V3zZx/c31X87Zjwb18JM8DKNk/ewKBj1MZVDcBdIWQT5WORPmpCVV7CeLE1TiXc5b2/2wNOOBdKPuDYBDGdPShqD91IaXmIs9KFUo4jFBE/V+K6fesUngudnouKdhFzSokoXbIpFNyi5L2TURtS9ebwm0Zkaz2xW86DJ6bSMtuMqhUDsJOZFmHh8NnTwuSDPUVXhlzbZ @oasis

5
d2utmpa06444 Normal file
View File

@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOrwk5LCELxzRGufJcI3ogOmaqYwNGYg0KIZqnQysKsPoAoGCCqGSM49
AwEHoUQDQgAEXkGf9akhGRCleBfum8S5D11uWdOngABaPtFj7OHGk4u8gncSGf3g
uQj9j5MSCt9BV57GXKXgb0Xu0TH0wXbNqA==
-----END EC PRIVATE KEY-----

12
d2utmpa07284 Normal file
View File

@ -0,0 +1,12 @@
-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQC8GRz9p5YiVi9BA7jNO3MXV2NkPlMfCv2xjieBE6bflmHKoKhC
ewlyrk1SfLJQgVbOZvdrgtsuYGgKfpqu8qWlVnEHOLYSa6f6CDcjRXa5X+T2+tBZ
zYZ7UBlEFuDLoCEpSOopsDzPz+wvyGBH7/DPtHhbLB/ipIZYXMe/QXcyFwIVAIA9
pz8MNAL+c9x9cNW9V40GIlnBAoGAWXg5YYAHb/+ZRHXBTTULmY8LT8Mhp8JDrIWY
TE+JHlFmGtHJsajoQNo5yFCj6ep1YqeKSZdj3x0JXSJDLLQNuiaGL74MdEasYt3g
rG04HE7k3tXfSwSM0cKhSFU/MKo9rhXStRcKdG5ZN4d+pTnoyV/ncfooiRJprqXH
l4yv2vMCgYEAp8OaX5N4UtY0KID34SNj5b3hsAoK5IZ3mBsX7Ngg6Rbnr7h2s5sK
sus5FiMtmymVssY84YZTRVP6oZWSShG/WOcUQrzo8zxKH9cj6pc/haSraTakSXLK
bbsI2Bj1nMYmXZxSelLUZS0Xwsp3EVxxLYmrzduXyV3ewvrHFZ1q6jsCFH3IbB4V
XAMosp5QzPxxeQQtAjVD
-----END DSA PRIVATE KEY-----

1
d2utmpa07336 Normal file
View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCci4oy7TlKHy9d8+4slhm66MzE9haGbasI3Wwt6LqrvK6X0jtVCA+04nBWoBH7m+8UJrd6mqldSsOVETiZFLm4sNl95MmKirWHmoSeJy12wyovQXYkyYRH0T4J2lDna6JbgCPuaZpgIq88sxb/Z8RVf9fjStd6aNIyM95BalRnL839mYJxXpfPNMBkXGED3w/m5S6GgxX8VrP1cC6N+kXao5nyctZqFZAQbtj122LAeFNWN6W0Ehy5mx1VETFII+h9vSJ2LwDNHNrYBPV2IOtJ/tQ8ajSoc60bNvJjJtgld/he3KlmrgjtKcC4Akr1Bmegm+iI4pg2VgUnpocTdDfb @oasis

27
d2utmpa08080 Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAupkFt/flL8uwzwiXemhydEVw5y/jQu1bAvklAL6LMjMG9z68
YxaG8iduMpehxKXR75pWzZIqTm3sN0/3azUNECvx+Frf+5pCHcTeiGxfYaRWi7fB
cndMne3KXcRh42FRI7lAR4LDiP9pNld82cf3N9V/O2Y8G9fCTPAyjZP3sCgY9TGV
Q3AXSFkE+VjkT5qQlVewnixNU4l3OW9v9sDTjgXSj7g2AQxnT0oag/dSGl5iLPSh
VKOIxQRP1fiun3rFJ4LnZ6LinYRc0qJKF2yKRTcouS9k1EbUvXm8JtGZGs9sVvOg
yem0jLbjKoVA7CTmRZh4fDZ08Lkgz1FV4Zc22QIDAQABAoIBAGkkUFSZGksUO0xt
Su1ubQ+XEUczdJsBo4bJXFBPDZ/7oLEwaHZs+xz3muBnEH/9741TKhYrhisrRS7l
oESIYBP8rxuCGTNseFTN2ZaFejlKoHmZ0Sbukf1rP9wWDBJTg6TdfZrN0+AeCurT
4UXVpzeO1WJi+Pu3V4SC0/lypt5aw2F1urfoWSaUR43xiYpnjMNQ6dDvVoXA4R2X
lMvvdAimTyA3XFDQILlUz6UHH01nEDO6n3T7VjB8UxiJrV5Oyy/aREBIJRiEHf5t
dkZjVmtoKhAxKsOCyne/BZ3G1dYIGAhEM/SPqMQtPWy7U95ZaKQbF/Y5BhZb+5d6
88HG6QECgYEA3VXddhNh8Ore1rrmlG/5/hwFg9BfP74Gt+lZcmT1Gwh9EBdcn3he
xn4kBiw3m1kYyJw3wUfg/zINerqPz57EV669aVaDOVXbqTsFHOsFa74wMERYfV+/
eBn7lFdwxOXq4vfDMzq0Ph+wtFvA+C2IkQVk60PR94dJMTn5VLm26nsCgYEA19Jm
Hfvm/P/9oc4+rtkTUrs5BDHloBJ28TydZ84bI4B4n1/pJOWKrZ4y4kATic00+otW
sncOVAeFq7Nj8yJ1XRCxKnjbhR2q/FZQf8f0c5xVWh4iXRt6Zf5hVcCmkle8SV6M
vQb5zpRbzQTx+nrbut6RMbQPVHy5BIXhdzIeHbsCgYAik41bKr/8INTa+quWuL93
AO2jn+OhU5A9HskIY9kedf8DioK/rtAvdfkuta2iKRMEE9Np8E6nzyvn5kkdCBJo
GDYixI8PX+hG0Z+E2von0Lg6chLY0yJYIsb4b4iAWeKNvmLSF/OcWNsD8el9W6+f
6BXR4vBkGNBITmQy5ig7DQKBgQCcfVLOKvkyOewOhx2sano4YsjU4dk+WCUmhm0b
97Z155GO/lxvBIGpoiwDIbMJGGJxyNb0UJ9zDoE+HrU6dqHi+Vd9FGUYAIsarPtx
q+r0aUb6MR95o5L8oZayNx6Qvk0oZgZmichYofpujkdm9+6bcQaWo5j6CfWd8fWq
GAz+QQKBgHBOyyzXC7HSy+IAu/Jo3kpkgTqjYUIsmig5QKamHo/5FP8FCq4ZVR1L
CYrpCVzbvjAjBnSm1/3UngjS3PPldUYjGIbez3gK/jJTfnzfsVghnQsZOd97YxuX
TusifzCTcDZEUIZSdxL72EpbGtkYqVeDl4SjU0ZMfSIyiEsfyDFw
-----END RSA PRIVATE KEY-----

7
d2utmpa08624 Normal file
View File

@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACDsm6kHU3O2x/KuzcbAUhZGYsoc4Gn6YiFcuulsx4gsyAAAAJAJSj5MCUo+
TAAAAAtzc2gtZWQyNTUxOQAAACDsm6kHU3O2x/KuzcbAUhZGYsoc4Gn6YiFcuulsx4gsyA
AAAECGe69spV/5acdoNqiARzB79o5ASCy2SQ6Ng7SWENmDguybqQdTc7bH8q7NxsBSFkZi
yhzgafpiIVy66WzHiCzIAAAABkBvYXNpcwECAwQFBgc=
-----END OPENSSH PRIVATE KEY-----

27
d2utmpa08916 Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAnIuKMu05Sh8vXfPuLJYZuujMxPYWhm2rCN1sLei6q7yul9I7
VQgPtOJwVqAR+5vvFCa3epqpXUrDlRE4mRS5uLDZfeTJioq1h5qEnictdsMqL0F2
JMmER9E+CdpQ52uiW4Aj7mmaYCKvPLMW/2fEVX/X40rXemjSMjPeQWpUZy/N/ZmC
cV6XzzTAZFxhA98P5uUuhoMV/Faz9XAujfpF2qOZ8nLWahWQEG7Y9dtiwHhTVjel
tBIcuZsdVRExSCPofb0idi8AzRza2AT1diDrSf7UPGo0qHOtGzbyYybYJXf4Xtyp
Zq4I7SnAuAJK9QZnoJvoiOKYNlYFJ6aHE3Q32wIDAQABAoIBAAg70qYBEi1S3JPt
e45+ypWpHvQRGXgylndd5g24GvFjeC9mEFbVmLXj3xK/UpLQTc/ahXX+YoAUqZrS
kA6FJ4uOSbI0cWFHEGs0dls3Jk4Dz9kycTtYGgwI9mFgSTcS0zRK1hj5FvSNfngL
117Rn2L72WgMDK9UihG35q28IPpYVUTN7W+qU5YdG9m5KutBjmq9lStc6eeHqMYH
EBo3WwMh43oBhcqbebowgQLIkQTcnVdDwsjT8GYEI7onH4SnQWapch7ogXERu34w
SDNhcQ5N4gSV/Urj5+RuA78s3eKb3zZMW3lLvmr4re6BZWa/E6XmYq8k2KAB12TX
5QaYqnECgYEAzlhlLMPXuOqcQp1O1TyVNxWwJ9Q8TqhLjnbFASLCzFU2E0lup0mH
2wK0cL8KhljT6rYzKFFp2ik5+1TzHKxEvnyzB89IJ3z/5e0AYssyv1oRnzMx9amg
+04BxP4iAo1Fs9xN60PhsjHfIBj8jH3EJcla0G/zY0JE510cDRCa/YkCgYEAwjdG
JBjva6vgwZiiZ5QoOmH0WIsOnNB5VjzOONXUrpYSNMBDGougnt9eOeyUbAGgPBLT
10eR9oR06DLacn/jw75u07NCBfqxTSdW+xziG54DnK24vONBS4KmbA/v4u1mMaIn
OxRfx++3lcOvrMeUqjA5ZrUUW5VXV/dNg0IStUMCgYEAxSEptzR6GMz576H9ODYi
j3eGzOYznymk1TueRdGBrFgTyyUyM1tKEO9qlvPMCEFAY1EhWnk82RDdtcCYaWIi
YqEbIHDki+UdS/m5jqh1mN1hTGhKaFlf0/XYNuxabXmth4EGZ6Z4Lhb7BN0aGNXl
1/ufaNYq/T7IOQh4zfp5N5ECgYEAgcpYmIUFc4owsJAlcF0FqUaO+aEsicWUYPpP
wpG8CVSHJDOcZKANHj8eBE3DPo6zm5Hlekf9FqacThS2AbDP8J9SBy4ToFVRqcLx
kO1TeatWtJ0wCSNCHolYWH0qDhgipGa+GvBZtg7QPEjDHQ9fnYCOy8GVskKSVVoS
tfYw9GsCgYEAjhgQ2pedGUGHdRY8upI7iQkGIAjsmNKExIIc7oPCiFO5d23XXsuV
lNjHie84Ty7mimuGn9kCX0GzJAHOJBV1cVAannZ+SA+PxcsIez3wAt1KxQIkfw6o
3vzanOICnGhZ22SFyib1h+0OveVXshJc3DeWlgiDxQN2Ox8BUN2KBFs=
-----END RSA PRIVATE KEY-----

27
d2utmpa09000 Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAnIuKMu05Sh8vXfPuLJYZuujMxPYWhm2rCN1sLei6q7yul9I7
VQgPtOJwVqAR+5vvFCa3epqpXUrDlRE4mRS5uLDZfeTJioq1h5qEnictdsMqL0F2
JMmER9E+CdpQ52uiW4Aj7mmaYCKvPLMW/2fEVX/X40rXemjSMjPeQWpUZy/N/ZmC
cV6XzzTAZFxhA98P5uUuhoMV/Faz9XAujfpF2qOZ8nLWahWQEG7Y9dtiwHhTVjel
tBIcuZsdVRExSCPofb0idi8AzRza2AT1diDrSf7UPGo0qHOtGzbyYybYJXf4Xtyp
Zq4I7SnAuAJK9QZnoJvoiOKYNlYFJ6aHE3Q32wIDAQABAoIBAAg70qYBEi1S3JPt
e45+ypWpHvQRGXgylndd5g24GvFjeC9mEFbVmLXj3xK/UpLQTc/ahXX+YoAUqZrS
kA6FJ4uOSbI0cWFHEGs0dls3Jk4Dz9kycTtYGgwI9mFgSTcS0zRK1hj5FvSNfngL
117Rn2L72WgMDK9UihG35q28IPpYVUTN7W+qU5YdG9m5KutBjmq9lStc6eeHqMYH
EBo3WwMh43oBhcqbebowgQLIkQTcnVdDwsjT8GYEI7onH4SnQWapch7ogXERu34w
SDNhcQ5N4gSV/Urj5+RuA78s3eKb3zZMW3lLvmr4re6BZWa/E6XmYq8k2KAB12TX
5QaYqnECgYEAzlhlLMPXuOqcQp1O1TyVNxWwJ9Q8TqhLjnbFASLCzFU2E0lup0mH
2wK0cL8KhljT6rYzKFFp2ik5+1TzHKxEvnyzB89IJ3z/5e0AYssyv1oRnzMx9amg
+04BxP4iAo1Fs9xN60PhsjHfIBj8jH3EJcla0G/zY0JE510cDRCa/YkCgYEAwjdG
JBjva6vgwZiiZ5QoOmH0WIsOnNB5VjzOONXUrpYSNMBDGougnt9eOeyUbAGgPBLT
10eR9oR06DLacn/jw75u07NCBfqxTSdW+xziG54DnK24vONBS4KmbA/v4u1mMaIn
OxRfx++3lcOvrMeUqjA5ZrUUW5VXV/dNg0IStUMCgYEAxSEptzR6GMz576H9ODYi
j3eGzOYznymk1TueRdGBrFgTyyUyM1tKEO9qlvPMCEFAY1EhWnk82RDdtcCYaWIi
YqEbIHDki+UdS/m5jqh1mN1hTGhKaFlf0/XYNuxabXmth4EGZ6Z4Lhb7BN0aGNXl
1/ufaNYq/T7IOQh4zfp5N5ECgYEAgcpYmIUFc4owsJAlcF0FqUaO+aEsicWUYPpP
wpG8CVSHJDOcZKANHj8eBE3DPo6zm5Hlekf9FqacThS2AbDP8J9SBy4ToFVRqcLx
kO1TeatWtJ0wCSNCHolYWH0qDhgipGa+GvBZtg7QPEjDHQ9fnYCOy8GVskKSVVoS
tfYw9GsCgYEAjhgQ2pedGUGHdRY8upI7iQkGIAjsmNKExIIc7oPCiFO5d23XXsuV
lNjHie84Ty7mimuGn9kCX0GzJAHOJBV1cVAannZ+SA+PxcsIez3wAt1KxQIkfw6o
3vzanOICnGhZ22SFyib1h+0OveVXshJc3DeWlgiDxQN2Ox8BUN2KBFs=
-----END RSA PRIVATE KEY-----

27
d2utmpa09040 Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAnIuKMu05Sh8vXfPuLJYZuujMxPYWhm2rCN1sLei6q7yul9I7
VQgPtOJwVqAR+5vvFCa3epqpXUrDlRE4mRS5uLDZfeTJioq1h5qEnictdsMqL0F2
JMmER9E+CdpQ52uiW4Aj7mmaYCKvPLMW/2fEVX/X40rXemjSMjPeQWpUZy/N/ZmC
cV6XzzTAZFxhA98P5uUuhoMV/Faz9XAujfpF2qOZ8nLWahWQEG7Y9dtiwHhTVjel
tBIcuZsdVRExSCPofb0idi8AzRza2AT1diDrSf7UPGo0qHOtGzbyYybYJXf4Xtyp
Zq4I7SnAuAJK9QZnoJvoiOKYNlYFJ6aHE3Q32wIDAQABAoIBAAg70qYBEi1S3JPt
e45+ypWpHvQRGXgylndd5g24GvFjeC9mEFbVmLXj3xK/UpLQTc/ahXX+YoAUqZrS
kA6FJ4uOSbI0cWFHEGs0dls3Jk4Dz9kycTtYGgwI9mFgSTcS0zRK1hj5FvSNfngL
117Rn2L72WgMDK9UihG35q28IPpYVUTN7W+qU5YdG9m5KutBjmq9lStc6eeHqMYH
EBo3WwMh43oBhcqbebowgQLIkQTcnVdDwsjT8GYEI7onH4SnQWapch7ogXERu34w
SDNhcQ5N4gSV/Urj5+RuA78s3eKb3zZMW3lLvmr4re6BZWa/E6XmYq8k2KAB12TX
5QaYqnECgYEAzlhlLMPXuOqcQp1O1TyVNxWwJ9Q8TqhLjnbFASLCzFU2E0lup0mH
2wK0cL8KhljT6rYzKFFp2ik5+1TzHKxEvnyzB89IJ3z/5e0AYssyv1oRnzMx9amg
+04BxP4iAo1Fs9xN60PhsjHfIBj8jH3EJcla0G/zY0JE510cDRCa/YkCgYEAwjdG
JBjva6vgwZiiZ5QoOmH0WIsOnNB5VjzOONXUrpYSNMBDGougnt9eOeyUbAGgPBLT
10eR9oR06DLacn/jw75u07NCBfqxTSdW+xziG54DnK24vONBS4KmbA/v4u1mMaIn
OxRfx++3lcOvrMeUqjA5ZrUUW5VXV/dNg0IStUMCgYEAxSEptzR6GMz576H9ODYi
j3eGzOYznymk1TueRdGBrFgTyyUyM1tKEO9qlvPMCEFAY1EhWnk82RDdtcCYaWIi
YqEbIHDki+UdS/m5jqh1mN1hTGhKaFlf0/XYNuxabXmth4EGZ6Z4Lhb7BN0aGNXl
1/ufaNYq/T7IOQh4zfp5N5ECgYEAgcpYmIUFc4owsJAlcF0FqUaO+aEsicWUYPpP
wpG8CVSHJDOcZKANHj8eBE3DPo6zm5Hlekf9FqacThS2AbDP8J9SBy4ToFVRqcLx
kO1TeatWtJ0wCSNCHolYWH0qDhgipGa+GvBZtg7QPEjDHQ9fnYCOy8GVskKSVVoS
tfYw9GsCgYEAjhgQ2pedGUGHdRY8upI7iQkGIAjsmNKExIIc7oPCiFO5d23XXsuV
lNjHie84Ty7mimuGn9kCX0GzJAHOJBV1cVAannZ+SA+PxcsIez3wAt1KxQIkfw6o
3vzanOICnGhZ22SFyib1h+0OveVXshJc3DeWlgiDxQN2Ox8BUN2KBFs=
-----END RSA PRIVATE KEY-----

5
d2utmpa09244 Normal file
View File

@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOrwk5LCELxzRGufJcI3ogOmaqYwNGYg0KIZqnQysKsPoAoGCCqGSM49
AwEHoUQDQgAEXkGf9akhGRCleBfum8S5D11uWdOngABaPtFj7OHGk4u8gncSGf3g
uQj9j5MSCt9BV57GXKXgb0Xu0TH0wXbNqA==
-----END EC PRIVATE KEY-----

7
d2utmpa09344 Normal file
View File

@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACDsm6kHU3O2x/KuzcbAUhZGYsoc4Gn6YiFcuulsx4gsyAAAAJAJSj5MCUo+
TAAAAAtzc2gtZWQyNTUxOQAAACDsm6kHU3O2x/KuzcbAUhZGYsoc4Gn6YiFcuulsx4gsyA
AAAECGe69spV/5acdoNqiARzB79o5ASCy2SQ6Ng7SWENmDguybqQdTc7bH8q7NxsBSFkZi
yhzgafpiIVy66WzHiCzIAAAABkBvYXNpcwECAwQFBgc=
-----END OPENSSH PRIVATE KEY-----

27
d2utmpa09348 Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAupkFt/flL8uwzwiXemhydEVw5y/jQu1bAvklAL6LMjMG9z68
YxaG8iduMpehxKXR75pWzZIqTm3sN0/3azUNECvx+Frf+5pCHcTeiGxfYaRWi7fB
cndMne3KXcRh42FRI7lAR4LDiP9pNld82cf3N9V/O2Y8G9fCTPAyjZP3sCgY9TGV
Q3AXSFkE+VjkT5qQlVewnixNU4l3OW9v9sDTjgXSj7g2AQxnT0oag/dSGl5iLPSh
VKOIxQRP1fiun3rFJ4LnZ6LinYRc0qJKF2yKRTcouS9k1EbUvXm8JtGZGs9sVvOg
yem0jLbjKoVA7CTmRZh4fDZ08Lkgz1FV4Zc22QIDAQABAoIBAGkkUFSZGksUO0xt
Su1ubQ+XEUczdJsBo4bJXFBPDZ/7oLEwaHZs+xz3muBnEH/9741TKhYrhisrRS7l
oESIYBP8rxuCGTNseFTN2ZaFejlKoHmZ0Sbukf1rP9wWDBJTg6TdfZrN0+AeCurT
4UXVpzeO1WJi+Pu3V4SC0/lypt5aw2F1urfoWSaUR43xiYpnjMNQ6dDvVoXA4R2X
lMvvdAimTyA3XFDQILlUz6UHH01nEDO6n3T7VjB8UxiJrV5Oyy/aREBIJRiEHf5t
dkZjVmtoKhAxKsOCyne/BZ3G1dYIGAhEM/SPqMQtPWy7U95ZaKQbF/Y5BhZb+5d6
88HG6QECgYEA3VXddhNh8Ore1rrmlG/5/hwFg9BfP74Gt+lZcmT1Gwh9EBdcn3he
xn4kBiw3m1kYyJw3wUfg/zINerqPz57EV669aVaDOVXbqTsFHOsFa74wMERYfV+/
eBn7lFdwxOXq4vfDMzq0Ph+wtFvA+C2IkQVk60PR94dJMTn5VLm26nsCgYEA19Jm
Hfvm/P/9oc4+rtkTUrs5BDHloBJ28TydZ84bI4B4n1/pJOWKrZ4y4kATic00+otW
sncOVAeFq7Nj8yJ1XRCxKnjbhR2q/FZQf8f0c5xVWh4iXRt6Zf5hVcCmkle8SV6M
vQb5zpRbzQTx+nrbut6RMbQPVHy5BIXhdzIeHbsCgYAik41bKr/8INTa+quWuL93
AO2jn+OhU5A9HskIY9kedf8DioK/rtAvdfkuta2iKRMEE9Np8E6nzyvn5kkdCBJo
GDYixI8PX+hG0Z+E2von0Lg6chLY0yJYIsb4b4iAWeKNvmLSF/OcWNsD8el9W6+f
6BXR4vBkGNBITmQy5ig7DQKBgQCcfVLOKvkyOewOhx2sano4YsjU4dk+WCUmhm0b
97Z155GO/lxvBIGpoiwDIbMJGGJxyNb0UJ9zDoE+HrU6dqHi+Vd9FGUYAIsarPtx
q+r0aUb6MR95o5L8oZayNx6Qvk0oZgZmichYofpujkdm9+6bcQaWo5j6CfWd8fWq
GAz+QQKBgHBOyyzXC7HSy+IAu/Jo3kpkgTqjYUIsmig5QKamHo/5FP8FCq4ZVR1L
CYrpCVzbvjAjBnSm1/3UngjS3PPldUYjGIbez3gK/jJTfnzfsVghnQsZOd97YxuX
TusifzCTcDZEUIZSdxL72EpbGtkYqVeDl4SjU0ZMfSIyiEsfyDFw
-----END RSA PRIVATE KEY-----

1
d2utmpa09960 Normal file
View File

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOybqQdTc7bH8q7NxsBSFkZiyhzgafpiIVy66WzHiCzI @oasis

1
d2utmpa10036 Normal file
View File

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOybqQdTc7bH8q7NxsBSFkZiyhzgafpiIVy66WzHiCzI @oasis

View File

@ -1,4 +1,4 @@
/* $OpenBSD: deattack.c,v 1.30 2006/09/16 19:53:37 djm Exp $ */
/* $OpenBSD: deattack.c,v 1.32 2015/01/20 23:14:00 deraadt Exp $ */
/*
* Cryptographic attack detector for ssh - source code
*
@ -20,16 +20,13 @@
#include "includes.h"
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "xmalloc.h"
#include "deattack.h"
#include "log.h"
#include "crc32.h"
#include "sshbuf.h"
#include "misc.h"
/*
@ -66,7 +63,7 @@
/* Hash function (Input keys are cipher results) */
#define HASH(x) get_u32(x)
#define HASH(x) PEEK_U32(x)
#define CMP(a, b) (memcmp(a, b, SSH_BLOCKSIZE))
@ -79,10 +76,10 @@ crc_update(u_int32_t *a, u_int32_t b)
/* detect if a block is used in a particular pattern */
static int
check_crc(u_char *S, u_char *buf, u_int32_t len)
check_crc(const u_char *S, const u_char *buf, u_int32_t len)
{
u_int32_t crc;
u_char *c;
const u_char *c;
crc = 0;
for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
@ -94,36 +91,44 @@ check_crc(u_char *S, u_char *buf, u_int32_t len)
crc_update(&crc, 0);
}
}
return (crc == 0);
return crc == 0;
}
void
deattack_init(struct deattack_ctx *dctx)
{
bzero(dctx, sizeof(*dctx));
dctx->n = HASH_MINSIZE / HASH_ENTRYSIZE;
}
/* Detect a crc32 compensation attack on a packet */
int
detect_attack(u_char *buf, u_int32_t len)
detect_attack(struct deattack_ctx *dctx, const u_char *buf, u_int32_t len)
{
static u_int16_t *h = (u_int16_t *) NULL;
static u_int32_t n = HASH_MINSIZE / HASH_ENTRYSIZE;
u_int32_t i, j;
u_int32_t l, same;
u_char *c;
u_char *d;
u_int32_t i, j, l, same;
u_int16_t *tmp;
const u_char *c, *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)
len % SSH_BLOCKSIZE != 0)
return DEATTACK_ERROR;
for (l = dctx->n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2)
;
if (h == NULL) {
debug("Installing crc compensation attack detector.");
h = (u_int16_t *) xcalloc(l, HASH_ENTRYSIZE);
n = l;
if (dctx->h == NULL) {
if ((dctx->h = calloc(l, HASH_ENTRYSIZE)) == NULL)
return DEATTACK_ERROR;
dctx->n = l;
} else {
if (l > n) {
h = (u_int16_t *)xrealloc(h, l, HASH_ENTRYSIZE);
n = l;
if (l > dctx->n) {
if ((tmp = reallocarray(dctx->h, l, HASH_ENTRYSIZE))
== NULL) {
free(dctx->h);
dctx->h = NULL;
return DEATTACK_ERROR;
}
dctx->h = tmp;
dctx->n = l;
}
}
@ -132,29 +137,29 @@ detect_attack(u_char *buf, u_int32_t len)
for (d = buf; d < c; d += SSH_BLOCKSIZE) {
if (!CMP(c, d)) {
if ((check_crc(c, buf, len)))
return (DEATTACK_DETECTED);
return DEATTACK_DETECTED;
else
break;
}
}
}
return (DEATTACK_OK);
return DEATTACK_OK;
}
memset(h, HASH_UNUSEDCHAR, n * HASH_ENTRYSIZE);
memset(dctx->h, HASH_UNUSEDCHAR, dctx->n * HASH_ENTRYSIZE);
for (c = buf, same = 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 (!CMP(c, buf + h[i] * SSH_BLOCKSIZE)) {
for (i = HASH(c) & (dctx->n - 1); dctx->h[i] != HASH_UNUSED;
i = (i + 1) & (dctx->n - 1)) {
if (!CMP(c, buf + dctx->h[i] * SSH_BLOCKSIZE)) {
if (++same > MAX_IDENTICAL)
return (DEATTACK_DOS_DETECTED);
return DEATTACK_DOS_DETECTED;
if (check_crc(c, buf, len))
return (DEATTACK_DETECTED);
return DEATTACK_DETECTED;
else
break;
}
}
h[i] = j;
dctx->h[i] = j;
}
return (DEATTACK_OK);
return DEATTACK_OK;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: deattack.h,v 1.10 2006/09/16 19:53:37 djm Exp $ */
/* $OpenBSD: deattack.h,v 1.11 2015/01/19 19:52:16 markus Exp $ */
/*
* Cryptographic attack detector for ssh - Header file
@ -26,6 +26,13 @@
#define DEATTACK_OK 0
#define DEATTACK_DETECTED 1
#define DEATTACK_DOS_DETECTED 2
#define DEATTACK_ERROR 3
int detect_attack(u_char *, u_int32_t);
struct deattack_ctx {
u_int16_t *h;
u_int32_t n;
};
void deattack_init(struct deattack_ctx *);
int detect_attack(struct deattack_ctx *, const u_char *, u_int32_t);
#endif

112
defines.h
View File

@ -25,7 +25,7 @@
#ifndef _DEFINES_H
#define _DEFINES_H
/* $Id: defines.h,v 1.167 2011/06/03 01:17:49 tim Exp $ */
/* $Id: defines.h,v 1.183 2014/09/02 19:33:26 djm Exp $ */
/* Constants */
@ -87,6 +87,12 @@ enum
# define IPTOS_DSCP_EF 0xb8
#endif /* IPTOS_DSCP_EF */
#ifndef PATH_MAX
# ifdef _POSIX_PATH_MAX
# define PATH_MAX _POSIX_PATH_MAX
# endif
#endif
#ifndef MAXPATHLEN
# ifdef PATH_MAX
# define MAXPATHLEN PATH_MAX
@ -99,11 +105,16 @@ enum
# endif /* PATH_MAX */
#endif /* MAXPATHLEN */
#ifndef PATH_MAX
# ifdef _POSIX_PATH_MAX
# define PATH_MAX _POSIX_PATH_MAX
#ifndef HOST_NAME_MAX
# include "netdb.h" /* for MAXHOSTNAMELEN */
# if defined(_POSIX_HOST_NAME_MAX)
# define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
# elif defined(MAXHOSTNAMELEN)
# define HOST_NAME_MAX MAXHOSTNAMELEN
# else
# define HOST_NAME_MAX 255
# endif
#endif
#endif /* HOST_NAME_MAX */
#if defined(HAVE_DECL_MAXSYMLINKS) && HAVE_DECL_MAXSYMLINKS == 0
# define MAXSYMLINKS 5
@ -171,11 +182,6 @@ enum
# define MAP_FAILED ((void *)-1)
#endif
/* *-*-nto-qnx doesn't define this constant in the system headers */
#ifdef MISSING_NFDBITS
# define NFDBITS (8 * sizeof(unsigned long))
#endif
/*
SCO Open Server 3 has INADDR_LOOPBACK defined in rpc/rpc.h but
including rpc/rpc.h breaks Solaris 6
@ -194,11 +200,7 @@ typedef unsigned int u_int;
#endif
#ifndef HAVE_INTXX_T
# if (SIZEOF_CHAR == 1)
typedef char int8_t;
# else
# error "8 bit int type not found."
# endif
typedef signed char int8_t;
# if (SIZEOF_SHORT_INT == 2)
typedef short int int16_t;
# else
@ -231,11 +233,7 @@ typedef uint16_t u_int16_t;
typedef uint32_t u_int32_t;
# define HAVE_U_INTXX_T 1
# else
# if (SIZEOF_CHAR == 1)
typedef unsigned char u_int8_t;
# else
# error "8 bit int type not found."
# endif
# if (SIZEOF_SHORT_INT == 2)
typedef unsigned short int u_int16_t;
# else
@ -282,11 +280,30 @@ typedef unsigned long long int u_int64_t;
# endif
#endif
#ifndef HAVE_UINTXX_T
typedef u_int8_t uint8_t;
typedef u_int16_t uint16_t;
typedef u_int32_t uint32_t;
typedef u_int64_t uint64_t;
#endif
#ifndef HAVE_INTMAX_T
typedef long long intmax_t;
#endif
#ifndef HAVE_UINTMAX_T
typedef unsigned long long uintmax_t;
#endif
#ifndef HAVE_U_CHAR
typedef unsigned char u_char;
# define HAVE_U_CHAR
#endif /* HAVE_U_CHAR */
#ifndef ULLONG_MAX
# define ULLONG_MAX ((unsigned long long)-1)
#endif
#ifndef SIZE_T_MAX
#define SIZE_T_MAX ULONG_MAX
#endif /* SIZE_T_MAX */
@ -359,11 +376,19 @@ struct winsize {
};
#endif
/* *-*-nto-qnx does not define this type in the system headers */
#ifdef MISSING_FD_MASK
/* bits needed for select that may not be in the system headers */
#ifndef HAVE_FD_MASK
typedef unsigned long int fd_mask;
#endif
#if defined(HAVE_DECL_NFDBITS) && HAVE_DECL_NFDBITS == 0
# define NFDBITS (8 * sizeof(unsigned long))
#endif
#if defined(HAVE_DECL_HOWMANY) && HAVE_DECL_HOWMANY == 0
# define howmany(x,y) (((x)+((y)-1))/(y))
#endif
/* Paths */
#ifndef _PATH_BSHELL
@ -391,7 +416,7 @@ struct winsize {
/* user may have set a different path */
#if defined(_PATH_MAILDIR) && defined(MAIL_DIRECTORY)
# undef _PATH_MAILDIR MAILDIR
# undef _PATH_MAILDIR
#endif /* defined(_PATH_MAILDIR) && defined(MAIL_DIRECTORY) */
#ifdef MAIL_DIRECTORY
@ -488,11 +513,6 @@ struct winsize {
# define __nonnull__(x)
#endif
/* *-*-nto-qnx doesn't define this macro in the system headers */
#ifdef MISSING_HOWMANY
# define howmany(x,y) (((x)+((y)-1))/(y))
#endif
#ifndef OSSH_ALIGNBYTES
#define OSSH_ALIGNBYTES (sizeof(int) - 1)
#endif
@ -577,6 +597,12 @@ struct winsize {
# undef HAVE_GAI_STRERROR
#endif
#if defined(HAVE_GETADDRINFO)
# if defined(HAVE_DECL_AI_NUMERICSERV) && HAVE_DECL_AI_NUMERICSERV == 0
# define AI_NUMERICSERV 0
# endif
#endif
#if defined(BROKEN_UPDWTMPX) && defined(HAVE_UPDWTMPX)
# undef HAVE_UPDWTMPX
#endif
@ -594,10 +620,6 @@ struct winsize {
# define memmove(s1, s2, n) bcopy((s2), (s1), (n))
#endif /* !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) */
#if defined(HAVE_VHANGUP) && !defined(HAVE_DEV_PTMX)
# define USE_VHANGUP
#endif /* defined(HAVE_VHANGUP) && !defined(HAVE_DEV_PTMX) */
#ifndef GETPGRP_VOID
# include <unistd.h>
# define getpgrp() getpgrp(0)
@ -800,14 +822,34 @@ struct winsize {
# define SSH_IOBUFSZ 8192
#endif
#ifndef _NSIG
# ifdef NSIG
# define _NSIG NSIG
/*
* Platforms that have arc4random_uniform() and not arc4random_stir()
* shouldn't need the latter.
*/
#if defined(HAVE_ARC4RANDOM) && defined(HAVE_ARC4RANDOM_UNIFORM) && \
!defined(HAVE_ARC4RANDOM_STIR)
# define arc4random_stir()
#endif
#ifndef HAVE_VA_COPY
# ifdef HAVE___VA_COPY
# define va_copy(dest, src) __va_copy(dest, src)
# else
# define _NSIG 128
# define va_copy(dest, src) (dest) = (src)
# endif
#endif
#ifndef __predict_true
# if defined(__GNUC__) && \
((__GNUC__ > (2)) || (__GNUC__ == (2) && __GNUC_MINOR__ >= (96)))
# define __predict_true(exp) __builtin_expect(((exp) != 0), 1)
# define __predict_false(exp) __builtin_expect(((exp) != 0), 0)
# else
# define __predict_true(exp) ((exp) != 0)
# define __predict_false(exp) ((exp) != 0)
# endif /* gcc version */
#endif /* __predict_true */
/* WIN32_FIXME */
#ifdef _WIN32
# define CUSTOM_SYS_AUTH_PASSWD 1

208
dh.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: dh.c,v 1.48 2009/10/01 11:37:33 grunk Exp $ */
/* $OpenBSD: dh.c,v 1.57 2015/05/27 23:39:18 dtucker Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
*
@ -25,7 +25,7 @@
#include "includes.h"
#include <sys/param.h>
#include <sys/param.h> /* MIN */
#include <openssl/bn.h>
#include <openssl/dh.h>
@ -34,11 +34,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "dh.h"
#include "pathnames.h"
#include "log.h"
#include "misc.h"
#include "ssherr.h"
static int
parse_prime(int linenum, char *line, struct dhgroup *dhg)
@ -48,6 +50,7 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg)
const char *errstr = NULL;
long long n;
dhg->p = dhg->g = NULL;
cp = line;
if ((arg = strdelim(&cp)) == NULL)
return 0;
@ -59,66 +62,84 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg)
/* time */
if (cp == NULL || *arg == '\0')
goto fail;
goto truncated;
arg = strsep(&cp, " "); /* type */
if (cp == NULL || *arg == '\0')
goto fail;
goto truncated;
/* Ensure this is a safe prime */
n = strtonum(arg, 0, 5, &errstr);
if (errstr != NULL || n != MODULI_TYPE_SAFE)
if (errstr != NULL || n != MODULI_TYPE_SAFE) {
error("moduli:%d: type is not %d", linenum, MODULI_TYPE_SAFE);
goto fail;
}
arg = strsep(&cp, " "); /* tests */
if (cp == NULL || *arg == '\0')
goto fail;
goto truncated;
/* Ensure prime has been tested and is not composite */
n = strtonum(arg, 0, 0x1f, &errstr);
if (errstr != NULL ||
(n & MODULI_TESTS_COMPOSITE) || !(n & ~MODULI_TESTS_COMPOSITE))
(n & MODULI_TESTS_COMPOSITE) || !(n & ~MODULI_TESTS_COMPOSITE)) {
error("moduli:%d: invalid moduli tests flag", linenum);
goto fail;
}
arg = strsep(&cp, " "); /* tries */
if (cp == NULL || *arg == '\0')
goto fail;
goto truncated;
n = strtonum(arg, 0, 1<<30, &errstr);
if (errstr != NULL || n == 0)
if (errstr != NULL || n == 0) {
error("moduli:%d: invalid primality trial count", linenum);
goto fail;
}
strsize = strsep(&cp, " "); /* size */
if (cp == NULL || *strsize == '\0' ||
(dhg->size = (int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 ||
errstr)
errstr) {
error("moduli:%d: invalid prime length", linenum);
goto fail;
}
/* The whole group is one bit larger */
dhg->size++;
gen = strsep(&cp, " "); /* gen */
if (cp == NULL || *gen == '\0')
goto fail;
goto truncated;
prime = strsep(&cp, " "); /* prime */
if (cp != NULL || *prime == '\0')
if (cp != NULL || *prime == '\0') {
truncated:
error("moduli:%d: truncated", linenum);
goto fail;
}
if ((dhg->g = BN_new()) == NULL)
fatal("parse_prime: BN_new failed");
if ((dhg->p = BN_new()) == NULL)
fatal("parse_prime: BN_new failed");
if (BN_hex2bn(&dhg->g, gen) == 0)
goto failclean;
if ((dhg->g = BN_new()) == NULL ||
(dhg->p = BN_new()) == NULL) {
error("parse_prime: BN_new failed");
goto fail;
}
if (BN_hex2bn(&dhg->g, gen) == 0) {
error("moduli:%d: could not parse generator value", linenum);
goto fail;
}
if (BN_hex2bn(&dhg->p, prime) == 0) {
error("moduli:%d: could not parse prime value", linenum);
goto fail;
}
if (BN_num_bits(dhg->p) != dhg->size) {
error("moduli:%d: prime has wrong size: actual %d listed %d",
linenum, BN_num_bits(dhg->p), dhg->size - 1);
goto fail;
}
if (BN_cmp(dhg->g, BN_value_one()) <= 0) {
error("moduli:%d: generator is invalid", linenum);
goto fail;
}
return 1;
if (BN_hex2bn(&dhg->p, prime) == 0)
goto failclean;
if (BN_num_bits(dhg->p) != dhg->size)
goto failclean;
if (BN_is_zero(dhg->g) || BN_is_one(dhg->g))
goto failclean;
return (1);
failclean:
BN_clear_free(dhg->g);
BN_clear_free(dhg->p);
fail:
error("Bad prime description in line %d", linenum);
return (0);
if (dhg->g != NULL)
BN_clear_free(dhg->g);
if (dhg->p != NULL)
BN_clear_free(dhg->p);
dhg->g = dhg->p = NULL;
return 0;
}
DH *
@ -134,7 +155,7 @@ choose_dh(int min, int wantbits, int max)
(f = fopen(_PATH_DH_PRIMES, "r")) == NULL) {
logit("WARNING: %s does not exist, using fixed modulus",
_PATH_DH_MODULI);
return (dh_new_group14());
return (dh_new_group_fallback(max));
}
linenum = 0;
@ -162,7 +183,7 @@ choose_dh(int min, int wantbits, int max)
if (bestcount == 0) {
fclose(f);
logit("WARNING: no suitable primes in %s", _PATH_DH_PRIMES);
return (dh_new_group14());
return (dh_new_group_fallback(max));
}
linenum = 0;
@ -180,9 +201,11 @@ choose_dh(int min, int wantbits, int max)
break;
}
fclose(f);
if (linenum != which+1)
fatal("WARNING: line %d disappeared in %s, giving up",
if (linenum != which+1) {
logit("WARNING: line %d disappeared in %s, giving up",
which, _PATH_DH_PRIMES);
return (dh_new_group_fallback(max));
}
return (dh_new_group(dhg.g, dhg.p));
}
@ -231,34 +254,22 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
return 0;
}
void
int
dh_gen_key(DH *dh, int need)
{
int i, bits_set, tries = 0;
int pbits;
if (dh->p == NULL)
fatal("dh_gen_key: dh->p == NULL");
if (need > INT_MAX / 2 || 2 * need >= BN_num_bits(dh->p))
fatal("dh_gen_key: group too small: %d (2*need %d)",
BN_num_bits(dh->p), 2*need);
do {
if (dh->priv_key != NULL)
BN_clear_free(dh->priv_key);
if ((dh->priv_key = BN_new()) == NULL)
fatal("dh_gen_key: BN_new failed");
/* generate a 2*need bits random private exponent */
if (!BN_rand(dh->priv_key, 2*need, 0, 0))
fatal("dh_gen_key: BN_rand failed");
if (DH_generate_key(dh) == 0)
fatal("DH_generate_key");
for (i = 0, bits_set = 0; i <= BN_num_bits(dh->priv_key); i++)
if (BN_is_bit_set(dh->priv_key, i))
bits_set++;
debug2("dh_gen_key: priv key bits set: %d/%d",
bits_set, BN_num_bits(dh->priv_key));
if (tries++ > 10)
fatal("dh_gen_key: too many bad keys: giving up");
} while (!dh_pub_is_valid(dh, dh->pub_key));
if (need < 0 || dh->p == NULL ||
(pbits = BN_num_bits(dh->p)) <= 0 ||
need > INT_MAX / 2 || 2 * need > pbits)
return SSH_ERR_INVALID_ARGUMENT;
dh->length = MIN(need * 2, pbits - 1);
if (DH_generate_key(dh) == 0 ||
!dh_pub_is_valid(dh, dh->pub_key)) {
BN_clear_free(dh->priv_key);
return SSH_ERR_LIBCRYPTO_ERROR;
}
return 0;
}
DH *
@ -267,13 +278,12 @@ dh_new_group_asc(const char *gen, const char *modulus)
DH *dh;
if ((dh = DH_new()) == NULL)
fatal("dh_new_group_asc: DH_new");
if (BN_hex2bn(&dh->p, modulus) == 0)
fatal("BN_hex2bn p");
if (BN_hex2bn(&dh->g, gen) == 0)
fatal("BN_hex2bn g");
return NULL;
if (BN_hex2bn(&dh->p, modulus) == 0 ||
BN_hex2bn(&dh->g, gen) == 0) {
DH_free(dh);
return NULL;
}
return (dh);
}
@ -288,7 +298,7 @@ dh_new_group(BIGNUM *gen, BIGNUM *modulus)
DH *dh;
if ((dh = DH_new()) == NULL)
fatal("dh_new_group: DH_new");
return NULL;
dh->p = modulus;
dh->g = gen;
@ -328,19 +338,61 @@ dh_new_group14(void)
return (dh_new_group_asc(gen, group14));
}
/*
* 4k bit fallback group used by DH-GEX if moduli file cannot be read.
* Source: MODP group 16 from RFC3526.
*/
DH *
dh_new_group_fallback(int max)
{
static char *gen = "2", *group16 =
"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
"29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
"EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
"E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
"EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
"C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
"83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
"670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
"E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
"DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
"15728E5A" "8AAAC42D" "AD33170D" "04507A33" "A85521AB" "DF1CBA64"
"ECFB8504" "58DBEF0A" "8AEA7157" "5D060C7D" "B3970F85" "A6E1E4C7"
"ABF5AE8C" "DB0933D7" "1E8C94E0" "4A25619D" "CEE3D226" "1AD2EE6B"
"F12FFA06" "D98A0864" "D8760273" "3EC86A64" "521F2B18" "177B200C"
"BBE11757" "7A615D6C" "770988C0" "BAD946E2" "08E24FA0" "74E5AB31"
"43DB5BFC" "E0FD108E" "4B82D120" "A9210801" "1A723C12" "A787E6D7"
"88719A10" "BDBA5B26" "99C32718" "6AF4E23C" "1A946834" "B6150BDA"
"2583E9CA" "2AD44CE8" "DBBBC2DB" "04DE8EF9" "2E8EFC14" "1FBECAA6"
"287C5947" "4E6BC05D" "99B2964F" "A090C3A2" "233BA186" "515BE7ED"
"1F612970" "CEE2D7AF" "B81BDD76" "2170481C" "D0069127" "D5B05AA9"
"93B4EA98" "8D8FDDC1" "86FFB7DC" "90A6C08F" "4DF435C9" "34063199"
"FFFFFFFF" "FFFFFFFF";
if (max < 4096) {
debug3("requested max size %d, using 2k bit group 14", max);
return dh_new_group14();
}
debug3("using 4k bit group 16");
return (dh_new_group_asc(gen, group16));
}
/*
* Estimates the group order for a Diffie-Hellman group that has an
* attack complexity approximately the same as O(2**bits). Estimate
* with: O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3)))
* attack complexity approximately the same as O(2**bits).
* Values from NIST Special Publication 800-57: Recommendation for Key
* Management Part 1 (rev 3) limited by the recommended maximum value
* from RFC4419 section 3.
*/
int
u_int
dh_estimate(int bits)
{
if (bits <= 112)
return 2048;
if (bits <= 128)
return (1024); /* O(2**86) */
return 3072;
if (bits <= 192)
return (2048); /* O(2**116) */
return (4096); /* O(2**156) */
return 7680;
return 8192;
}

8
dh.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: dh.h,v 1.10 2008/06/26 09:19:40 djm Exp $ */
/* $OpenBSD: dh.h,v 1.13 2015/05/27 23:39:18 dtucker Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
@ -37,12 +37,14 @@ DH *dh_new_group_asc(const char *, const char *);
DH *dh_new_group(BIGNUM *, BIGNUM *);
DH *dh_new_group1(void);
DH *dh_new_group14(void);
DH *dh_new_group_fallback(int);
void dh_gen_key(DH *, int);
int dh_gen_key(DH *, int);
int dh_pub_is_valid(DH *, BIGNUM *);
int dh_estimate(int);
u_int dh_estimate(int);
/* Min and max values from RFC4419. */
#define DH_GRP_MIN 1024
#define DH_GRP_MAX 8192

264
digest-libc.c Normal file
View File

@ -0,0 +1,264 @@
/* $OpenBSD: digest-libc.c,v 1.5 2015/05/05 02:48:17 jsg Exp $ */
/*
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
* Copyright (c) 2014 Markus Friedl. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#ifndef WITH_OPENSSL
#include <sys/types.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#if 0
#include <md5.h>
#include <rmd160.h>
#include <sha1.h>
#include <sha2.h>
#endif
#include "ssherr.h"
#include "sshbuf.h"
#include "digest.h"
typedef void md_init_fn(void *mdctx);
typedef void md_update_fn(void *mdctx, const u_int8_t *m, size_t mlen);
typedef void md_final_fn(u_int8_t[], void *mdctx);
struct ssh_digest_ctx {
int alg;
void *mdctx;
};
struct ssh_digest {
int id;
const char *name;
size_t block_len;
size_t digest_len;
size_t ctx_len;
md_init_fn *md_init;
md_update_fn *md_update;
md_final_fn *md_final;
};
/* NB. Indexed directly by algorithm number */
const struct ssh_digest digests[SSH_DIGEST_MAX] = {
{
SSH_DIGEST_MD5,
"MD5",
MD5_BLOCK_LENGTH,
MD5_DIGEST_LENGTH,
sizeof(MD5_CTX),
(md_init_fn *) MD5Init,
(md_update_fn *) MD5Update,
(md_final_fn *) MD5Final
},
{
SSH_DIGEST_RIPEMD160,
"RIPEMD160",
RMD160_BLOCK_LENGTH,
RMD160_DIGEST_LENGTH,
sizeof(RMD160_CTX),
(md_init_fn *) RMD160Init,
(md_update_fn *) RMD160Update,
(md_final_fn *) RMD160Final
},
{
SSH_DIGEST_SHA1,
"SHA1",
SHA1_BLOCK_LENGTH,
SHA1_DIGEST_LENGTH,
sizeof(SHA1_CTX),
(md_init_fn *) SHA1Init,
(md_update_fn *) SHA1Update,
(md_final_fn *) SHA1Final
},
{
SSH_DIGEST_SHA256,
"SHA256",
SHA256_BLOCK_LENGTH,
SHA256_DIGEST_LENGTH,
sizeof(SHA256_CTX),
(md_init_fn *) SHA256_Init,
(md_update_fn *) SHA256_Update,
(md_final_fn *) SHA256_Final
},
{
SSH_DIGEST_SHA384,
"SHA384",
SHA384_BLOCK_LENGTH,
SHA384_DIGEST_LENGTH,
sizeof(SHA384_CTX),
(md_init_fn *) SHA384_Init,
(md_update_fn *) SHA384_Update,
(md_final_fn *) SHA384_Final
},
{
SSH_DIGEST_SHA512,
"SHA512",
SHA512_BLOCK_LENGTH,
SHA512_DIGEST_LENGTH,
sizeof(SHA512_CTX),
(md_init_fn *) SHA512_Init,
(md_update_fn *) SHA512_Update,
(md_final_fn *) SHA512_Final
}
};
static const struct ssh_digest *
ssh_digest_by_alg(int alg)
{
if (alg < 0 || alg >= SSH_DIGEST_MAX)
return NULL;
if (digests[alg].id != alg) /* sanity */
return NULL;
return &(digests[alg]);
}
int
ssh_digest_alg_by_name(const char *name)
{
int alg;
for (alg = 0; alg < SSH_DIGEST_MAX; alg++) {
if (strcasecmp(name, digests[alg].name) == 0)
return digests[alg].id;
}
return -1;
}
const char *
ssh_digest_alg_name(int alg)
{
const struct ssh_digest *digest = ssh_digest_by_alg(alg);
return digest == NULL ? NULL : digest->name;
}
size_t
ssh_digest_bytes(int alg)
{
const struct ssh_digest *digest = ssh_digest_by_alg(alg);
return digest == NULL ? 0 : digest->digest_len;
}
size_t
ssh_digest_blocksize(struct ssh_digest_ctx *ctx)
{
const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
return digest == NULL ? 0 : digest->block_len;
}
struct ssh_digest_ctx *
ssh_digest_start(int alg)
{
const struct ssh_digest *digest = ssh_digest_by_alg(alg);
struct ssh_digest_ctx *ret;
if (digest == NULL || (ret = calloc(1, sizeof(*ret))) == NULL)
return NULL;
if ((ret->mdctx = calloc(1, digest->ctx_len)) == NULL) {
free(ret);
return NULL;
}
ret->alg = alg;
digest->md_init(ret->mdctx);
return ret;
}
int
ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
{
const struct ssh_digest *digest = ssh_digest_by_alg(from->alg);
if (digest == NULL || from->alg != to->alg)
return SSH_ERR_INVALID_ARGUMENT;
memcpy(to->mdctx, from->mdctx, digest->ctx_len);
return 0;
}
int
ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
{
const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
if (digest == NULL)
return SSH_ERR_INVALID_ARGUMENT;
digest->md_update(ctx->mdctx, m, mlen);
return 0;
}
int
ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const struct sshbuf *b)
{
return ssh_digest_update(ctx, sshbuf_ptr(b), sshbuf_len(b));
}
int
ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
{
const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
if (digest == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if (dlen > UINT_MAX)
return SSH_ERR_INVALID_ARGUMENT;
if (dlen < digest->digest_len) /* No truncation allowed */
return SSH_ERR_INVALID_ARGUMENT;
digest->md_final(d, ctx->mdctx);
return 0;
}
void
ssh_digest_free(struct ssh_digest_ctx *ctx)
{
const struct ssh_digest *digest;
if (ctx != NULL) {
digest = ssh_digest_by_alg(ctx->alg);
if (digest) {
explicit_bzero(ctx->mdctx, digest->ctx_len);
free(ctx->mdctx);
explicit_bzero(ctx, sizeof(*ctx));
free(ctx);
}
}
}
int
ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen)
{
struct ssh_digest_ctx *ctx = ssh_digest_start(alg);
if (ctx == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if (ssh_digest_update(ctx, m, mlen) != 0 ||
ssh_digest_final(ctx, d, dlen) != 0)
return SSH_ERR_INVALID_ARGUMENT;
ssh_digest_free(ctx);
return 0;
}
int
ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen)
{
return ssh_digest_memory(alg, sshbuf_ptr(b), sshbuf_len(b), d, dlen);
}
#endif /* !WITH_OPENSSL */

205
digest-openssl.c Normal file
View File

@ -0,0 +1,205 @@
/* $OpenBSD: digest-openssl.c,v 1.5 2014/12/21 22:27:56 djm Exp $ */
/*
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#ifdef WITH_OPENSSL
#include <sys/types.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include "openbsd-compat/openssl-compat.h"
#include "sshbuf.h"
#include "digest.h"
#include "ssherr.h"
#ifndef HAVE_EVP_RIPEMD160
# define EVP_ripemd160 NULL
#endif /* HAVE_EVP_RIPEMD160 */
#ifndef HAVE_EVP_SHA256
# define EVP_sha256 NULL
# define EVP_sha384 NULL
# define EVP_sha512 NULL
#endif /* HAVE_EVP_SHA256 */
struct ssh_digest_ctx {
int alg;
EVP_MD_CTX mdctx;
};
struct ssh_digest {
int id;
const char *name;
size_t digest_len;
const EVP_MD *(*mdfunc)(void);
};
/* NB. Indexed directly by algorithm number */
const struct ssh_digest digests[] = {
{ SSH_DIGEST_MD5, "MD5", 16, EVP_md5 },
{ SSH_DIGEST_RIPEMD160, "RIPEMD160", 20, EVP_ripemd160 },
{ SSH_DIGEST_SHA1, "SHA1", 20, EVP_sha1 },
{ SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 },
{ SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 },
{ SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 },
{ -1, NULL, 0, NULL },
};
static const struct ssh_digest *
ssh_digest_by_alg(int alg)
{
if (alg < 0 || alg >= SSH_DIGEST_MAX)
return NULL;
if (digests[alg].id != alg) /* sanity */
return NULL;
if (digests[alg].mdfunc == NULL)
return NULL;
return &(digests[alg]);
}
int
ssh_digest_alg_by_name(const char *name)
{
int alg;
for (alg = 0; digests[alg].id != -1; alg++) {
if (strcasecmp(name, digests[alg].name) == 0)
return digests[alg].id;
}
return -1;
}
const char *
ssh_digest_alg_name(int alg)
{
const struct ssh_digest *digest = ssh_digest_by_alg(alg);
return digest == NULL ? NULL : digest->name;
}
size_t
ssh_digest_bytes(int alg)
{
const struct ssh_digest *digest = ssh_digest_by_alg(alg);
return digest == NULL ? 0 : digest->digest_len;
}
size_t
ssh_digest_blocksize(struct ssh_digest_ctx *ctx)
{
return EVP_MD_CTX_block_size(&ctx->mdctx);
}
struct ssh_digest_ctx *
ssh_digest_start(int alg)
{
const struct ssh_digest *digest = ssh_digest_by_alg(alg);
struct ssh_digest_ctx *ret;
if (digest == NULL || ((ret = calloc(1, sizeof(*ret))) == NULL))
return NULL;
ret->alg = alg;
EVP_MD_CTX_init(&ret->mdctx);
if (EVP_DigestInit_ex(&ret->mdctx, digest->mdfunc(), NULL) != 1) {
free(ret);
return NULL;
}
return ret;
}
int
ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
{
if (from->alg != to->alg)
return SSH_ERR_INVALID_ARGUMENT;
/* we have bcopy-style order while openssl has memcpy-style */
if (!EVP_MD_CTX_copy_ex(&to->mdctx, &from->mdctx))
return SSH_ERR_LIBCRYPTO_ERROR;
return 0;
}
int
ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
{
if (EVP_DigestUpdate(&ctx->mdctx, m, mlen) != 1)
return SSH_ERR_LIBCRYPTO_ERROR;
return 0;
}
int
ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const struct sshbuf *b)
{
return ssh_digest_update(ctx, sshbuf_ptr(b), sshbuf_len(b));
}
int
ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
{
const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
u_int l = dlen;
if (dlen > UINT_MAX)
return SSH_ERR_INVALID_ARGUMENT;
if (dlen < digest->digest_len) /* No truncation allowed */
return SSH_ERR_INVALID_ARGUMENT;
if (EVP_DigestFinal_ex(&ctx->mdctx, d, &l) != 1)
return SSH_ERR_LIBCRYPTO_ERROR;
if (l != digest->digest_len) /* sanity */
return SSH_ERR_INTERNAL_ERROR;
return 0;
}
void
ssh_digest_free(struct ssh_digest_ctx *ctx)
{
if (ctx != NULL) {
EVP_MD_CTX_cleanup(&ctx->mdctx);
explicit_bzero(ctx, sizeof(*ctx));
free(ctx);
}
}
int
ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen)
{
const struct ssh_digest *digest = ssh_digest_by_alg(alg);
u_int mdlen;
if (digest == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if (dlen > UINT_MAX)
return SSH_ERR_INVALID_ARGUMENT;
if (dlen < digest->digest_len)
return SSH_ERR_INVALID_ARGUMENT;
mdlen = dlen;
if (!EVP_Digest(m, mlen, d, &mdlen, digest->mdfunc(), NULL))
return SSH_ERR_LIBCRYPTO_ERROR;
return 0;
}
int
ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen)
{
return ssh_digest_memory(alg, sshbuf_ptr(b), sshbuf_len(b), d, dlen);
}
#endif /* WITH_OPENSSL */

71
digest.h Normal file
View File

@ -0,0 +1,71 @@
/* $OpenBSD: digest.h,v 1.7 2014/12/21 22:27:56 djm Exp $ */
/*
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _DIGEST_H
#define _DIGEST_H
/* Maximum digest output length */
#define SSH_DIGEST_MAX_LENGTH 64
/* Digest algorithms */
#define SSH_DIGEST_MD5 0
#define SSH_DIGEST_RIPEMD160 1
#define SSH_DIGEST_SHA1 2
#define SSH_DIGEST_SHA256 3
#define SSH_DIGEST_SHA384 4
#define SSH_DIGEST_SHA512 5
#define SSH_DIGEST_MAX 6
struct sshbuf;
struct ssh_digest_ctx;
/* Looks up a digest algorithm by name */
int ssh_digest_alg_by_name(const char *name);
/* Returns the algorithm name for a digest identifier */
const char *ssh_digest_alg_name(int alg);
/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */
size_t ssh_digest_bytes(int alg);
/* Returns the block size of the digest, e.g. for implementing HMAC */
size_t ssh_digest_blocksize(struct ssh_digest_ctx *ctx);
/* Copies internal state of digest of 'from' to 'to' */
int ssh_digest_copy_state(struct ssh_digest_ctx *from,
struct ssh_digest_ctx *to);
/* One-shot API */
int ssh_digest_memory(int alg, const void *m, size_t mlen,
u_char *d, size_t dlen)
__attribute__((__bounded__(__buffer__, 2, 3)))
__attribute__((__bounded__(__buffer__, 4, 5)));
int ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen)
__attribute__((__bounded__(__buffer__, 3, 4)));
/* Update API */
struct ssh_digest_ctx *ssh_digest_start(int alg);
int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
__attribute__((__bounded__(__buffer__, 2, 3)));
int ssh_digest_update_buffer(struct ssh_digest_ctx *ctx,
const struct sshbuf *b);
int ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
__attribute__((__bounded__(__buffer__, 2, 3)));
void ssh_digest_free(struct ssh_digest_ctx *ctx);
#endif /* _DIGEST_H */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: dispatch.c,v 1.22 2008/10/31 15:05:34 stevesk Exp $ */
/* $OpenBSD: dispatch.c,v 1.27 2015/05/01 07:10:01 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -36,69 +36,107 @@
#include "dispatch.h"
#include "packet.h"
#include "compat.h"
#include "ssherr.h"
#define DISPATCH_MAX 255
dispatch_fn *dispatch[DISPATCH_MAX];
void
dispatch_protocol_error(int type, u_int32_t seq, void *ctxt)
int
dispatch_protocol_error(int type, u_int32_t seq, void *ctx)
{
struct ssh *ssh = active_state; /* XXX */
int r;
logit("dispatch_protocol_error: type %d seq %u", type, seq);
if (!compat20)
fatal("protocol error");
packet_start(SSH2_MSG_UNIMPLEMENTED);
packet_put_int(seq);
packet_send();
packet_write_wait();
if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
(r = sshpkt_put_u32(ssh, seq)) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
sshpkt_fatal(ssh, __func__, r);
return 0;
}
void
dispatch_protocol_ignore(int type, u_int32_t seq, void *ctxt)
int
dispatch_protocol_ignore(int type, u_int32_t seq, void *ssh)
{
logit("dispatch_protocol_ignore: type %d seq %u", type, seq);
return 0;
}
void
dispatch_init(dispatch_fn *dflt)
ssh_dispatch_init(struct ssh *ssh, dispatch_fn *dflt)
{
u_int i;
for (i = 0; i < DISPATCH_MAX; i++)
dispatch[i] = dflt;
ssh->dispatch[i] = dflt;
}
void
dispatch_range(u_int from, u_int to, dispatch_fn *fn)
ssh_dispatch_range(struct ssh *ssh, u_int from, u_int to, dispatch_fn *fn)
{
u_int i;
for (i = from; i <= to; i++) {
if (i >= DISPATCH_MAX)
break;
dispatch[i] = fn;
ssh->dispatch[i] = fn;
}
}
void
dispatch_set(int type, dispatch_fn *fn)
{
dispatch[type] = fn;
}
void
dispatch_run(int mode, volatile sig_atomic_t *done, void *ctxt)
{
for (;;) {
int type;
u_int32_t seqnr;
void
ssh_dispatch_set(struct ssh *ssh, int type, dispatch_fn *fn)
{
ssh->dispatch[type] = fn;
}
int
ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done,
void *ctxt)
{
int r;
u_char type;
u_int32_t seqnr;
for (;;) {
if (mode == DISPATCH_BLOCK) {
type = packet_read_seqnr(&seqnr);
r = ssh_packet_read_seqnr(ssh, &type, &seqnr);
if (r != 0)
return r;
} else {
type = packet_read_poll_seqnr(&seqnr);
r = ssh_packet_read_poll_seqnr(ssh, &type, &seqnr);
if (r != 0)
return r;
if (type == SSH_MSG_NONE)
return;
return 0;
}
if (type > 0 && type < DISPATCH_MAX &&
ssh->dispatch[type] != NULL) {
if (ssh->dispatch_skip_packets) {
debug2("skipped packet (type %u)", type);
ssh->dispatch_skip_packets--;
continue;
}
/* XXX 'ssh' will replace 'ctxt' later */
r = (*ssh->dispatch[type])(type, seqnr, ctxt);
if (r != 0)
return r;
} else {
r = sshpkt_disconnect(ssh,
"protocol error: rcvd type %d", type);
if (r != 0)
return r;
return SSH_ERR_DISCONNECTED;
}
if (type > 0 && type < DISPATCH_MAX && dispatch[type] != NULL)
(*dispatch[type])(type, seqnr, ctxt);
else
packet_disconnect("protocol error: rcvd type %d", type);
if (done != NULL && *done)
return;
return 0;
}
}
void
ssh_dispatch_run_fatal(struct ssh *ssh, int mode, volatile sig_atomic_t *done,
void *ctxt)
{
int r;
if ((r = ssh_dispatch_run(ssh, mode, done, ctxt)) != 0)
sshpkt_fatal(ssh, __func__, r);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: dispatch.h,v 1.11 2006/04/20 09:27:09 djm Exp $ */
/* $OpenBSD: dispatch.h,v 1.12 2015/01/19 20:07:45 markus Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -24,18 +24,35 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <signal.h>
#ifndef DISPATCH_H
#define DISPATCH_H
#define DISPATCH_MAX 255
enum {
DISPATCH_BLOCK,
DISPATCH_NONBLOCK
};
typedef void dispatch_fn(int, u_int32_t, void *);
struct ssh;
void dispatch_init(dispatch_fn *);
void dispatch_set(int, dispatch_fn *);
void dispatch_range(u_int, u_int, dispatch_fn *);
void dispatch_run(int, volatile sig_atomic_t *, void *);
void dispatch_protocol_error(int, u_int32_t, void *);
void dispatch_protocol_ignore(int, u_int32_t, void *);
typedef int dispatch_fn(int, u_int32_t, void *);
int dispatch_protocol_error(int, u_int32_t, void *);
int dispatch_protocol_ignore(int, u_int32_t, void *);
void ssh_dispatch_init(struct ssh *, dispatch_fn *);
void ssh_dispatch_set(struct ssh *, int, dispatch_fn *);
void ssh_dispatch_range(struct ssh *, u_int, u_int, dispatch_fn *);
int ssh_dispatch_run(struct ssh *, int, volatile sig_atomic_t *, void *);
void ssh_dispatch_run_fatal(struct ssh *, int, volatile sig_atomic_t *, void *);
#define dispatch_init(dflt) \
ssh_dispatch_init(active_state, (dflt))
#define dispatch_range(from, to, fn) \
ssh_dispatch_range(active_state, (from), (to), (fn))
#define dispatch_set(type, fn) \
ssh_dispatch_set(active_state, (type), (fn))
#define dispatch_run(mode, done, ctxt) \
ssh_dispatch_run_fatal(active_state, (mode), (done), (ctxt))
#endif

139
dns.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: dns.c,v 1.27 2010/08/31 11:54:45 djm Exp $ */
/* $OpenBSD: dns.c,v 1.35 2015/08/20 22:32:42 deraadt Exp $ */
/*
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
@ -34,11 +34,15 @@
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include "xmalloc.h"
#include "key.h"
#include "sshkey.h"
#include "ssherr.h"
#include "dns.h"
#include "log.h"
#include "digest.h"
static const char *errset_text[] = {
"success", /* 0 ERRSET_SUCCESS */
@ -75,30 +79,55 @@ dns_result_totext(unsigned int res)
*/
static int
dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
u_char **digest, u_int *digest_len, Key *key)
u_char **digest, size_t *digest_len, struct sshkey *key)
{
int success = 0;
int r, success = 0;
int fp_alg = -1;
switch (key->type) {
case KEY_RSA:
*algorithm = SSHFP_KEY_RSA;
if (!*digest_type)
*digest_type = SSHFP_HASH_SHA1;
break;
case KEY_DSA:
*algorithm = SSHFP_KEY_DSA;
if (!*digest_type)
*digest_type = SSHFP_HASH_SHA1;
break;
case KEY_ECDSA:
*algorithm = SSHFP_KEY_ECDSA;
if (!*digest_type)
*digest_type = SSHFP_HASH_SHA256;
break;
case KEY_ED25519:
*algorithm = SSHFP_KEY_ED25519;
if (!*digest_type)
*digest_type = SSHFP_HASH_SHA256;
break;
/* XXX KEY_ECDSA */
default:
*algorithm = SSHFP_KEY_RESERVED; /* 0 */
*digest_type = SSHFP_HASH_RESERVED; /* 0 */
}
if (*algorithm) {
*digest_type = SSHFP_HASH_SHA1;
*digest = key_fingerprint_raw(key, SSH_FP_SHA1, digest_len);
if (*digest == NULL)
fatal("dns_read_key: null from key_fingerprint_raw()");
switch (*digest_type) {
case SSHFP_HASH_SHA1:
fp_alg = SSH_DIGEST_SHA1;
break;
case SSHFP_HASH_SHA256:
fp_alg = SSH_DIGEST_SHA256;
break;
default:
*digest_type = SSHFP_HASH_RESERVED; /* 0 */
}
if (*algorithm && *digest_type) {
if ((r = sshkey_fingerprint_raw(key, fp_alg, digest,
digest_len)) != 0)
fatal("%s: sshkey_fingerprint_raw: %s", __func__,
ssh_err(r));
success = 1;
} else {
*digest_type = SSHFP_HASH_RESERVED;
*digest = NULL;
*digest_len = 0;
success = 0;
@ -112,7 +141,7 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
*/
static int
dns_read_rdata(u_int8_t *algorithm, u_int8_t *digest_type,
u_char **digest, u_int *digest_len, u_char *rdata, int rdata_len)
u_char **digest, size_t *digest_len, u_char *rdata, int rdata_len)
{
int success = 0;
@ -125,7 +154,7 @@ dns_read_rdata(u_int8_t *algorithm, u_int8_t *digest_type,
*digest_len = rdata_len - 2;
if (*digest_len > 0) {
*digest = (u_char *) xmalloc(*digest_len);
*digest = xmalloc(*digest_len);
memcpy(*digest, rdata + 2, *digest_len);
} else {
*digest = (u_char *)xstrdup("");
@ -173,7 +202,7 @@ is_numeric_hostname(const char *hostname)
*/
int
verify_host_key_dns(const char *hostname, struct sockaddr *address,
Key *hostkey, int *flags)
struct sshkey *hostkey, int *flags)
{
#ifndef WIN32_FIXME
u_int counter;
@ -181,14 +210,14 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
struct rrsetinfo *fingerprints = NULL;
u_int8_t hostkey_algorithm;
u_int8_t hostkey_digest_type;
u_int8_t hostkey_digest_type = SSHFP_HASH_RESERVED;
u_char *hostkey_digest;
u_int hostkey_digest_len;
size_t hostkey_digest_len;
u_int8_t dnskey_algorithm;
u_int8_t dnskey_digest_type;
u_char *dnskey_digest;
u_int dnskey_digest_len;
size_t dnskey_digest_len;
*flags = 0;
@ -217,7 +246,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
fingerprints->rri_nrdatas);
}
/* Initialize host key parameters */
/* Initialize default host key parameters */
if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type,
&hostkey_digest, &hostkey_digest_len, hostkey)) {
error("Error calculating host key fingerprint.");
@ -241,21 +270,32 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
continue;
}
if (hostkey_digest_type != dnskey_digest_type) {
hostkey_digest_type = dnskey_digest_type;
free(hostkey_digest);
/* Initialize host key parameters */
if (!dns_read_key(&hostkey_algorithm,
&hostkey_digest_type, &hostkey_digest,
&hostkey_digest_len, hostkey)) {
error("Error calculating key fingerprint.");
freerrset(fingerprints);
return -1;
}
}
/* Check if the current key is the same as the given key */
if (hostkey_algorithm == dnskey_algorithm &&
hostkey_digest_type == dnskey_digest_type) {
if (hostkey_digest_len == dnskey_digest_len &&
memcmp(hostkey_digest, dnskey_digest,
hostkey_digest_len) == 0) {
timingsafe_bcmp(hostkey_digest, dnskey_digest,
hostkey_digest_len) == 0)
*flags |= DNS_VERIFY_MATCH;
}
}
xfree(dnskey_digest);
free(dnskey_digest);
}
xfree(hostkey_digest); /* from key_fingerprint_raw() */
free(hostkey_digest); /* from sshkey_fingerprint_raw() */
freerrset(fingerprints);
if (*flags & DNS_VERIFY_FOUND)
@ -276,34 +316,39 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
* Export the fingerprint of a key as a DNS resource record
*/
int
export_dns_rr(const char *hostname, Key *key, FILE *f, int generic)
export_dns_rr(const char *hostname, struct sshkey *key, FILE *f, int generic)
{
u_int8_t rdata_pubkey_algorithm = 0;
u_int8_t rdata_digest_type = SSHFP_HASH_SHA1;
u_int8_t rdata_digest_type = SSHFP_HASH_RESERVED;
u_int8_t dtype;
u_char *rdata_digest;
u_int rdata_digest_len;
u_int i;
size_t i, rdata_digest_len;
int success = 0;
if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type,
&rdata_digest, &rdata_digest_len, key)) {
for (dtype = SSHFP_HASH_SHA1; dtype < SSHFP_HASH_MAX; dtype++) {
rdata_digest_type = dtype;
if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type,
&rdata_digest, &rdata_digest_len, key)) {
if (generic) {
fprintf(f, "%s IN TYPE%d \\# %zu %02x %02x ",
hostname, DNS_RDATATYPE_SSHFP,
2 + rdata_digest_len,
rdata_pubkey_algorithm, rdata_digest_type);
} else {
fprintf(f, "%s IN SSHFP %d %d ", hostname,
rdata_pubkey_algorithm, rdata_digest_type);
}
for (i = 0; i < rdata_digest_len; i++)
fprintf(f, "%02x", rdata_digest[i]);
fprintf(f, "\n");
free(rdata_digest); /* from sshkey_fingerprint_raw() */
success = 1;
}
}
if (generic)
fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ", hostname,
DNS_RDATATYPE_SSHFP, 2 + rdata_digest_len,
rdata_pubkey_algorithm, rdata_digest_type);
else
fprintf(f, "%s IN SSHFP %d %d ", hostname,
rdata_pubkey_algorithm, rdata_digest_type);
for (i = 0; i < rdata_digest_len; i++)
fprintf(f, "%02x", rdata_digest[i]);
fprintf(f, "\n");
xfree(rdata_digest); /* from key_fingerprint_raw() */
success = 1;
} else {
error("export_dns_rr: unsupported algorithm");
/* No SSHFP record was generated at all */
if (success == 0) {
error("%s: unsupported algorithm and/or digest_type", __func__);
}
return success;

21
dns.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: dns.h,v 1.11 2010/02/26 20:29:54 djm Exp $ */
/* $OpenBSD: dns.h,v 1.15 2015/05/08 06:45:13 djm Exp $ */
/*
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
@ -29,14 +29,18 @@
#define DNS_H
enum sshfp_types {
SSHFP_KEY_RESERVED,
SSHFP_KEY_RSA,
SSHFP_KEY_DSA
SSHFP_KEY_RESERVED = 0,
SSHFP_KEY_RSA = 1,
SSHFP_KEY_DSA = 2,
SSHFP_KEY_ECDSA = 3,
SSHFP_KEY_ED25519 = 4
};
enum sshfp_hashes {
SSHFP_HASH_RESERVED,
SSHFP_HASH_SHA1
SSHFP_HASH_RESERVED = 0,
SSHFP_HASH_SHA1 = 1,
SSHFP_HASH_SHA256 = 2,
SSHFP_HASH_MAX = 3
};
#define DNS_RDATACLASS_IN 1
@ -46,7 +50,8 @@ enum sshfp_hashes {
#define DNS_VERIFY_MATCH 0x00000002
#define DNS_VERIFY_SECURE 0x00000004
int verify_host_key_dns(const char *, struct sockaddr *, Key *, int *);
int export_dns_rr(const char *, Key *, FILE *, int);
int verify_host_key_dns(const char *, struct sockaddr *,
struct sshkey *, int *);
int export_dns_rr(const char *, struct sshkey *, FILE *, int);
#endif /* DNS_H */

144
ed25519.c Normal file
View File

@ -0,0 +1,144 @@
/* $OpenBSD: ed25519.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */
/*
* Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange,
* Peter Schwabe, Bo-Yin Yang.
* Copied from supercop-20130419/crypto_sign/ed25519/ref/ed25519.c
*/
#include "includes.h"
#include "crypto_api.h"
#include "ge25519.h"
static void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen)
{
unsigned long long i;
for (i = 0;i < 32;++i) playground[i] = sm[i];
for (i = 32;i < 64;++i) playground[i] = pk[i-32];
for (i = 64;i < smlen;++i) playground[i] = sm[i];
crypto_hash_sha512(hram,playground,smlen);
}
int crypto_sign_ed25519_keypair(
unsigned char *pk,
unsigned char *sk
)
{
sc25519 scsk;
ge25519 gepk;
unsigned char extsk[64];
int i;
randombytes(sk, 32);
crypto_hash_sha512(extsk, sk, 32);
extsk[0] &= 248;
extsk[31] &= 127;
extsk[31] |= 64;
sc25519_from32bytes(&scsk,extsk);
ge25519_scalarmult_base(&gepk, &scsk);
ge25519_pack(pk, &gepk);
for(i=0;i<32;i++)
sk[32 + i] = pk[i];
return 0;
}
int crypto_sign_ed25519(
unsigned char *sm,unsigned long long *smlen,
const unsigned char *m,unsigned long long mlen,
const unsigned char *sk
)
{
sc25519 sck, scs, scsk;
ge25519 ger;
unsigned char r[32];
unsigned char s[32];
unsigned char extsk[64];
unsigned long long i;
unsigned char hmg[crypto_hash_sha512_BYTES];
unsigned char hram[crypto_hash_sha512_BYTES];
crypto_hash_sha512(extsk, sk, 32);
extsk[0] &= 248;
extsk[31] &= 127;
extsk[31] |= 64;
*smlen = mlen+64;
for(i=0;i<mlen;i++)
sm[64 + i] = m[i];
for(i=0;i<32;i++)
sm[32 + i] = extsk[32+i];
crypto_hash_sha512(hmg, sm+32, mlen+32); /* Generate k as h(extsk[32],...,extsk[63],m) */
/* Computation of R */
sc25519_from64bytes(&sck, hmg);
ge25519_scalarmult_base(&ger, &sck);
ge25519_pack(r, &ger);
/* Computation of s */
for(i=0;i<32;i++)
sm[i] = r[i];
get_hram(hram, sm, sk+32, sm, mlen+64);
sc25519_from64bytes(&scs, hram);
sc25519_from32bytes(&scsk, extsk);
sc25519_mul(&scs, &scs, &scsk);
sc25519_add(&scs, &scs, &sck);
sc25519_to32bytes(s,&scs); /* cat s */
for(i=0;i<32;i++)
sm[32 + i] = s[i];
return 0;
}
int crypto_sign_ed25519_open(
unsigned char *m,unsigned long long *mlen,
const unsigned char *sm,unsigned long long smlen,
const unsigned char *pk
)
{
unsigned int i;
int ret;
unsigned char t2[32];
ge25519 get1, get2;
sc25519 schram, scs;
unsigned char hram[crypto_hash_sha512_BYTES];
*mlen = (unsigned long long) -1;
if (smlen < 64) return -1;
if (ge25519_unpackneg_vartime(&get1, pk)) return -1;
get_hram(hram,sm,pk,m,smlen);
sc25519_from64bytes(&schram, hram);
sc25519_from32bytes(&scs, sm+32);
ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &ge25519_base, &scs);
ge25519_pack(t2, &get2);
ret = crypto_verify_32(sm, t2);
if (!ret)
{
for(i=0;i<smlen-64;i++)
m[i] = sm[i + 64];
*mlen = smlen-64;
}
else
{
for(i=0;i<smlen-64;i++)
m[i] = 0;
}
return ret;
}

Some files were not shown because too many files have changed in this diff Show More