mirror of
https://github.com/PowerShell/Win32-OpenSSH.git
synced 2025-09-14 05:38:26 +02:00
nomachine + additional changes applied to openssh 7.1p1 source base
This commit is contained in:
parent
47c23e53d7
commit
f4b56e2280
@ -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 \
|
||||
|
13
addrmatch.c
13
addrmatch.c
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
79
audit-bsm.c
79
audit-bsm.c
@ -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));
|
||||
|
@ -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);
|
||||
|
26
auth-chall.c
26
auth-chall.c
@ -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);
|
||||
|
43
auth-krb5.c
43
auth-krb5.c
@ -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);
|
||||
|
||||
|
226
auth-options.c
226
auth-options.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
53
auth-pam.c
53
auth-pam.c
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
56
auth-rsa.c
56
auth-rsa.c
@ -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
201
auth.c
@ -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
54
auth.h
@ -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
64
auth1.c
@ -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 */
|
||||
|
@ -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
|
||||
|
54
auth2-gss.c
54
auth2-gss.c
@ -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 = {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
826
auth2-pubkey.c
826
auth2-pubkey.c
File diff suppressed because it is too large
Load Diff
319
auth2.c
319
auth2.c
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
60
authfd.h
60
authfd.h
@ -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
1089
authfile.c
File diff suppressed because it is too large
Load Diff
63
authfile.h
63
authfile.h
@ -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
212
bitmap.c
Normal 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
56
bitmap.h
Normal 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
248
blocks.c
Normal 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
271
bufaux.c
@ -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
206
bufbn.c
@ -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
106
bufec.c
@ -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
246
buffer.c
@ -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");
|
||||
}
|
||||
|
63
buffer.h
63
buffer.h
@ -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 */
|
||||
|
||||
|
60
canohost.c
60
canohost.c
@ -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
219
chacha.c
Normal 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
35
chacha.h
Normal 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
1248
channels.c
File diff suppressed because it is too large
Load Diff
74
channels.h
74
channels.h
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
83
cipher-aesctr.c
Normal 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
35
cipher-aesctr.h
Normal 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
|
21
cipher-bf1.c
21
cipher-bf1.c
@ -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
118
cipher-chachapoly.c
Normal 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
41
cipher-chachapoly.h
Normal 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 */
|
@ -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
592
cipher.c
@ -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
|
||||
}
|
||||
|
59
cipher.h
59
cipher.h
@ -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 */
|
||||
|
847
clientloop.c
847
clientloop.c
File diff suppressed because it is too large
Load Diff
@ -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
156
compat.c
@ -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;
|
||||
}
|
||||
|
||||
|
10
compat.h
10
compat.h
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
44
crypto_api.h
Normal 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
1
d2utmpa00408
Normal file
@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6mQW39+Uvy7DPCJd6aHJ0RXDnL+NC7VsC+SUAvosyMwb3PrxjFobyJ24yl6HEpdHvmlbNkipObew3T/drNQ0QK/H4Wt/7mkIdxN6IbF9hpFaLt8Fyd0yd7cpdxGHjYVEjuUBHgsOI/2k2V3zZx/c31X87Zjwb18JM8DKNk/ewKBj1MZVDcBdIWQT5WORPmpCVV7CeLE1TiXc5b2/2wNOOBdKPuDYBDGdPShqD91IaXmIs9KFUo4jFBE/V+K6fesUngudnouKdhFzSokoXbIpFNyi5L2TURtS9ebwm0Zkaz2xW86DJ6bSMtuMqhUDsJOZFmHh8NnTwuSDPUVXhlzbZ @oasis
|
1
d2utmpa00420
Normal file
1
d2utmpa00420
Normal file
@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCci4oy7TlKHy9d8+4slhm66MzE9haGbasI3Wwt6LqrvK6X0jtVCA+04nBWoBH7m+8UJrd6mqldSsOVETiZFLm4sNl95MmKirWHmoSeJy12wyovQXYkyYRH0T4J2lDna6JbgCPuaZpgIq88sxb/Z8RVf9fjStd6aNIyM95BalRnL839mYJxXpfPNMBkXGED3w/m5S6GgxX8VrP1cC6N+kXao5nyctZqFZAQbtj122LAeFNWN6W0Ehy5mx1VETFII+h9vSJ2LwDNHNrYBPV2IOtJ/tQ8ajSoc60bNvJjJtgld/he3KlmrgjtKcC4Akr1Bmegm+iI4pg2VgUnpocTdDfb @oasis
|
12
d2utmpa00672
Normal file
12
d2utmpa00672
Normal 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
7
d2utmpa01232
Normal 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
1
d2utmpa01324
Normal 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
1
d2utmpa01468
Normal file
@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCci4oy7TlKHy9d8+4slhm66MzE9haGbasI3Wwt6LqrvK6X0jtVCA+04nBWoBH7m+8UJrd6mqldSsOVETiZFLm4sNl95MmKirWHmoSeJy12wyovQXYkyYRH0T4J2lDna6JbgCPuaZpgIq88sxb/Z8RVf9fjStd6aNIyM95BalRnL839mYJxXpfPNMBkXGED3w/m5S6GgxX8VrP1cC6N+kXao5nyctZqFZAQbtj122LAeFNWN6W0Ehy5mx1VETFII+h9vSJ2LwDNHNrYBPV2IOtJ/tQ8ajSoc60bNvJjJtgld/he3KlmrgjtKcC4Akr1Bmegm+iI4pg2VgUnpocTdDfb @oasis
|
27
d2utmpa02828
Normal file
27
d2utmpa02828
Normal 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
5
d2utmpa03344
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIOrwk5LCELxzRGufJcI3ogOmaqYwNGYg0KIZqnQysKsPoAoGCCqGSM49
|
||||
AwEHoUQDQgAEXkGf9akhGRCleBfum8S5D11uWdOngABaPtFj7OHGk4u8gncSGf3g
|
||||
uQj9j5MSCt9BV57GXKXgb0Xu0TH0wXbNqA==
|
||||
-----END EC PRIVATE KEY-----
|
1
d2utmpa03516
Normal file
1
d2utmpa03516
Normal file
@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6mQW39+Uvy7DPCJd6aHJ0RXDnL+NC7VsC+SUAvosyMwb3PrxjFobyJ24yl6HEpdHvmlbNkipObew3T/drNQ0QK/H4Wt/7mkIdxN6IbF9hpFaLt8Fyd0yd7cpdxGHjYVEjuUBHgsOI/2k2V3zZx/c31X87Zjwb18JM8DKNk/ewKBj1MZVDcBdIWQT5WORPmpCVV7CeLE1TiXc5b2/2wNOOBdKPuDYBDGdPShqD91IaXmIs9KFUo4jFBE/V+K6fesUngudnouKdhFzSokoXbIpFNyi5L2TURtS9ebwm0Zkaz2xW86DJ6bSMtuMqhUDsJOZFmHh8NnTwuSDPUVXhlzbZ @oasis
|
1
d2utmpa04376
Normal file
1
d2utmpa04376
Normal file
@ -0,0 +1 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOybqQdTc7bH8q7NxsBSFkZiyhzgafpiIVy66WzHiCzI @oasis
|
1
d2utmpa04792
Normal file
1
d2utmpa04792
Normal 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
1
d2utmpa04800
Normal 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
12
d2utmpa05272
Normal 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
1
d2utmpa06292
Normal file
@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6mQW39+Uvy7DPCJd6aHJ0RXDnL+NC7VsC+SUAvosyMwb3PrxjFobyJ24yl6HEpdHvmlbNkipObew3T/drNQ0QK/H4Wt/7mkIdxN6IbF9hpFaLt8Fyd0yd7cpdxGHjYVEjuUBHgsOI/2k2V3zZx/c31X87Zjwb18JM8DKNk/ewKBj1MZVDcBdIWQT5WORPmpCVV7CeLE1TiXc5b2/2wNOOBdKPuDYBDGdPShqD91IaXmIs9KFUo4jFBE/V+K6fesUngudnouKdhFzSokoXbIpFNyi5L2TURtS9ebwm0Zkaz2xW86DJ6bSMtuMqhUDsJOZFmHh8NnTwuSDPUVXhlzbZ @oasis
|
5
d2utmpa06444
Normal file
5
d2utmpa06444
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIOrwk5LCELxzRGufJcI3ogOmaqYwNGYg0KIZqnQysKsPoAoGCCqGSM49
|
||||
AwEHoUQDQgAEXkGf9akhGRCleBfum8S5D11uWdOngABaPtFj7OHGk4u8gncSGf3g
|
||||
uQj9j5MSCt9BV57GXKXgb0Xu0TH0wXbNqA==
|
||||
-----END EC PRIVATE KEY-----
|
12
d2utmpa07284
Normal file
12
d2utmpa07284
Normal 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
1
d2utmpa07336
Normal file
@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCci4oy7TlKHy9d8+4slhm66MzE9haGbasI3Wwt6LqrvK6X0jtVCA+04nBWoBH7m+8UJrd6mqldSsOVETiZFLm4sNl95MmKirWHmoSeJy12wyovQXYkyYRH0T4J2lDna6JbgCPuaZpgIq88sxb/Z8RVf9fjStd6aNIyM95BalRnL839mYJxXpfPNMBkXGED3w/m5S6GgxX8VrP1cC6N+kXao5nyctZqFZAQbtj122LAeFNWN6W0Ehy5mx1VETFII+h9vSJ2LwDNHNrYBPV2IOtJ/tQ8ajSoc60bNvJjJtgld/he3KlmrgjtKcC4Akr1Bmegm+iI4pg2VgUnpocTdDfb @oasis
|
27
d2utmpa08080
Normal file
27
d2utmpa08080
Normal 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
7
d2utmpa08624
Normal 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
27
d2utmpa08916
Normal 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
27
d2utmpa09000
Normal 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
27
d2utmpa09040
Normal 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
5
d2utmpa09244
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIOrwk5LCELxzRGufJcI3ogOmaqYwNGYg0KIZqnQysKsPoAoGCCqGSM49
|
||||
AwEHoUQDQgAEXkGf9akhGRCleBfum8S5D11uWdOngABaPtFj7OHGk4u8gncSGf3g
|
||||
uQj9j5MSCt9BV57GXKXgb0Xu0TH0wXbNqA==
|
||||
-----END EC PRIVATE KEY-----
|
7
d2utmpa09344
Normal file
7
d2utmpa09344
Normal 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
27
d2utmpa09348
Normal 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
1
d2utmpa09960
Normal file
@ -0,0 +1 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOybqQdTc7bH8q7NxsBSFkZiyhzgafpiIVy66WzHiCzI @oasis
|
1
d2utmpa10036
Normal file
1
d2utmpa10036
Normal file
@ -0,0 +1 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOybqQdTc7bH8q7NxsBSFkZiyhzgafpiIVy66WzHiCzI @oasis
|
81
deattack.c
81
deattack.c
@ -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;
|
||||
}
|
||||
|
11
deattack.h
11
deattack.h
@ -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
112
defines.h
@ -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
208
dh.c
@ -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
8
dh.h
@ -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
264
digest-libc.c
Normal 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
205
digest-openssl.c
Normal 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
71
digest.h
Normal 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 */
|
||||
|
110
dispatch.c
110
dispatch.c
@ -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);
|
||||
}
|
||||
|
35
dispatch.h
35
dispatch.h
@ -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
139
dns.c
@ -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
21
dns.h
@ -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
144
ed25519.c
Normal 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
Loading…
x
Reference in New Issue
Block a user