Commit 4b4116ce authored by Alexey Alyaev's avatar Alexey Alyaev

Support for building with cygwin-2.5.2 + SSPI

parent e6e05d87
...@@ -95,10 +95,11 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ ...@@ -95,10 +95,11 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \
kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \ kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \
kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \ kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \
platform-pledge.o platform-tracing.o platform-pledge.o platform-tracing.o libcrypto-compat.o
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
sshconnect.o sshconnect1.o sshconnect2.o mux.o proxy.o sshconnect.o sshconnect1.o sshconnect2.o mux.o proxy.o \
gss-serv-sspi.o
SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \
audit.o audit-bsm.o audit-linux.o platform.o \ audit.o audit-bsm.o audit-linux.o platform.o \
...@@ -108,7 +109,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \ ...@@ -108,7 +109,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \
auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
auth2-none.o auth2-passwd.o auth2-pubkey.o \ auth2-none.o auth2-passwd.o auth2-pubkey.o \
monitor.o monitor_wrap.o auth-krb5.o \ monitor.o monitor_wrap.o auth-krb5.o \
auth2-gss.o gss-serv.o gss-serv-krb5.o \ auth2-gss.o gss-serv.o gss-serv-krb5.o gss-serv-sspi.o \
loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
sftp-server.o sftp-common.o \ sftp-server.o sftp-common.o \
sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
......
# $Id: Makefile.in,v 1.365 2014/08/30 06:23:07 djm Exp $
# uncomment if you run a non bourne compatable shell. Ie. csh
#SHELL = @SH@
AUTORECONF=autoreconf
prefix=@prefix@
exec_prefix=@exec_prefix@
bindir=@bindir@
sbindir=@sbindir@
libexecdir=@libexecdir@
datadir=@datadir@
datarootdir=@datarootdir@
mandir=@mandir@
mansubdir=@mansubdir@
sysconfdir=@sysconfdir@
piddir=@piddir@
srcdir=@srcdir@
top_srcdir=@top_srcdir@
DESTDIR=
VPATH=@srcdir@
SSH_PROGRAM=@bindir@/ssh
ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
SFTP_SERVER=$(libexecdir)/sftp-server
SSH_KEYSIGN=$(libexecdir)/ssh-keysign
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
PRIVSEP_PATH=@PRIVSEP_PATH@
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
STRIP_OPT=@STRIP_OPT@
TEST_SHELL=@TEST_SHELL@
NXCOMPINC=@NXCOMPINC@
NXCOMPLIBS=@NXCOMPLIBS@
PATHS= -DSSHDIR=\"$(sysconfdir)\" \
-D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \
-D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \
-D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \
-D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \
-D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \
-D_PATH_SSH_PIDDIR=\"$(piddir)\" \
-D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\"
CC=@CC@
LD=@LD@
CFLAGS=@CFLAGS@
CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
LIBS=@LIBS@
K5LIBS=@K5LIBS@
GSSLIBS=@GSSLIBS@
SSHLIBS=@SSHLIBS@
SSHDLIBS=@SSHDLIBS@
LIBEDIT=@LIBEDIT@
AR=@AR@
AWK=@AWK@
RANLIB=@RANLIB@
INSTALL=@INSTALL@
PERL=@PERL@
SED=@SED@
ENT=@ENT@
XAUTH_PATH=@XAUTH_PATH@
LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
EXEEXT=@EXEEXT@
MANFMT=@MANFMT@
TARGETS=nxssh$(EXEEXT) nxsshd$(EXEEXT) nxssh-keygen$(EXEEXT)
LIBOPENSSH_OBJS=\
ssh_api.o \
ssherr.o \
sshbuf.o \
sshkey.o \
sshbuf-getput-basic.o \
sshbuf-misc.o \
sshbuf-getput-crypto.o \
krl.o \
bitmap.o
LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
authfd.o authfile.o bufaux.o bufbn.o bufec.o buffer.o \
canohost.o channels.o cipher.o cipher-aes.o cipher-aesctr.o \
cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \
compat.o crc32.o deattack.o fatal.o hostfile.o \
log.o match.o md-sha256.o moduli.o nchan.o packet.o opacket.o \
readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \
atomicio.o key.o dispatch.o mac.o uidswap.o uuencode.o misc.o utf8.o \
monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
ssh-pkcs11.o smult_curve25519_ref.o \
poly1305.o chacha.o cipher-chachapoly.o \
ssh-ed25519.o digest-openssl.o digest-libc.o hmac.o \
sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o \
kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \
kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \
kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \
platform-pledge.o platform-tracing.o
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
sshconnect.o sshconnect1.o sshconnect2.o mux.o proxy.o
SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \
audit.o audit-bsm.o audit-linux.o platform.o \
sshpty.o sshlogin.o servconf.o serverloop.o \
auth.o auth2.o auth-options.o session.o \
auth2-chall.o groupaccess.o \
auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
auth2-none.o auth2-passwd.o auth2-pubkey.o \
monitor.o monitor_wrap.o auth-krb5.o \
auth2-gss.o gss-serv.o gss-serv-krb5.o \
loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
sftp-server.o sftp-common.o \
sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \
sandbox-solaris.o
MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out
MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5
MANTYPE = @MANTYPE@
CONFIGFILES=ssh_config.out sshd_config.out
CONFIGFILES_IN=ssh_config sshd_config
PATHSUBS = \
-e 's|/etc/ssh/ssh_config|$(sysconfdir)/ssh_config|g' \
-e 's|/etc/ssh/ssh_known_hosts|$(sysconfdir)/ssh_known_hosts|g' \
-e 's|/etc/ssh/sshd_config|$(sysconfdir)/sshd_config|g' \
-e 's|/usr/libexec|$(libexecdir)|g' \
-e 's|/etc/shosts.equiv|$(sysconfdir)/shosts.equiv|g' \
-e 's|/etc/ssh/ssh_host_key|$(sysconfdir)/ssh_host_key|g' \
-e 's|/etc/ssh/ssh_host_ecdsa_key|$(sysconfdir)/ssh_host_ecdsa_key|g' \
-e 's|/etc/ssh/ssh_host_dsa_key|$(sysconfdir)/ssh_host_dsa_key|g' \
-e 's|/etc/ssh/ssh_host_rsa_key|$(sysconfdir)/ssh_host_rsa_key|g' \
-e 's|/etc/ssh/ssh_host_ed25519_key|$(sysconfdir)/ssh_host_ed25519_key|g' \
-e 's|/var/run/sshd.pid|$(piddir)/sshd.pid|g' \
-e 's|/etc/moduli|$(sysconfdir)/moduli|g' \
-e 's|/etc/ssh/moduli|$(sysconfdir)/moduli|g' \
-e 's|/etc/ssh/sshrc|$(sysconfdir)/sshrc|g' \
-e 's|/usr/X11R6/bin/xauth|$(XAUTH_PATH)|g' \
-e 's|/var/empty|$(PRIVSEP_PATH)|g' \
-e 's|/usr/bin:/bin:/usr/sbin:/sbin|@user_path@|g'
FIXPATHSCMD = $(SED) $(PATHSUBS)
FIXALGORITHMSCMD= $(SHELL) $(srcdir)/fixalgorithms $(SED) \
@UNSUPPORTED_ALGORITHMS@
all: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
$(LIBSSH_OBJS): Makefile.in config.h
$(SSHOBJS): Makefile.in config.h
$(SSHDOBJS): Makefile.in config.h
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) $(NXCOMPINC) -c $< -o $@
LIBCOMPAT=openbsd-compat/libopenbsd-compat.a
$(LIBCOMPAT): always
(cd openbsd-compat && $(MAKE))
always:
libssh.a: $(LIBSSH_OBJS)
$(AR) rv $@ $(LIBSSH_OBJS)
$(RANLIB) $@
nxssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
$(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(GSSLIBS) $(NXCOMPLIBS)
nxsshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS)
$(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBWRAP) $(LIBPAM) $(LIBSELINUX) $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS)
scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
$(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
$(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o
$(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
nxssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
$(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o readconf.o
$(LD) -o $@ ssh-keysign.o readconf.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o
$(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
$(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o
$(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
$(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
# test driver for the loginrec code - not built by default
logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o
$(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS)
$(CONFIGFILES): $(CONFIGFILES_IN)
conffile=`echo $@ | sed 's/.out$$//'`; \
$(FIXPATHSCMD) $(srcdir)/$${conffile} > $@
# fake rule to stop make trying to compile moduli.o into a binary "moduli.o"
moduli:
echo
# special case target for umac128
umac128.o: umac.c
$(CC) $(CFLAGS) $(CPPFLAGS) -o umac128.o -c $(srcdir)/umac.c \
-DUMAC_OUTPUT_LEN=16 -Dumac_new=umac128_new \
-Dumac_update=umac128_update -Dumac_final=umac128_final \
-Dumac_delete=umac128_delete -Dumac_ctx=umac128_ctx
clean: regressclean
rm -f *.o *.a $(TARGETS) logintest config.cache config.log
rm -f *.out core survey
rm -f regress/unittests/test_helper/*.a
rm -f regress/unittests/test_helper/*.o
rm -f regress/unittests/sshbuf/*.o
rm -f regress/unittests/sshbuf/test_sshbuf
rm -f regress/unittests/sshkey/*.o
rm -f regress/unittests/sshkey/test_sshkey
rm -f regress/unittests/bitmap/*.o
rm -f regress/unittests/bitmap/test_bitmap
rm -f regress/unittests/conversion/*.o
rm -f regress/unittests/conversion/test_conversion
rm -f regress/unittests/hostkeys/*.o
rm -f regress/unittests/hostkeys/test_hostkeys
rm -f regress/unittests/kex/*.o
rm -f regress/unittests/kex/test_kex
rm -f regress/unittests/match/*.o
rm -f regress/unittests/match/test_match
rm -f regress/unittests/utf8/*.o
rm -f regress/unittests/utf8/test_utf8
rm -f regress/misc/kexfuzz/*.o
rm -f regress/misc/kexfuzz/kexfuzz
(cd openbsd-compat && $(MAKE) clean)
distclean: regressclean
rm -f *.o *.a $(TARGETS) logintest config.cache config.log
rm -f *.out core opensshd.init openssh.xml
rm -f Makefile buildpkg.sh config.h config.status
rm -f survey.sh openbsd-compat/regress/Makefile *~
rm -rf autom4te.cache
rm -f regress/unittests/test_helper/*.a
rm -f regress/unittests/test_helper/*.o
rm -f regress/unittests/sshbuf/*.o
rm -f regress/unittests/sshbuf/test_sshbuf
rm -f regress/unittests/sshkey/*.o
rm -f regress/unittests/sshkey/test_sshkey
rm -f regress/unittests/bitmap/*.o
rm -f regress/unittests/bitmap/test_bitmap
rm -f regress/unittests/conversion/*.o
rm -f regress/unittests/conversion/test_conversion
rm -f regress/unittests/hostkeys/*.o
rm -f regress/unittests/hostkeys/test_hostkeys
rm -f regress/unittests/kex/*.o
rm -f regress/unittests/kex/test_kex
rm -f regress/unittests/match/*.o
rm -f regress/unittests/match/test_match
rm -f regress/unittests/utf8/*.o
rm -f regress/unittests/utf8/test_utf8
rm -f regress/unittests/misc/kexfuzz
(cd openbsd-compat && $(MAKE) distclean)
if test -d pkg ; then \
rm -fr pkg ; \
fi
veryclean: distclean
rm -f configure config.h.in *.0
cleandir: veryclean
mrproper: veryclean
realclean: veryclean
regress-prep:
[ -d `pwd`/regress ] || mkdir -p `pwd`/regress
[ -d `pwd`/regress/unittests ] || mkdir -p `pwd`/regress/unittests
[ -d `pwd`/regress/unittests/test_helper ] || \
mkdir -p `pwd`/regress/unittests/test_helper
[ -d `pwd`/regress/unittests/sshbuf ] || \
mkdir -p `pwd`/regress/unittests/sshbuf
[ -d `pwd`/regress/unittests/sshkey ] || \
mkdir -p `pwd`/regress/unittests/sshkey
[ -d `pwd`/regress/unittests/bitmap ] || \
mkdir -p `pwd`/regress/unittests/bitmap
[ -d `pwd`/regress/unittests/conversion ] || \
mkdir -p `pwd`/regress/unittests/conversion
[ -d `pwd`/regress/unittests/hostkeys ] || \
mkdir -p `pwd`/regress/unittests/hostkeys
[ -d `pwd`/regress/unittests/kex ] || \
mkdir -p `pwd`/regress/unittests/kex
[ -d `pwd`/regress/unittests/match ] || \
mkdir -p `pwd`/regress/unittests/match
[ -d `pwd`/regress/unittests/utf8 ] || \
mkdir -p `pwd`/regress/unittests/utf8
[ -d `pwd`/regress/misc/kexfuzz ] || \
mkdir -p `pwd`/regress/misc/kexfuzz
[ -f `pwd`/regress/Makefile ] || \
ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile
REGRESSLIBS=libssh.a $(LIBCOMPAT)
regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c $(REGRESSLIBS)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/modpipe.c \
$(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
regress/setuid-allowed$(EXEEXT): $(srcdir)/regress/setuid-allowed.c $(REGRESSLIBS)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/setuid-allowed.c \
$(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
regress/netcat$(EXEEXT): $(srcdir)/regress/netcat.c $(REGRESSLIBS)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/netcat.c \
$(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
regress/check-perm$(EXEEXT): $(srcdir)/regress/check-perm.c $(REGRESSLIBS)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/check-perm.c \
$(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_HELPER_OBJS=\
regress/unittests/test_helper/test_helper.o \
regress/unittests/test_helper/fuzz.o
regress/unittests/test_helper/libtest_helper.a: ${UNITTESTS_TEST_HELPER_OBJS}
$(AR) rv $@ $(UNITTESTS_TEST_HELPER_OBJS)
$(RANLIB) $@
UNITTESTS_TEST_SSHBUF_OBJS=\
regress/unittests/sshbuf/tests.o \
regress/unittests/sshbuf/test_sshbuf.o \
regress/unittests/sshbuf/test_sshbuf_getput_basic.o \
regress/unittests/sshbuf/test_sshbuf_getput_crypto.o \
regress/unittests/sshbuf/test_sshbuf_misc.o \
regress/unittests/sshbuf/test_sshbuf_fuzz.o \
regress/unittests/sshbuf/test_sshbuf_getput_fuzz.o \
regress/unittests/sshbuf/test_sshbuf_fixed.o
regress/unittests/sshbuf/test_sshbuf$(EXEEXT): ${UNITTESTS_TEST_SSHBUF_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_SSHBUF_OBJS) \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_SSHKEY_OBJS=\
regress/unittests/sshkey/test_fuzz.o \
regress/unittests/sshkey/tests.o \
regress/unittests/sshkey/common.o \
regress/unittests/sshkey/test_file.o \
regress/unittests/sshkey/test_sshkey.o
regress/unittests/sshkey/test_sshkey$(EXEEXT): ${UNITTESTS_TEST_SSHKEY_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_SSHKEY_OBJS) \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_BITMAP_OBJS=\
regress/unittests/bitmap/tests.o
regress/unittests/bitmap/test_bitmap$(EXEEXT): ${UNITTESTS_TEST_BITMAP_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_BITMAP_OBJS) \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_CONVERSION_OBJS=\
regress/unittests/conversion/tests.o
regress/unittests/conversion/test_conversion$(EXEEXT): \
${UNITTESTS_TEST_CONVERSION_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_CONVERSION_OBJS) \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_KEX_OBJS=\
regress/unittests/kex/tests.o \
regress/unittests/kex/test_kex.o
regress/unittests/kex/test_kex$(EXEEXT): ${UNITTESTS_TEST_KEX_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_KEX_OBJS) \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_HOSTKEYS_OBJS=\
regress/unittests/hostkeys/tests.o \
regress/unittests/hostkeys/test_iterate.o
regress/unittests/hostkeys/test_hostkeys$(EXEEXT): \
${UNITTESTS_TEST_HOSTKEYS_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_HOSTKEYS_OBJS) \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_MATCH_OBJS=\
regress/unittests/match/tests.o
regress/unittests/match/test_match$(EXEEXT): \
${UNITTESTS_TEST_MATCH_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_MATCH_OBJS) \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_UTF8_OBJS=\
regress/unittests/utf8/tests.o
regress/unittests/utf8/test_utf8$(EXEEXT): \
${UNITTESTS_TEST_UTF8_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_UTF8_OBJS) \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
MISC_KEX_FUZZ_OBJS=\
regress/misc/kexfuzz/kexfuzz.o
regress/misc/kexfuzz/kexfuzz$(EXEEXT): ${MISC_KEX_FUZZ_OBJS} libssh.a
$(LD) -o $@ $(LDFLAGS) $(MISC_KEX_FUZZ_OBJS) \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
regress-binaries: regress/modpipe$(EXEEXT) \
regress/setuid-allowed$(EXEEXT) \
regress/netcat$(EXEEXT) \
regress/check-perm$(EXEEXT) \
regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \
regress/unittests/sshkey/test_sshkey$(EXEEXT) \
regress/unittests/bitmap/test_bitmap$(EXEEXT) \
regress/unittests/conversion/test_conversion$(EXEEXT) \
regress/unittests/hostkeys/test_hostkeys$(EXEEXT) \
regress/unittests/kex/test_kex$(EXEEXT) \
regress/unittests/match/test_match$(EXEEXT) \
regress/unittests/utf8/test_utf8$(EXEEXT) \
regress/misc/kexfuzz/kexfuzz$(EXEEXT)
tests interop-tests t-exec unit: regress-prep regress-binaries $(TARGETS)
BUILDDIR=`pwd`; \
TEST_SSH_SCP="$${BUILDDIR}/scp"; \
TEST_SSH_SSH="$${BUILDDIR}/ssh"; \
TEST_SSH_SSHD="$${BUILDDIR}/sshd"; \
TEST_SSH_SSHAGENT="$${BUILDDIR}/ssh-agent"; \
TEST_SSH_SSHADD="$${BUILDDIR}/ssh-add"; \
TEST_SSH_SSHKEYGEN="$${BUILDDIR}/ssh-keygen"; \
TEST_SSH_SSHPKCS11HELPER="$${BUILDDIR}/ssh-pkcs11-helper"; \
TEST_SSH_SSHKEYSCAN="$${BUILDDIR}/ssh-keyscan"; \
TEST_SSH_SFTP="$${BUILDDIR}/sftp"; \
TEST_SSH_SFTPSERVER="$${BUILDDIR}/sftp-server"; \
TEST_SSH_PLINK="plink"; \
TEST_SSH_PUTTYGEN="puttygen"; \
TEST_SSH_CONCH="conch"; \
TEST_SSH_IPV6="@TEST_SSH_IPV6@" ; \
TEST_SSH_UTF8="@TEST_SSH_UTF8@" ; \
TEST_SSH_ECC="@TEST_SSH_ECC@" ; \
cd $(srcdir)/regress || exit $$?; \
$(MAKE) \
.OBJDIR="$${BUILDDIR}/regress" \
.CURDIR="`pwd`" \
BUILDDIR="$${BUILDDIR}" \
OBJ="$${BUILDDIR}/regress/" \
PATH="$${BUILDDIR}:$${PATH}" \
TEST_ENV=MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \
TEST_MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \
TEST_SSH_SCP="$${TEST_SSH_SCP}" \
TEST_SSH_SSH="$${TEST_SSH_SSH}" \
TEST_SSH_SSHD="$${TEST_SSH_SSHD}" \
TEST_SSH_SSHAGENT="$${TEST_SSH_SSHAGENT}" \
TEST_SSH_SSHADD="$${TEST_SSH_SSHADD}" \
TEST_SSH_SSHKEYGEN="$${TEST_SSH_SSHKEYGEN}" \
TEST_SSH_SSHPKCS11HELPER="$${TEST_SSH_SSHPKCS11HELPER}" \
TEST_SSH_SSHKEYSCAN="$${TEST_SSH_SSHKEYSCAN}" \
TEST_SSH_SFTP="$${TEST_SSH_SFTP}" \
TEST_SSH_SFTPSERVER="$${TEST_SSH_SFTPSERVER}" \
TEST_SSH_PLINK="$${TEST_SSH_PLINK}" \
TEST_SSH_PUTTYGEN="$${TEST_SSH_PUTTYGEN}" \
TEST_SSH_CONCH="$${TEST_SSH_CONCH}" \
TEST_SSH_IPV6="$${TEST_SSH_IPV6}" \
TEST_SSH_UTF8="$${TEST_SSH_UTF8}" \
TEST_SSH_ECC="$${TEST_SSH_ECC}" \
TEST_SHELL="${TEST_SHELL}" \
EXEEXT="$(EXEEXT)" \
$@ && echo all tests passed
compat-tests: $(LIBCOMPAT)
(cd openbsd-compat/regress && $(MAKE))
regressclean:
if [ -f regress/Makefile ] && [ -r regress/Makefile ]; then \
(cd regress && $(MAKE) clean) \
fi
survey: survey.sh ssh
@$(SHELL) ./survey.sh > survey
@echo 'The survey results have been placed in the file "survey" in the'
@echo 'current directory. Please review the file then send with'
@echo '"make send-survey".'
send-survey: survey
mail portable-survey@mindrot.org <survey
package: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
if [ "@MAKE_PACKAGE_SUPPORTED@" = yes ]; then \
sh buildpkg.sh; \
fi
# NXSSH on Cygwin 2.5.2 with SSPI module
This branch contains the code from master branch plus additional patches
applied to make it buildable with OpenSSL 1.1.* + cygwin 2.5.2
It also contains patch to enable GSS SSPI feature to support native GSS
token delegation using Windows SSPI interface.
All applied patches that make this branch different from master are located
in patches/ subdirectory.
## Building
```bash
$ WANT_AUTOCONF='2.69' autoreconf -fvi
$ ./configure --with-sspi
$ make -j$((`nproc` + 1))
```
\ No newline at end of file
...@@ -129,6 +129,10 @@ extern u_int utmp_len; ...@@ -129,6 +129,10 @@ extern u_int utmp_len;
typedef pthread_t sp_pthread_t; typedef pthread_t sp_pthread_t;
#else #else
typedef pid_t sp_pthread_t; typedef pid_t sp_pthread_t;
# define pthread_create(a, b, c, d) _ssh_compat_pthread_create(a, b, c, d)
# define pthread_exit(a) _ssh_compat_pthread_exit(a)
# define pthread_cancel(a) _ssh_compat_pthread_cancel(a)
# define pthread_join(a, b) _ssh_compat_pthread_join(a, b)
#endif #endif
struct pam_ctxt { struct pam_ctxt {
......
...@@ -207,15 +207,22 @@ deserialise_identity1(struct sshbuf *ids, struct sshkey **keyp, char **commentp) ...@@ -207,15 +207,22 @@ deserialise_identity1(struct sshbuf *ids, struct sshkey **keyp, char **commentp)
int r, keybits; int r, keybits;
u_int32_t bits; u_int32_t bits;
char *comment = NULL; char *comment = NULL;
BIGNUM *e = NULL, *n = NULL;
if ((key = sshkey_new(KEY_RSA1)) == NULL) if ((key = sshkey_new(KEY_RSA1)) == NULL)
return SSH_ERR_ALLOC_FAIL; return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_get_u32(ids, &bits)) != 0 || if ((e = BN_new()) == NULL ||
(r = sshbuf_get_bignum1(ids, key->rsa->e)) != 0 || (n = BN_new()) == NULL ||
(r = sshbuf_get_bignum1(ids, key->rsa->n)) != 0 || (r = sshbuf_get_u32(ids, &bits)) != 0 ||
(r = sshbuf_get_cstring(ids, &comment, NULL)) != 0) (r = sshbuf_get_bignum1(ids, e)) != 0 ||
(r = sshbuf_get_bignum1(ids, n)) != 0 ||
(r = sshbuf_get_cstring(ids, &comment, NULL)) != 0 ||
(RSA_set0_key(key->rsa, n, e, NULL) == 0)) {
BN_free(n);
BN_free(e);
goto out; goto out;
keybits = BN_num_bits(key->rsa->n); }
keybits = BN_num_bits(n);
/* XXX previously we just warned here. I think we should be strict */ /* XXX previously we just warned here. I think we should be strict */
if (keybits < 0 || bits != (u_int)keybits) { if (keybits < 0 || bits != (u_int)keybits) {
r = SSH_ERR_KEY_BITS_MISMATCH; r = SSH_ERR_KEY_BITS_MISMATCH;
...@@ -393,15 +400,17 @@ ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge, ...@@ -393,15 +400,17 @@ ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge,
struct sshbuf *msg; struct sshbuf *msg;
int r; int r;
u_char type; u_char type;
const BIGNUM *e, *n;
if (key->type != KEY_RSA1) if (key->type != KEY_RSA1)
return SSH_ERR_INVALID_ARGUMENT; return SSH_ERR_INVALID_ARGUMENT;
if ((msg = sshbuf_new()) == NULL) if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL; return SSH_ERR_ALLOC_FAIL;
RSA_get0_key(key->rsa, &n, &e, NULL);
if ((r = sshbuf_put_u8(msg, SSH_AGENTC_RSA_CHALLENGE)) != 0 || if ((r = sshbuf_put_u8(msg, SSH_AGENTC_RSA_CHALLENGE)) != 0 ||
(r = sshbuf_put_u32(msg, BN_num_bits(key->rsa->n))) != 0 || (r = sshbuf_put_u32(msg, BN_num_bits(n))) != 0 ||
(r = sshbuf_put_bignum1(msg, key->rsa->e)) != 0 || (r = sshbuf_put_bignum1(msg, e)) != 0 ||
(r = sshbuf_put_bignum1(msg, key->rsa->n)) != 0 || (r = sshbuf_put_bignum1(msg, n)) != 0 ||
(r = sshbuf_put_bignum1(msg, challenge)) != 0 || (r = sshbuf_put_bignum1(msg, challenge)) != 0 ||
(r = sshbuf_put(msg, session_id, 16)) != 0 || (r = sshbuf_put(msg, session_id, 16)) != 0 ||
(r = sshbuf_put_u32(msg, 1)) != 0) /* Response type for proto 1.1 */ (r = sshbuf_put_u32(msg, 1)) != 0) /* Response type for proto 1.1 */
...@@ -499,15 +508,19 @@ static int ...@@ -499,15 +508,19 @@ static int
ssh_encode_identity_rsa1(struct sshbuf *b, RSA *key, const char *comment) ssh_encode_identity_rsa1(struct sshbuf *b, RSA *key, const char *comment)
{ {
int r; int r;
const BIGNUM *n, *e, *d, *q, *p, *iqmp;
RSA_get0_key(key, &n, &e, &d);
RSA_get0_factors(key, &p, &q);
RSA_get0_crt_params(key, NULL, NULL, &iqmp);
/* To keep within the protocol: p < q for ssh. in SSL p > q */ /* To keep within the protocol: p < q for ssh. in SSL p > q */
if ((r = sshbuf_put_u32(b, BN_num_bits(key->n))) != 0 || if ((r = sshbuf_put_u32(b, BN_num_bits(n))) != 0 ||
(r = sshbuf_put_bignum1(b, key->n)) != 0 || (r = sshbuf_put_bignum1(b, n)) != 0 ||
(r = sshbuf_put_bignum1(b, key->e)) != 0 || (r = sshbuf_put_bignum1(b, e)) != 0 ||
(r = sshbuf_put_bignum1(b, key->d)) != 0 || (r = sshbuf_put_bignum1(b, d)) != 0 ||
(r = sshbuf_put_bignum1(b, key->iqmp)) != 0 || (r = sshbuf_put_bignum1(b, iqmp)) != 0 ||
(r = sshbuf_put_bignum1(b, key->q)) != 0 || (r = sshbuf_put_bignum1(b, q)) != 0 ||
(r = sshbuf_put_bignum1(b, key->p)) != 0 || (r = sshbuf_put_bignum1(b, p)) != 0 ||
(r = sshbuf_put_cstring(b, comment)) != 0) (r = sshbuf_put_cstring(b, comment)) != 0)
return r; return r;
return 0; return 0;
...@@ -622,11 +635,13 @@ ssh_remove_identity(int sock, struct sshkey *key) ...@@ -622,11 +635,13 @@ ssh_remove_identity(int sock, struct sshkey *key)
#ifdef WITH_SSH1 #ifdef WITH_SSH1
if (key->type == KEY_RSA1) { if (key->type == KEY_RSA1) {
const BIGNUM *e, *n;
RSA_get0_key(key->rsa, &n, &e, NULL);
if ((r = sshbuf_put_u8(msg, if ((r = sshbuf_put_u8(msg,
SSH_AGENTC_REMOVE_RSA_IDENTITY)) != 0 || SSH_AGENTC_REMOVE_RSA_IDENTITY)) != 0 ||
(r = sshbuf_put_u32(msg, BN_num_bits(key->rsa->n))) != 0 || (r = sshbuf_put_u32(msg, BN_num_bits(n))) != 0 ||
(r = sshbuf_put_bignum1(msg, key->rsa->e)) != 0 || (r = sshbuf_put_bignum1(msg, e)) != 0 ||
(r = sshbuf_put_bignum1(msg, key->rsa->n)) != 0) (r = sshbuf_put_bignum1(msg, n)) != 0)
goto out; goto out;
} else } else
#endif #endif
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
*/ */
struct ssh1_3des_ctx struct ssh1_3des_ctx
{ {
EVP_CIPHER_CTX k1, k2, k3; EVP_CIPHER_CTX *k1, *k2, *k3;
}; };
const EVP_CIPHER * evp_ssh1_3des(void); const EVP_CIPHER * evp_ssh1_3des(void);
...@@ -65,7 +65,7 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, ...@@ -65,7 +65,7 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
if (key == NULL) if (key == NULL)
return 1; return 1;
if (enc == -1) if (enc == -1)
enc = ctx->encrypt; enc = EVP_CIPHER_CTX_encrypting(ctx);
k1 = k2 = k3 = (u_char *) key; k1 = k2 = k3 = (u_char *) key;
k2 += 8; k2 += 8;
if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) { if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
...@@ -74,12 +74,19 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, ...@@ -74,12 +74,19 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
else else
k1 += 16; k1 += 16;
} }
EVP_CIPHER_CTX_init(&c->k1); c->k1 = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(&c->k2); c->k2 = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(&c->k3); c->k3 = EVP_CIPHER_CTX_new();
if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 || if (c->k1 == NULL || c->k2 == NULL || c->k3 == NULL) {
EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 || EVP_CIPHER_CTX_free(c->k1);
EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) { EVP_CIPHER_CTX_free(c->k2);
EVP_CIPHER_CTX_free(c->k3);
free(c);
return 0;
}
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) {
explicit_bzero(c, sizeof(*c)); explicit_bzero(c, sizeof(*c));
free(c); free(c);
EVP_CIPHER_CTX_set_app_data(ctx, NULL); EVP_CIPHER_CTX_set_app_data(ctx, NULL);
...@@ -95,9 +102,9 @@ ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, size_t len) ...@@ -95,9 +102,9 @@ ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, size_t len)
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
return 0; return 0;
if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 || if (EVP_Cipher(c->k1, dest, (u_char *)src, len) == 0 ||
EVP_Cipher(&c->k2, dest, dest, len) == 0 || EVP_Cipher(c->k2, dest, dest, len) == 0 ||
EVP_Cipher(&c->k3, dest, dest, len) == 0) EVP_Cipher(c->k3, dest, dest, len) == 0)
return 0; return 0;
return 1; return 1;
} }
...@@ -108,9 +115,9 @@ ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx) ...@@ -108,9 +115,9 @@ ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
struct ssh1_3des_ctx *c; struct ssh1_3des_ctx *c;
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
EVP_CIPHER_CTX_cleanup(&c->k1); EVP_CIPHER_CTX_free(c->k1);
EVP_CIPHER_CTX_cleanup(&c->k2); EVP_CIPHER_CTX_free(c->k2);
EVP_CIPHER_CTX_cleanup(&c->k3); EVP_CIPHER_CTX_free(c->k3);
explicit_bzero(c, sizeof(*c)); explicit_bzero(c, sizeof(*c));
free(c); free(c);
EVP_CIPHER_CTX_set_app_data(ctx, NULL); EVP_CIPHER_CTX_set_app_data(ctx, NULL);
...@@ -128,13 +135,13 @@ ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len) ...@@ -128,13 +135,13 @@ ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
return SSH_ERR_INTERNAL_ERROR; return SSH_ERR_INTERNAL_ERROR;
if (doset) { if (doset) {
memcpy(c->k1.iv, iv, 8); memcpy(EVP_CIPHER_CTX_iv_noconst(c->k1), iv, 8);
memcpy(c->k2.iv, iv + 8, 8); memcpy(EVP_CIPHER_CTX_iv_noconst(c->k2), iv + 8, 8);
memcpy(c->k3.iv, iv + 16, 8); memcpy(EVP_CIPHER_CTX_iv_noconst(c->k3), iv + 16, 8);
} else { } else {
memcpy(iv, c->k1.iv, 8); memcpy(iv, EVP_CIPHER_CTX_iv(c->k1), 8);
memcpy(iv + 8, c->k2.iv, 8); memcpy(iv + 8, EVP_CIPHER_CTX_iv(c->k2), 8);
memcpy(iv + 16, c->k3.iv, 8); memcpy(iv + 16, EVP_CIPHER_CTX_iv(c->k3), 8);
} }
return 0; return 0;
} }
...@@ -142,17 +149,14 @@ ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len) ...@@ -142,17 +149,14 @@ ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
const EVP_CIPHER * const EVP_CIPHER *
evp_ssh1_3des(void) evp_ssh1_3des(void)
{ {
static EVP_CIPHER ssh1_3des; EVP_CIPHER *ssh1_3des;
memset(&ssh1_3des, 0, sizeof(ssh1_3des)); ssh1_3des = EVP_CIPHER_meth_new(NID_undef, 8, 16);
ssh1_3des.nid = NID_undef; EVP_CIPHER_meth_set_iv_length(ssh1_3des, 0);
ssh1_3des.block_size = 8; EVP_CIPHER_meth_set_init(ssh1_3des, ssh1_3des_init);
ssh1_3des.iv_len = 0; EVP_CIPHER_meth_set_cleanup(ssh1_3des, ssh1_3des_cleanup);
ssh1_3des.key_len = 16; EVP_CIPHER_meth_set_do_cipher(ssh1_3des, ssh1_3des_cbc);
ssh1_3des.init = ssh1_3des_init; EVP_CIPHER_meth_set_flags(ssh1_3des, EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH);
ssh1_3des.cleanup = ssh1_3des_cleanup; return ssh1_3des;
ssh1_3des.do_cipher = ssh1_3des_cbc;
ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
return &ssh1_3des;
} }
#endif /* WITH_SSH1 */ #endif /* WITH_SSH1 */
...@@ -89,17 +89,28 @@ bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, ...@@ -89,17 +89,28 @@ bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in,
const EVP_CIPHER * const EVP_CIPHER *
evp_ssh1_bf(void) evp_ssh1_bf(void)
{ {
static EVP_CIPHER ssh1_bf; EVP_CIPHER *ssh1_bf;
memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER)); orig_bf = EVP_CIPHER_meth_get_do_cipher(EVP_bf_cbc());
orig_bf = ssh1_bf.do_cipher; /* block_size, length, flags from openssl/crypto/engine/eng_cryptodev.c:638 */
ssh1_bf.nid = NID_undef; ssh1_bf = EVP_CIPHER_meth_new(NID_undef, 8, 32);
EVP_CIPHER_meth_set_iv_length(ssh1_bf, 8);
EVP_CIPHER_meth_set_flags(ssh1_bf, EVP_CIPH_CBC_MODE);
#ifdef SSH_OLD_EVP #ifdef SSH_OLD_EVP
ssh1_bf.init = bf_ssh1_init; EVP_CIPHER_meth_set_init(ssh1_bf, ssh1_bf_init);
#else
EVP_CIPHER_meth_set_init(ssh1_bf,
EVP_CIPHER_meth_get_init(EVP_bf_cbc()));
#endif #endif
ssh1_bf.do_cipher = bf_ssh1_cipher; /* copy methods and parameters from old EVP_BF_cbc()
ssh1_bf.key_len = 32; * meth_dup does not allow to change type and key_len */
return (&ssh1_bf); EVP_CIPHER_meth_set_cleanup(ssh1_bf,
EVP_CIPHER_meth_get_cleanup(EVP_bf_cbc()));
EVP_CIPHER_meth_set_ctrl(ssh1_bf,
EVP_CIPHER_meth_get_ctrl(EVP_bf_cbc()));
/* ASN1 params??? */
EVP_CIPHER_meth_set_do_cipher(ssh1_bf, bf_ssh1_cipher);
return ssh1_bf;
} }
#endif /* defined(WITH_OPENSSL) && !defined(OPENSSL_NO_BF) */ #endif /* defined(WITH_OPENSSL) && !defined(OPENSSL_NO_BF) */
......
...@@ -372,7 +372,7 @@ cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher, ...@@ -372,7 +372,7 @@ cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher,
ret = SSH_ERR_ALLOC_FAIL; ret = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
} }
if (EVP_CipherInit(cc->evp, type, NULL, (u_char *)iv, if (EVP_CipherInit(cc->evp, type, (u_char *)key, (u_char *)iv,
(do_encrypt == CIPHER_ENCRYPT)) == 0) { (do_encrypt == CIPHER_ENCRYPT)) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR; ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out; goto out;
...@@ -390,10 +390,6 @@ cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher, ...@@ -390,10 +390,6 @@ cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher,
goto out; goto out;
} }
} }
if (EVP_CipherInit(cc->evp, NULL, (u_char *)key, NULL, -1) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if (cipher->discard_len > 0) { if (cipher->discard_len > 0) {
if ((junk = malloc(cipher->discard_len)) == NULL || if ((junk = malloc(cipher->discard_len)) == NULL ||
...@@ -625,7 +621,7 @@ cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len) ...@@ -625,7 +621,7 @@ cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
len, iv)) len, iv))
return SSH_ERR_LIBCRYPTO_ERROR; return SSH_ERR_LIBCRYPTO_ERROR;
} else } else
memcpy(iv, cc->evp->iv, len); memcpy(iv, EVP_CIPHER_CTX_iv(cc->evp), len);
break; break;
#endif #endif
#ifdef WITH_SSH1 #ifdef WITH_SSH1
...@@ -671,7 +667,7 @@ cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv) ...@@ -671,7 +667,7 @@ cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv)) EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv))
return SSH_ERR_LIBCRYPTO_ERROR; return SSH_ERR_LIBCRYPTO_ERROR;
} else } else
memcpy(cc->evp->iv, iv, evplen); memcpy(EVP_CIPHER_CTX_iv_noconst(cc->evp), iv, evplen);
break; break;
#endif #endif
#ifdef WITH_SSH1 #ifdef WITH_SSH1
...@@ -685,8 +681,8 @@ cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv) ...@@ -685,8 +681,8 @@ cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
} }
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
#define EVP_X_STATE(evp) (evp)->cipher_data #define EVP_X_STATE(evp) EVP_CIPHER_CTX_get_cipher_data(evp)
#define EVP_X_STATE_LEN(evp) (evp)->cipher->ctx_size #define EVP_X_STATE_LEN(evp) EVP_CIPHER_impl_ctx_size(EVP_CIPHER_CTX_cipher(evp))
#endif #endif
int int
......
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
/* Define if you have a getaddrinfo that fails for the all-zeros IPv6 address
*/
#undef AIX_GETNAMEINFO_HACK
/* Define if your AIX loginfailed() function takes 4 arguments (AIX >= 5.2) */
#undef AIX_LOGINFAILED_4ARG
/* System only supports IPv4 audit records */
#undef AU_IPv4
/* Define if your resolver libs need this for getrrsetbyname */
#undef BIND_8_COMPAT
/* The system has incomplete BSM API */
#undef BROKEN_BSM_API
/* Define if cmsg_type is not passed correctly */
#undef BROKEN_CMSG_TYPE
/* getaddrinfo is broken (if present) */
#undef BROKEN_GETADDRINFO
/* getgroups(0,NULL) will return -1 */
#undef BROKEN_GETGROUPS
/* FreeBSD glob does not do what we need */
#undef BROKEN_GLOB
/* Define if you system's inet_ntoa is busted (e.g. Irix gcc issue) */
#undef BROKEN_INET_NTOA
/* ia_uinfo routines not supported by OS yet */
#undef BROKEN_LIBIAF
/* Define if your struct dirent expects you to allocate extra space for d_name
*/
#undef BROKEN_ONE_BYTE_DIRENT_D_NAME
/* Can't do comparisons on readv */
#undef BROKEN_READV_COMPARISON
/* NetBSD read function is sometimes redirected, breaking atomicio comparisons
against it */
#undef BROKEN_READ_COMPARISON
/* realpath does not work with nonexistent files */
#undef BROKEN_REALPATH
/* Needed for NeXT */
#undef BROKEN_SAVED_UIDS
/* Define if your setregid() is broken */
#undef BROKEN_SETREGID
/* Define if your setresgid() is broken */
#undef BROKEN_SETRESGID
/* Define if your setresuid() is broken */
#undef BROKEN_SETRESUID
/* Define if your setreuid() is broken */
#undef BROKEN_SETREUID
/* LynxOS has broken setvbuf() implementation */
#undef BROKEN_SETVBUF
/* QNX shadow support is broken */
#undef BROKEN_SHADOW_EXPIRE
/* Define if your snprintf is busted */
#undef BROKEN_SNPRINTF
/* strnvis detected broken */
#undef BROKEN_STRNVIS
/* tcgetattr with ICANON may hang */
#undef BROKEN_TCGETATTR_ICANON
/* updwtmpx is broken (if present) */
#undef BROKEN_UPDWTMPX
/* Define if you have BSD auth support */
#undef BSD_AUTH
/* Define if you want to specify the path to your lastlog file */
#undef CONF_LASTLOG_FILE
/* Define if you want to specify the path to your utmp file */
#undef CONF_UTMP_FILE
/* Define if you want to specify the path to your wtmpx file */
#undef CONF_WTMPX_FILE
/* Define if you want to specify the path to your wtmp file */
#undef CONF_WTMP_FILE
/* Define if your platform needs to skip post auth file descriptor passing */
#undef DISABLE_FD_PASSING
/* Define if you don't want to use lastlog */
#undef DISABLE_LASTLOG
/* Define if you don't want to use your system's login() call */
#undef DISABLE_LOGIN
/* Define if you don't want to use pututline() etc. to write [uw]tmp */
#undef DISABLE_PUTUTLINE
/* Define if you don't want to use pututxline() etc. to write [uw]tmpx */
#undef DISABLE_PUTUTXLINE
/* Define if you want to disable shadow passwords */
#undef DISABLE_SHADOW
/* Define if you don't want to use utmp */
#undef DISABLE_UTMP
/* Define if you don't want to use utmpx */
#undef DISABLE_UTMPX
/* Define if you don't want to use wtmp */
#undef DISABLE_WTMP
/* Define if you don't want to use wtmpx */
#undef DISABLE_WTMPX
/* Enable for PKCS#11 support */
#undef ENABLE_PKCS11
/* File names may not contain backslash characters */
#undef FILESYSTEM_NO_BACKSLASH
/* fsid_t has member val */
#undef FSID_HAS_VAL
/* fsid_t has member __val */
#undef FSID_HAS___VAL
/* Define to 1 if the `getpgrp' function requires zero arguments. */
#undef GETPGRP_VOID
/* Conflicting defs for getspnam */
#undef GETSPNAM_CONFLICTING_DEFS
/* Define if your system glob() function has the GLOB_ALTDIRFUNC extension */
#undef GLOB_HAS_ALTDIRFUNC
/* Define if your system glob() function has gl_matchc options in glob_t */
#undef GLOB_HAS_GL_MATCHC
/* Define if your system glob() function has gl_statv options in glob_t */
#undef GLOB_HAS_GL_STATV
/* Define this if you want GSSAPI support in the version 2 protocol */
#undef GSSAPI
/* Define if you want GSSAPI SSPI support */
#undef GSSAPI_SSPI
/* Define if you want to use shadow password expire field */
#undef HAS_SHADOW_EXPIRE
/* Define if your system uses access rights style file descriptor passing */
#undef HAVE_ACCRIGHTS_IN_MSGHDR
/* Define if you have ut_addr in utmp.h */
#undef HAVE_ADDR_IN_UTMP
/* Define if you have ut_addr in utmpx.h */
#undef HAVE_ADDR_IN_UTMPX
/* Define if you have ut_addr_v6 in utmp.h */
#undef HAVE_ADDR_V6_IN_UTMP
/* Define if you have ut_addr_v6 in utmpx.h */
#undef HAVE_ADDR_V6_IN_UTMPX
/* Define to 1 if you have the `arc4random' function. */
#undef HAVE_ARC4RANDOM
/* Define to 1 if you have the `arc4random_buf' function. */
#undef HAVE_ARC4RANDOM_BUF
/* Define to 1 if you have the `arc4random_stir' function. */
#undef HAVE_ARC4RANDOM_STIR
/* Define to 1 if you have the `arc4random_uniform' function. */
#undef HAVE_ARC4RANDOM_UNIFORM
/* Define to 1 if you have the `asprintf' function. */
#undef HAVE_ASPRINTF
/* OpenBSD's gcc has bounded */
#undef HAVE_ATTRIBUTE__BOUNDED__
/* Have attribute nonnull */
#undef HAVE_ATTRIBUTE__NONNULL__
/* OpenBSD's gcc has sentinel */
#undef HAVE_ATTRIBUTE__SENTINEL__
/* Define to 1 if you have the `aug_get_machine' function. */
#undef HAVE_AUG_GET_MACHINE
/* Define to 1 if you have the `b64_ntop' function. */
#undef HAVE_B64_NTOP
/* Define to 1 if you have the `b64_pton' function. */
#undef HAVE_B64_PTON
/* Define if you have the basename function. */
#undef HAVE_BASENAME
/* Define to 1 if you have the `bcopy' function. */
#undef HAVE_BCOPY
/* Define to 1 if you have the `bcrypt_pbkdf' function. */
#undef HAVE_BCRYPT_PBKDF
/* Define to 1 if you have the `bindresvport_sa' function. */
#undef HAVE_BINDRESVPORT_SA
/* Define to 1 if you have the `blf_enc' function. */
#undef HAVE_BLF_ENC
/* Define to 1 if you have the <blf.h> header file. */
#undef HAVE_BLF_H
/* Define to 1 if you have the `Blowfish_expand0state' function. */
#undef HAVE_BLOWFISH_EXPAND0STATE
/* Define to 1 if you have the `Blowfish_expandstate' function. */
#undef HAVE_BLOWFISH_EXPANDSTATE
/* Define to 1 if you have the `Blowfish_initstate' function. */
#undef HAVE_BLOWFISH_INITSTATE
/* Define to 1 if you have the `Blowfish_stream2word' function. */
#undef HAVE_BLOWFISH_STREAM2WORD
/* Define to 1 if you have the `BN_is_prime_ex' function. */
#undef HAVE_BN_IS_PRIME_EX
/* Define to 1 if you have the <bsd/libutil.h> header file. */
#undef HAVE_BSD_LIBUTIL_H
/* Define to 1 if you have the <bsm/audit.h> header file. */
#undef HAVE_BSM_AUDIT_H
/* Define to 1 if you have the <bstring.h> header file. */
#undef HAVE_BSTRING_H
/* Define to 1 if you have the `cap_rights_limit' function. */
#undef HAVE_CAP_RIGHTS_LIMIT
/* Define to 1 if you have the `clock' function. */
#undef HAVE_CLOCK
/* Have clock_gettime */
#undef HAVE_CLOCK_GETTIME
/* define if you have clock_t data type */
#undef HAVE_CLOCK_T
/* Define to 1 if you have the `closefrom' function. */
#undef HAVE_CLOSEFROM
/* Define if gai_strerror() returns const char * */
#undef HAVE_CONST_GAI_STRERROR_PROTO
/* Define if your system uses ancillary data style file descriptor passing */
#undef HAVE_CONTROL_IN_MSGHDR
/* Define to 1 if you have the `crypt' function. */
#undef HAVE_CRYPT
/* Define to 1 if you have the <crypto/sha2.h> header file. */
#undef HAVE_CRYPTO_SHA2_H
/* Define to 1 if you have the <crypt.h> header file. */
#undef HAVE_CRYPT_H
/* Define if you are on Cygwin */
#undef HAVE_CYGWIN
/* Define if your libraries define daemon() */
#undef HAVE_DAEMON
/* Define to 1 if you have the declaration of `AI_NUMERICSERV', and to 0 if
you don't. */
#undef HAVE_DECL_AI_NUMERICSERV
/* Define to 1 if you have the declaration of `authenticate', and to 0 if you
don't. */
#undef HAVE_DECL_AUTHENTICATE
/* Define to 1 if you have the declaration of `GLOB_NOMATCH', and to 0 if you
don't. */
#undef HAVE_DECL_GLOB_NOMATCH
/* Define to 1 if you have the declaration of `GSS_C_NT_HOSTBASED_SERVICE',
and to 0 if you don't. */
#undef HAVE_DECL_GSS_C_NT_HOSTBASED_SERVICE
/* Define to 1 if you have the declaration of `howmany', and to 0 if you
don't. */
#undef HAVE_DECL_HOWMANY
/* Define to 1 if you have the declaration of `h_errno', and to 0 if you
don't. */
#undef HAVE_DECL_H_ERRNO
/* Define to 1 if you have the declaration of `loginfailed', and to 0 if you
don't. */
#undef HAVE_DECL_LOGINFAILED
/* Define to 1 if you have the declaration of `loginrestrictions', and to 0 if
you don't. */
#undef HAVE_DECL_LOGINRESTRICTIONS
/* Define to 1 if you have the declaration of `loginsuccess', and to 0 if you
don't. */
#undef HAVE_DECL_LOGINSUCCESS
/* Define to 1 if you have the declaration of `MAXSYMLINKS', and to 0 if you
don't. */
#undef HAVE_DECL_MAXSYMLINKS
/* Define to 1 if you have the declaration of `NFDBITS', and to 0 if you
don't. */
#undef HAVE_DECL_NFDBITS
/* Define to 1 if you have the declaration of `offsetof', and to 0 if you
don't. */
#undef HAVE_DECL_OFFSETOF
/* Define to 1 if you have the declaration of `O_NONBLOCK', and to 0 if you
don't. */
#undef HAVE_DECL_O_NONBLOCK
/* Define to 1 if you have the declaration of `passwdexpired', and to 0 if you
don't. */
#undef HAVE_DECL_PASSWDEXPIRED
/* Define to 1 if you have the declaration of `setauthdb', and to 0 if you
don't. */
#undef HAVE_DECL_SETAUTHDB
/* Define to 1 if you have the declaration of `SHUT_RD', and to 0 if you
don't. */
#undef HAVE_DECL_SHUT_RD
/* Define to 1 if you have the declaration of `writev', and to 0 if you don't.
*/
#undef HAVE_DECL_WRITEV
/* Define to 1 if you have the declaration of `_getlong', and to 0 if you
don't. */
#undef HAVE_DECL__GETLONG
/* Define to 1 if you have the declaration of `_getshort', and to 0 if you
don't. */
#undef HAVE_DECL__GETSHORT
/* Define to 1 if you have the `DES_crypt' function. */
#undef HAVE_DES_CRYPT
/* Define if you have /dev/ptmx */
#undef HAVE_DEV_PTMX
/* Define if you have /dev/ptc */
#undef HAVE_DEV_PTS_AND_PTC
/* Define to 1 if you have the <dirent.h> header file. */
#undef HAVE_DIRENT_H
/* Define to 1 if you have the `dirfd' function. */
#undef HAVE_DIRFD
/* Define to 1 if you have the `dirname' function. */
#undef HAVE_DIRNAME
/* Define to 1 if you have the `DSA_generate_parameters_ex' function. */
#undef HAVE_DSA_GENERATE_PARAMETERS_EX
/* Define to 1 if you have the <elf.h> header file. */
#undef HAVE_ELF_H
/* Define to 1 if you have the `endgrent' function. */
#undef HAVE_ENDGRENT
/* Define to 1 if you have the <endian.h> header file. */
#undef HAVE_ENDIAN_H
/* Define to 1 if you have the `endutent' function. */
#undef HAVE_ENDUTENT
/* Define to 1 if you have the `endutxent' function. */
#undef HAVE_ENDUTXENT
/* Define to 1 if you have the `err' function. */
#undef HAVE_ERR
/* Define to 1 if you have the `errx' function. */
#undef HAVE_ERRX
/* Define to 1 if you have the <err.h> header file. */
#undef HAVE_ERR_H
/* Define if your system has /etc/default/login */
#undef HAVE_ETC_DEFAULT_LOGIN
/* Define if libcrypto has EVP_CIPHER_CTX_ctrl */
#undef HAVE_EVP_CIPHER_CTX_CTRL
/* Define to 1 if you have the `EVP_DigestFinal_ex' function. */
#undef HAVE_EVP_DIGESTFINAL_EX
/* Define to 1 if you have the `EVP_DigestInit_ex' function. */
#undef HAVE_EVP_DIGESTINIT_EX
/* Define to 1 if you have the `EVP_MD_CTX_cleanup' function. */
#undef HAVE_EVP_MD_CTX_CLEANUP
/* Define to 1 if you have the `EVP_MD_CTX_copy_ex' function. */
#undef HAVE_EVP_MD_CTX_COPY_EX
/* Define to 1 if you have the `EVP_MD_CTX_init' function. */
#undef HAVE_EVP_MD_CTX_INIT
/* Define to 1 if you have the `EVP_ripemd160' function. */
#undef HAVE_EVP_RIPEMD160
/* Define to 1 if you have the `EVP_sha256' function. */
#undef HAVE_EVP_SHA256
/* Define if you have ut_exit in utmp.h */
#undef HAVE_EXIT_IN_UTMP
/* Define to 1 if you have the `explicit_bzero' function. */
#undef HAVE_EXPLICIT_BZERO
/* Define to 1 if you have the `fchmod' function. */
#undef HAVE_FCHMOD
/* Define to 1 if you have the `fchown' function. */
#undef HAVE_FCHOWN
/* Use F_CLOSEM fcntl for closefrom */
#undef HAVE_FCNTL_CLOSEM
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if the system has the type `fd_mask'. */
#undef HAVE_FD_MASK
/* Define to 1 if you have the <features.h> header file. */
#undef HAVE_FEATURES_H
/* Define to 1 if you have the <floatingpoint.h> header file. */
#undef HAVE_FLOATINGPOINT_H
/* Define to 1 if you have the `fmt_scaled' function. */
#undef HAVE_FMT_SCALED
/* Define to 1 if you have the `freeaddrinfo' function. */
#undef HAVE_FREEADDRINFO
/* Define to 1 if the system has the type `fsblkcnt_t'. */
#undef HAVE_FSBLKCNT_T
/* Define to 1 if the system has the type `fsfilcnt_t'. */
#undef HAVE_FSFILCNT_T
/* Define to 1 if you have the `fstatfs' function. */
#undef HAVE_FSTATFS
/* Define to 1 if you have the `fstatvfs' function. */
#undef HAVE_FSTATVFS
/* Define to 1 if you have the `futimes' function. */
#undef HAVE_FUTIMES
/* Define to 1 if you have the `gai_strerror' function. */
#undef HAVE_GAI_STRERROR
/* Define to 1 if you have the `getaddrinfo' function. */
#undef HAVE_GETADDRINFO
/* Define to 1 if you have the `getaudit' function. */
#undef HAVE_GETAUDIT
/* Define to 1 if you have the `getaudit_addr' function. */
#undef HAVE_GETAUDIT_ADDR
/* Define to 1 if you have the `getcwd' function. */
#undef HAVE_GETCWD
/* Define to 1 if you have the `getgrouplist' function. */
#undef HAVE_GETGROUPLIST
/* Define to 1 if you have the `getgrset' function. */
#undef HAVE_GETGRSET
/* Define to 1 if you have the `getlastlogxbyname' function. */
#undef HAVE_GETLASTLOGXBYNAME
/* Define to 1 if you have the `getluid' function. */
#undef HAVE_GETLUID
/* Define to 1 if you have the `getnameinfo' function. */
#undef HAVE_GETNAMEINFO
/* Define to 1 if you have the `getopt' function. */
#undef HAVE_GETOPT
/* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
/* Define if your getopt(3) defines and uses optreset */
#undef HAVE_GETOPT_OPTRESET
/* Define if your libraries define getpagesize() */
#undef HAVE_GETPAGESIZE
/* Define to 1 if you have the `getpeereid' function. */
#undef HAVE_GETPEEREID
/* Define to 1 if you have the `getpeerucred' function. */
#undef HAVE_GETPEERUCRED
/* Define to 1 if you have the `getpgid' function. */
#undef HAVE_GETPGID
/* Define to 1 if you have the `getpgrp' function. */
#undef HAVE_GETPGRP
/* Define to 1 if you have the `getpwanam' function. */
#undef HAVE_GETPWANAM
/* Define to 1 if you have the `getrlimit' function. */
#undef HAVE_GETRLIMIT
/* Define if getrrsetbyname() exists */
#undef HAVE_GETRRSETBYNAME
/* Define to 1 if you have the `getrusage' function. */
#undef HAVE_GETRUSAGE
/* Define to 1 if you have the `getseuserbyname' function. */
#undef HAVE_GETSEUSERBYNAME
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define to 1 if you have the `getttyent' function. */
#undef HAVE_GETTTYENT
/* Define to 1 if you have the `getutent' function. */
#undef HAVE_GETUTENT
/* Define to 1 if you have the `getutid' function. */
#undef HAVE_GETUTID
/* Define to 1 if you have the `getutline' function. */
#undef HAVE_GETUTLINE
/* Define to 1 if you have the `getutxent' function. */
#undef HAVE_GETUTXENT
/* Define to 1 if you have the `getutxid' function. */
#undef HAVE_GETUTXID
/* Define to 1 if you have the `getutxline' function. */
#undef HAVE_GETUTXLINE
/* Define to 1 if you have the `getutxuser' function. */
#undef HAVE_GETUTXUSER
/* Define to 1 if you have the `get_default_context_with_level' function. */
#undef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
/* Define to 1 if you have the `glob' function. */
#undef HAVE_GLOB
/* Define to 1 if you have the <glob.h> header file. */
#undef HAVE_GLOB_H
/* Define to 1 if you have the `group_from_gid' function. */
#undef HAVE_GROUP_FROM_GID
/* Define to 1 if you have the <gssapi_generic.h> header file. */
#undef HAVE_GSSAPI_GENERIC_H
/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
#undef HAVE_GSSAPI_GSSAPI_GENERIC_H
/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
#undef HAVE_GSSAPI_GSSAPI_H
/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
#undef HAVE_GSSAPI_GSSAPI_KRB5_H
/* Define to 1 if you have the <gssapi.h> header file. */
#undef HAVE_GSSAPI_H
/* Define to 1 if you have the <gssapi_krb5.h> header file. */
#undef HAVE_GSSAPI_KRB5_H
/* Define if HEADER.ad exists in arpa/nameser.h */
#undef HAVE_HEADER_AD
/* Define to 1 if you have the `HMAC_CTX_init' function. */
#undef HAVE_HMAC_CTX_INIT
/* Define if you have ut_host in utmp.h */
#undef HAVE_HOST_IN_UTMP
/* Define if you have ut_host in utmpx.h */
#undef HAVE_HOST_IN_UTMPX
/* Define to 1 if you have the <iaf.h> header file. */
#undef HAVE_IAF_H
/* Define to 1 if you have the <ia.h> header file. */
#undef HAVE_IA_H
/* Define if you have ut_id in utmp.h */
#undef HAVE_ID_IN_UTMP
/* Define if you have ut_id in utmpx.h */
#undef HAVE_ID_IN_UTMPX
/* Define to 1 if you have the `inet_aton' function. */
#undef HAVE_INET_ATON
/* Define to 1 if you have the `inet_ntoa' function. */
#undef HAVE_INET_NTOA
/* Define to 1 if you have the `inet_ntop' function. */
#undef HAVE_INET_NTOP
/* Define to 1 if you have the `innetgr' function. */
#undef HAVE_INNETGR
/* define if you have int64_t data type */
#undef HAVE_INT64_T
/* Define to 1 if the system has the type `intmax_t'. */
#undef HAVE_INTMAX_T
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* define if you have intxx_t data type */
#undef HAVE_INTXX_T
/* Define to 1 if the system has the type `in_addr_t'. */
#undef HAVE_IN_ADDR_T
/* Define to 1 if the system has the type `in_port_t'. */
#undef HAVE_IN_PORT_T
/* Define if you have isblank(3C). */
#undef HAVE_ISBLANK
/* Define to 1 if you have the `krb5_cc_new_unique' function. */
#undef HAVE_KRB5_CC_NEW_UNIQUE
/* Define to 1 if you have the `krb5_free_error_message' function. */
#undef HAVE_KRB5_FREE_ERROR_MESSAGE
/* Define to 1 if you have the `krb5_get_error_message' function. */
#undef HAVE_KRB5_GET_ERROR_MESSAGE
/* Define to 1 if you have the <langinfo.h> header file. */
#undef HAVE_LANGINFO_H
/* Define to 1 if you have the <lastlog.h> header file. */
#undef HAVE_LASTLOG_H
/* Define if you want ldns support */
#undef HAVE_LDNS
/* Define to 1 if you have the <libaudit.h> header file. */
#undef HAVE_LIBAUDIT_H
/* Define to 1 if you have the `bsm' library (-lbsm). */
#undef HAVE_LIBBSM
/* Define to 1 if you have the `crypt' library (-lcrypt). */
#undef HAVE_LIBCRYPT
/* Define to 1 if you have the `dl' library (-ldl). */
#undef HAVE_LIBDL
/* Define to 1 if you have the <libgen.h> header file. */
#undef HAVE_LIBGEN_H
/* Define if system has libiaf that supports set_id */
#undef HAVE_LIBIAF
/* Define to 1 if you have the `network' library (-lnetwork). */
#undef HAVE_LIBNETWORK
/* Define to 1 if you have the `pam' library (-lpam). */
#undef HAVE_LIBPAM
/* Define to 1 if you have the `socket' library (-lsocket). */
#undef HAVE_LIBSOCKET
/* Define to 1 if you have the <libutil.h> header file. */
#undef HAVE_LIBUTIL_H
/* Define to 1 if you have the `xnet' library (-lxnet). */
#undef HAVE_LIBXNET
/* Define to 1 if you have the `z' library (-lz). */
#undef HAVE_LIBZ
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if you have the <linux/audit.h> header file. */
#undef HAVE_LINUX_AUDIT_H
/* Define to 1 if you have the <linux/filter.h> header file. */
#undef HAVE_LINUX_FILTER_H
/* Define to 1 if you have the <linux/if_tun.h> header file. */
#undef HAVE_LINUX_IF_TUN_H
/* Define to 1 if you have the <linux/seccomp.h> header file. */
#undef HAVE_LINUX_SECCOMP_H
/* Define to 1 if you have the `llabs' function. */
#undef HAVE_LLABS
/* Define to 1 if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H
/* Define to 1 if you have the `login' function. */
#undef HAVE_LOGIN
/* Define to 1 if you have the <login_cap.h> header file. */
#undef HAVE_LOGIN_CAP_H
/* Define to 1 if you have the `login_getcapbool' function. */
#undef HAVE_LOGIN_GETCAPBOOL
/* Define to 1 if you have the <login.h> header file. */
#undef HAVE_LOGIN_H
/* Define to 1 if you have the `logout' function. */
#undef HAVE_LOGOUT
/* Define to 1 if you have the `logwtmp' function. */
#undef HAVE_LOGWTMP
/* Define to 1 if the system has the type `long double'. */
#undef HAVE_LONG_DOUBLE
/* Define to 1 if the system has the type `long long'. */
#undef HAVE_LONG_LONG
/* Define to 1 if you have the <maillock.h> header file. */
#undef HAVE_MAILLOCK_H
/* Define to 1 if you have the `mblen' function. */
#undef HAVE_MBLEN
/* Define to 1 if you have the `mbtowc' function. */
#undef HAVE_MBTOWC
/* Define to 1 if you have the `md5_crypt' function. */
#undef HAVE_MD5_CRYPT
/* Define if you want to allow MD5 passwords */
#undef HAVE_MD5_PASSWORDS
/* Define to 1 if you have the `memmove' function. */
#undef HAVE_MEMMOVE
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `memset_s' function. */
#undef HAVE_MEMSET_S
/* Define to 1 if you have the `mkdtemp' function. */
#undef HAVE_MKDTEMP
/* define if you have mode_t data type */
#undef HAVE_MODE_T
/* Some systems put nanosleep outside of libc */
#undef HAVE_NANOSLEEP
/* Define to 1 if you have the <ndir.h> header file. */
#undef HAVE_NDIR_H
/* Define to 1 if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
/* Define to 1 if you have the <netgroup.h> header file. */
#undef HAVE_NETGROUP_H
/* Define to 1 if you have the <net/if_tun.h> header file. */
#undef HAVE_NET_IF_TUN_H
/* Define if you are on NeXT */
#undef HAVE_NEXT
/* Define to 1 if you have the `ngetaddrinfo' function. */
#undef HAVE_NGETADDRINFO
/* Define to 1 if you have the `nl_langinfo' function. */
#undef HAVE_NL_LANGINFO
/* Define to 1 if you have the `nsleep' function. */
#undef HAVE_NSLEEP
/* Define to 1 if you have the `ogetaddrinfo' function. */
#undef HAVE_OGETADDRINFO
/* Define if you have an old version of PAM which takes only one argument to
pam_strerror */
#undef HAVE_OLD_PAM
/* Define to 1 if you have the `openlog_r' function. */
#undef HAVE_OPENLOG_R
/* Define to 1 if you have the `openpty' function. */
#undef HAVE_OPENPTY
/* Define if your ssl headers are included with #include <openssl/header.h> */
#undef HAVE_OPENSSL
/* Define if you have Digital Unix Security Integration Architecture */
#undef HAVE_OSF_SIA
/* Define to 1 if you have the `pam_getenvlist' function. */
#undef HAVE_PAM_GETENVLIST
/* Define to 1 if you have the <pam/pam_appl.h> header file. */
#undef HAVE_PAM_PAM_APPL_H
/* Define to 1 if you have the `pam_putenv' function. */
#undef HAVE_PAM_PUTENV
/* Define to 1 if you have the <paths.h> header file. */
#undef HAVE_PATHS_H
/* Define if you have ut_pid in utmp.h */
#undef HAVE_PID_IN_UTMP
/* define if you have pid_t data type */
#undef HAVE_PID_T
/* Define to 1 if you have the `pledge' function. */
#undef HAVE_PLEDGE
/* Define to 1 if you have the `poll' function. */
#undef HAVE_POLL
/* Define to 1 if you have the <poll.h> header file. */
#undef HAVE_POLL_H
/* Define to 1 if you have the `prctl' function. */
#undef HAVE_PRCTL
/* Define to 1 if you have the `priv_basicset' function. */
#undef HAVE_PRIV_BASICSET
/* Define to 1 if you have the <priv.h> header file. */
#undef HAVE_PRIV_H
/* Define if you have /proc/$pid/fd */
#undef HAVE_PROC_PID
/* Define to 1 if you have the `pstat' function. */
#undef HAVE_PSTAT
/* Define to 1 if you have the <pty.h> header file. */
#undef HAVE_PTY_H
/* Define to 1 if you have the `pututline' function. */
#undef HAVE_PUTUTLINE
/* Define to 1 if you have the `pututxline' function. */
#undef HAVE_PUTUTXLINE
/* Define to 1 if you have the `readpassphrase' function. */
#undef HAVE_READPASSPHRASE
/* Define to 1 if you have the <readpassphrase.h> header file. */
#undef HAVE_READPASSPHRASE_H
/* Define to 1 if you have the `reallocarray' function. */
#undef HAVE_REALLOCARRAY
/* Define to 1 if you have the `realpath' function. */
#undef HAVE_REALPATH
/* Define to 1 if you have the `recvmsg' function. */
#undef HAVE_RECVMSG
/* sys/resource.h has RLIMIT_NPROC */
#undef HAVE_RLIMIT_NPROC
/* Define to 1 if you have the <rpc/types.h> header file. */
#undef HAVE_RPC_TYPES_H
/* Define to 1 if you have the `rresvport_af' function. */
#undef HAVE_RRESVPORT_AF
/* Define to 1 if you have the `RSA_generate_key_ex' function. */
#undef HAVE_RSA_GENERATE_KEY_EX
/* Define to 1 if you have the `RSA_get_default_method' function. */
#undef HAVE_RSA_GET_DEFAULT_METHOD
/* Define to 1 if you have the <sandbox.h> header file. */
#undef HAVE_SANDBOX_H
/* Define to 1 if you have the `sandbox_init' function. */
#undef HAVE_SANDBOX_INIT
/* define if you have sa_family_t data type */
#undef HAVE_SA_FAMILY_T
/* Define to 1 if you have the `scan_scaled' function. */
#undef HAVE_SCAN_SCALED
/* Define if you have SecureWare-based protected password database */
#undef HAVE_SECUREWARE
/* Define to 1 if you have the <security/pam_appl.h> header file. */
#undef HAVE_SECURITY_PAM_APPL_H
/* Define to 1 if you have the `sendmsg' function. */
#undef HAVE_SENDMSG
/* Define to 1 if you have the `setauthdb' function. */
#undef HAVE_SETAUTHDB
/* Define to 1 if you have the `setdtablesize' function. */
#undef HAVE_SETDTABLESIZE
/* Define to 1 if you have the `setegid' function. */
#undef HAVE_SETEGID
/* Define to 1 if you have the `setenv' function. */
#undef HAVE_SETENV
/* Define to 1 if you have the `seteuid' function. */
#undef HAVE_SETEUID
/* Define to 1 if you have the `setgroupent' function. */
#undef HAVE_SETGROUPENT
/* Define to 1 if you have the `setgroups' function. */
#undef HAVE_SETGROUPS
/* Define to 1 if you have the `setlinebuf' function. */
#undef HAVE_SETLINEBUF
/* Define to 1 if you have the `setlogin' function. */
#undef HAVE_SETLOGIN
/* Define to 1 if you have the `setluid' function. */
#undef HAVE_SETLUID
/* Define to 1 if you have the `setpassent' function. */
#undef HAVE_SETPASSENT
/* Define to 1 if you have the `setpcred' function. */
#undef HAVE_SETPCRED
/* Define to 1 if you have the `setpflags' function. */
#undef HAVE_SETPFLAGS
/* Define to 1 if you have the `setppriv' function. */
#undef HAVE_SETPPRIV
/* Define to 1 if you have the `setproctitle' function. */
#undef HAVE_SETPROCTITLE
/* Define to 1 if you have the `setregid' function. */
#undef HAVE_SETREGID
/* Define to 1 if you have the `setresgid' function. */
#undef HAVE_SETRESGID
/* Define to 1 if you have the `setresuid' function. */
#undef HAVE_SETRESUID
/* Define to 1 if you have the `setreuid' function. */
#undef HAVE_SETREUID
/* Define to 1 if you have the `setrlimit' function. */
#undef HAVE_SETRLIMIT
/* Define to 1 if you have the `setsid' function. */
#undef HAVE_SETSID
/* Define to 1 if you have the `setutent' function. */
#undef HAVE_SETUTENT
/* Define to 1 if you have the `setutxdb' function. */
#undef HAVE_SETUTXDB
/* Define to 1 if you have the `setutxent' function. */
#undef HAVE_SETUTXENT
/* Define to 1 if you have the `setvbuf' function. */
#undef HAVE_SETVBUF
/* Define to 1 if you have the `set_id' function. */
#undef HAVE_SET_ID
/* Define to 1 if you have the `SHA256_Update' function. */
#undef HAVE_SHA256_UPDATE
/* Define to 1 if you have the <sha2.h> header file. */
#undef HAVE_SHA2_H
/* Define to 1 if you have the <shadow.h> header file. */
#undef HAVE_SHADOW_H
/* Define to 1 if you have the `sigaction' function. */
#undef HAVE_SIGACTION
/* Define to 1 if you have the `sigvec' function. */
#undef HAVE_SIGVEC
/* Define to 1 if the system has the type `sig_atomic_t'. */
#undef HAVE_SIG_ATOMIC_T
/* define if you have size_t data type */
#undef HAVE_SIZE_T
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
/* Define to 1 if you have the `socketpair' function. */
#undef HAVE_SOCKETPAIR
/* Have PEERCRED socket option */
#undef HAVE_SO_PEERCRED
/* define if you have ssize_t data type */
#undef HAVE_SSIZE_T
/* Fields in struct sockaddr_storage */
#undef HAVE_SS_FAMILY_IN_SS
/* Define to 1 if you have the `statfs' function. */
#undef HAVE_STATFS
/* Define to 1 if you have the `statvfs' function. */
#undef HAVE_STATVFS
/* Define to 1 if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strcasestr' function. */
#undef HAVE_STRCASESTR
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the `strftime' function. */
#undef HAVE_STRFTIME
/* Silly mkstemp() */
#undef HAVE_STRICT_MKSTEMP
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strlcat' function. */
#undef HAVE_STRLCAT
/* Define to 1 if you have the `strlcpy' function. */
#undef HAVE_STRLCPY
/* Define to 1 if you have the `strmode' function. */
#undef HAVE_STRMODE
/* Define to 1 if you have the `strnlen' function. */
#undef HAVE_STRNLEN
/* Define to 1 if you have the `strnvis' function. */
#undef HAVE_STRNVIS
/* Define to 1 if you have the `strptime' function. */
#undef HAVE_STRPTIME
/* Define to 1 if you have the `strsep' function. */
#undef HAVE_STRSEP
/* Define to 1 if you have the `strtoll' function. */
#undef HAVE_STRTOLL
/* Define to 1 if you have the `strtonum' function. */
#undef HAVE_STRTONUM
/* Define to 1 if you have the `strtoul' function. */
#undef HAVE_STRTOUL
/* Define to 1 if you have the `strtoull' function. */
#undef HAVE_STRTOULL
/* define if you have struct addrinfo data type */
#undef HAVE_STRUCT_ADDRINFO
/* define if you have struct in6_addr data type */
#undef HAVE_STRUCT_IN6_ADDR
/* Define to 1 if `pw_change' is a member of `struct passwd'. */
#undef HAVE_STRUCT_PASSWD_PW_CHANGE
/* Define to 1 if `pw_class' is a member of `struct passwd'. */
#undef HAVE_STRUCT_PASSWD_PW_CLASS
/* Define to 1 if `pw_expire' is a member of `struct passwd'. */
#undef HAVE_STRUCT_PASSWD_PW_EXPIRE
/* Define to 1 if `pw_gecos' is a member of `struct passwd'. */
#undef HAVE_STRUCT_PASSWD_PW_GECOS
/* define if you have struct sockaddr_in6 data type */
#undef HAVE_STRUCT_SOCKADDR_IN6
/* Define to 1 if `sin6_scope_id' is a member of `struct sockaddr_in6'. */
#undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
/* define if you have struct sockaddr_storage data type */
#undef HAVE_STRUCT_SOCKADDR_STORAGE
/* Define to 1 if `st_blksize' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLKSIZE
/* Define to 1 if the system has the type `struct timespec'. */
#undef HAVE_STRUCT_TIMESPEC
/* define if you have struct timeval */
#undef HAVE_STRUCT_TIMEVAL
/* Define to 1 if you have the `swap32' function. */
#undef HAVE_SWAP32
/* Define to 1 if you have the `sysconf' function. */
#undef HAVE_SYSCONF
/* Define if you have syslen in utmpx.h */
#undef HAVE_SYSLEN_IN_UTMPX
/* Define to 1 if you have the <sys/audit.h> header file. */
#undef HAVE_SYS_AUDIT_H
/* Define to 1 if you have the <sys/bitypes.h> header file. */
#undef HAVE_SYS_BITYPES_H
/* Define to 1 if you have the <sys/bsdtty.h> header file. */
#undef HAVE_SYS_BSDTTY_H
/* Define to 1 if you have the <sys/capability.h> header file. */
#undef HAVE_SYS_CAPABILITY_H
/* Define to 1 if you have the <sys/cdefs.h> header file. */
#undef HAVE_SYS_CDEFS_H
/* Define to 1 if you have the <sys/dir.h> header file. */
#undef HAVE_SYS_DIR_H
/* Define if your system defines sys_errlist[] */
#undef HAVE_SYS_ERRLIST
/* Define to 1 if you have the <sys/mman.h> header file. */
#undef HAVE_SYS_MMAN_H
/* Define to 1 if you have the <sys/mount.h> header file. */
#undef HAVE_SYS_MOUNT_H
/* Define to 1 if you have the <sys/ndir.h> header file. */
#undef HAVE_SYS_NDIR_H
/* Define if your system defines sys_nerr */
#undef HAVE_SYS_NERR
/* Define to 1 if you have the <sys/poll.h> header file. */
#undef HAVE_SYS_POLL_H
/* Define to 1 if you have the <sys/prctl.h> header file. */
#undef HAVE_SYS_PRCTL_H
/* Define to 1 if you have the <sys/pstat.h> header file. */
#undef HAVE_SYS_PSTAT_H
/* Define to 1 if you have the <sys/ptms.h> header file. */
#undef HAVE_SYS_PTMS_H
/* Define to 1 if you have the <sys/ptrace.h> header file. */
#undef HAVE_SYS_PTRACE_H
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define to 1 if you have the <sys/statvfs.h> header file. */
#undef HAVE_SYS_STATVFS_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/stream.h> header file. */
#undef HAVE_SYS_STREAM_H
/* Define to 1 if you have the <sys/stropts.h> header file. */
#undef HAVE_SYS_STROPTS_H
/* Define to 1 if you have the <sys/strtio.h> header file. */
#undef HAVE_SYS_STRTIO_H
/* Force use of sys/syslog.h on Ultrix */
#undef HAVE_SYS_SYSLOG_H
/* Define to 1 if you have the <sys/sysmacros.h> header file. */
#undef HAVE_SYS_SYSMACROS_H
/* Define to 1 if you have the <sys/timers.h> header file. */
#undef HAVE_SYS_TIMERS_H
/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <sys/un.h> header file. */
#undef HAVE_SYS_UN_H
/* Define to 1 if you have the `tcgetpgrp' function. */
#undef HAVE_TCGETPGRP
/* Define to 1 if you have the `tcsendbreak' function. */
#undef HAVE_TCSENDBREAK
/* Define to 1 if you have the `time' function. */
#undef HAVE_TIME
/* Define to 1 if you have the <time.h> header file. */
#undef HAVE_TIME_H
/* Define if you have ut_time in utmp.h */
#undef HAVE_TIME_IN_UTMP
/* Define if you have ut_time in utmpx.h */
#undef HAVE_TIME_IN_UTMPX
/* Define to 1 if you have the `timingsafe_bcmp' function. */
#undef HAVE_TIMINGSAFE_BCMP
/* Define to 1 if you have the <tmpdir.h> header file. */
#undef HAVE_TMPDIR_H
/* Define to 1 if you have the `truncate' function. */
#undef HAVE_TRUNCATE
/* Define to 1 if you have the <ttyent.h> header file. */
#undef HAVE_TTYENT_H
/* Define if you have ut_tv in utmp.h */
#undef HAVE_TV_IN_UTMP
/* Define if you have ut_tv in utmpx.h */
#undef HAVE_TV_IN_UTMPX
/* Define if you have ut_type in utmp.h */
#undef HAVE_TYPE_IN_UTMP
/* Define if you have ut_type in utmpx.h */
#undef HAVE_TYPE_IN_UTMPX
/* Define to 1 if you have the <ucred.h> header file. */
#undef HAVE_UCRED_H
/* Define to 1 if the system has the type `uintmax_t'. */
#undef HAVE_UINTMAX_T
/* define if you have uintxx_t data type */
#undef HAVE_UINTXX_T
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `unsetenv' function. */
#undef HAVE_UNSETENV
/* Define to 1 if the system has the type `unsigned long long'. */
#undef HAVE_UNSIGNED_LONG_LONG
/* Define to 1 if you have the `updwtmp' function. */
#undef HAVE_UPDWTMP
/* Define to 1 if you have the `updwtmpx' function. */
#undef HAVE_UPDWTMPX
/* Define to 1 if you have the <usersec.h> header file. */
#undef HAVE_USERSEC_H
/* Define to 1 if you have the `user_from_uid' function. */
#undef HAVE_USER_FROM_UID
/* Define to 1 if you have the `usleep' function. */
#undef HAVE_USLEEP
/* Define to 1 if you have the <util.h> header file. */
#undef HAVE_UTIL_H
/* Define to 1 if you have the `utimes' function. */
#undef HAVE_UTIMES
/* Define to 1 if you have the <utime.h> header file. */
#undef HAVE_UTIME_H
/* Define to 1 if you have the `utmpname' function. */
#undef HAVE_UTMPNAME
/* Define to 1 if you have the `utmpxname' function. */
#undef HAVE_UTMPXNAME
/* Define to 1 if you have the <utmpx.h> header file. */
#undef HAVE_UTMPX_H
/* Define to 1 if you have the <utmp.h> header file. */
#undef HAVE_UTMP_H
/* define if you have u_char data type */
#undef HAVE_U_CHAR
/* define if you have u_int data type */
#undef HAVE_U_INT
/* define if you have u_int64_t data type */
#undef HAVE_U_INT64_T
/* define if you have u_intxx_t data type */
#undef HAVE_U_INTXX_T
/* Define to 1 if you have the `vasprintf' function. */
#undef HAVE_VASPRINTF
/* Define if va_copy exists */
#undef HAVE_VA_COPY
/* Define to 1 if you have the <vis.h> header file. */
#undef HAVE_VIS_H
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
/* Define to 1 if you have the `waitpid' function. */
#undef HAVE_WAITPID
/* Define to 1 if you have the `warn' function. */
#undef HAVE_WARN
/* Define to 1 if you have the <wchar.h> header file. */
#undef HAVE_WCHAR_H
/* Define to 1 if you have the `wcwidth' function. */
#undef HAVE_WCWIDTH
/* Define to 1 if you have the `_getlong' function. */
#undef HAVE__GETLONG
/* Define to 1 if you have the `_getpty' function. */
#undef HAVE__GETPTY
/* Define to 1 if you have the `_getshort' function. */
#undef HAVE__GETSHORT
/* Define if you have struct __res_state _res as an extern */
#undef HAVE__RES_EXTERN
/* Define to 1 if you have the `__b64_ntop' function. */
#undef HAVE___B64_NTOP
/* Define to 1 if you have the `__b64_pton' function. */
#undef HAVE___B64_PTON
/* Define if compiler implements __FUNCTION__ */
#undef HAVE___FUNCTION__
/* Define if libc defines __progname */
#undef HAVE___PROGNAME
/* Fields in struct sockaddr_storage */
#undef HAVE___SS_FAMILY_IN_SS
/* Define if __va_copy exists */
#undef HAVE___VA_COPY
/* Define if compiler implements __func__ */
#undef HAVE___func__
/* Define this if you are using the Heimdal version of Kerberos V5 */
#undef HEIMDAL
/* Define if you need to use IP address instead of hostname in $DISPLAY */
#undef IPADDR_IN_DISPLAY
/* Detect IPv4 in IPv6 mapped addresses and treat as IPv4 */
#undef IPV4_IN_IPV6
/* Define if your system choked on IP TOS setting */
#undef IP_TOS_IS_BROKEN
/* Define if you want Kerberos 5 support */
#undef KRB5
/* Define if pututxline updates lastlog too */
#undef LASTLOG_WRITE_PUTUTXLINE
/* Define to whatever link() returns for "not supported" if it doesn't return
EOPNOTSUPP. */
#undef LINK_OPNOTSUPP_ERRNO
/* Adjust Linux out-of-memory killer */
#undef LINUX_OOM_ADJUST
/* max value of long long calculated by configure */
#undef LLONG_MAX
/* min value of long long calculated by configure */
#undef LLONG_MIN
/* Account locked with pw(1) */
#undef LOCKED_PASSWD_PREFIX
/* String used in /etc/passwd to denote locked account */
#undef LOCKED_PASSWD_STRING
/* String used in /etc/passwd to denote locked account */
#undef LOCKED_PASSWD_SUBSTR
/* Some systems need a utmpx entry for /bin/login to work */
#undef LOGIN_NEEDS_UTMPX
/* Set this to your mail directory if you do not have _PATH_MAILDIR */
#undef MAIL_DIRECTORY
/* Need setpgrp to acquire controlling tty */
#undef NEED_SETPGRP
/* compiler does not accept __attribute__ on return types */
#undef NO_ATTRIBUTE_ON_RETURN_TYPE
/* Define if you don't want to use lastlog in session.c */
#undef NO_SSH_LASTLOG
/* Define to disable UID restoration test */
#undef NO_UID_RESTORATION_TEST
/* Define if X11 doesn't support AF_UNIX sockets on that system */
#undef NO_X11_UNIX_SOCKETS
/* Define if EVP_DigestUpdate returns void */
#undef OPENSSL_EVP_DIGESTUPDATE_VOID
/* OpenSSL has ECC */
#undef OPENSSL_HAS_ECC
/* libcrypto has NID_X9_62_prime256v1 */
#undef OPENSSL_HAS_NISTP256
/* libcrypto has NID_secp384r1 */
#undef OPENSSL_HAS_NISTP384
/* libcrypto has NID_secp521r1 */
#undef OPENSSL_HAS_NISTP521
/* libcrypto has EVP AES CTR */
#undef OPENSSL_HAVE_EVPCTR
/* libcrypto has EVP AES GCM */
#undef OPENSSL_HAVE_EVPGCM
/* libcrypto is missing AES 192 and 256 bit functions */
#undef OPENSSL_LOBOTOMISED_AES
/* Define if you want the OpenSSL internally seeded PRNG only */
#undef OPENSSL_PRNG_ONLY
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define if you are using Solaris-derived PAM which passes pam_messages to
the conversation function with an extra level of indirection */
#undef PAM_SUN_CODEBASE
/* Work around problematic Linux PAM modules handling of PAM_TTY */
#undef PAM_TTY_KLUDGE
/* must supply username to passwd */
#undef PASSWD_NEEDS_USERNAME
/* System dirs owned by bin (uid 2) */
#undef PLATFORM_SYS_DIR_UID
/* Port number of PRNGD/EGD random number socket */
#undef PRNGD_PORT
/* Location of PRNGD/EGD random number socket */
#undef PRNGD_SOCKET
/* read(1) can return 0 for a non-closed fd */
#undef PTY_ZEROREAD
/* Sandbox using capsicum */
#undef SANDBOX_CAPSICUM
/* Sandbox using Darwin sandbox_init(3) */
#undef SANDBOX_DARWIN
/* no privsep sandboxing */
#undef SANDBOX_NULL
/* Sandbox using pledge(2) */
#undef SANDBOX_PLEDGE
/* Sandbox using setrlimit(2) */
#undef SANDBOX_RLIMIT
/* Sandbox using seccomp filter */
#undef SANDBOX_SECCOMP_FILTER
/* setrlimit RLIMIT_FSIZE works */
#undef SANDBOX_SKIP_RLIMIT_FSIZE
/* define if setrlimit RLIMIT_NOFILE breaks things */
#undef SANDBOX_SKIP_RLIMIT_NOFILE
/* Sandbox using Solaris/Illumos privileges */
#undef SANDBOX_SOLARIS
/* Sandbox using systrace(4) */
#undef SANDBOX_SYSTRACE
/* Specify the system call convention in use */
#undef SECCOMP_AUDIT_ARCH
/* Define if your platform breaks doing a seteuid before a setuid */
#undef SETEUID_BREAKS_SETUID
/* The size of `int', as computed by sizeof. */
#undef SIZEOF_INT
/* The size of `long int', as computed by sizeof. */
#undef SIZEOF_LONG_INT
/* The size of `long long int', as computed by sizeof. */
#undef SIZEOF_LONG_LONG_INT
/* The size of `short int', as computed by sizeof. */
#undef SIZEOF_SHORT_INT
/* Define if you want S/Key support */
#undef SKEY
/* Define if your skeychallenge() function takes 4 arguments (NetBSD) */
#undef SKEYCHALLENGE_4ARG
/* Define as const if snprintf() can declare const char *fmt */
#undef SNPRINTF_CONST
/* Define to a Set Process Title type if your system is supported by
bsd-setproctitle.c */
#undef SPT_TYPE
/* Define if sshd somehow reacquires a controlling TTY after setsid() */
#undef SSHD_ACQUIRES_CTTY
/* sshd PAM service name */
#undef SSHD_PAM_SERVICE
/* Define if pam_chauthtok wants real uid set to the unpriv'ed user */
#undef SSHPAM_CHAUTHTOK_NEEDS_RUID
/* Use audit debugging module */
#undef SSH_AUDIT_EVENTS
/* Windows is sensitive to read buffer size */
#undef SSH_IOBUFSZ
/* non-privileged user for privilege separation */
#undef SSH_PRIVSEP_USER
/* Use tunnel device compatibility to OpenBSD */
#undef SSH_TUN_COMPAT_AF
/* Open tunnel devices the FreeBSD way */
#undef SSH_TUN_FREEBSD
/* Open tunnel devices the Linux tun/tap way */
#undef SSH_TUN_LINUX
/* No layer 2 tunnel support */
#undef SSH_TUN_NO_L2
/* Open tunnel devices the OpenBSD way */
#undef SSH_TUN_OPENBSD
/* Prepend the address family to IP tunnel traffic */
#undef SSH_TUN_PREPEND_AF
/* Define if you want SSPI support */
#undef SSPI
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define if you want a different $PATH for the superuser */
#undef SUPERUSER_PATH
/* syslog_r function is safe to use in in a signal handler */
#undef SYSLOG_R_SAFE_IN_SIGHAND
/* Support passwords > 8 chars */
#undef UNIXWARE_LONG_PASSWORDS
/* Specify default $PATH */
#undef USER_PATH
/* Define this if you want to use libkafs' AFS support */
#undef USE_AFS
/* Use BSM audit module */
#undef USE_BSM_AUDIT
/* Use btmp to log bad logins */
#undef USE_BTMP
/* Use libedit for sftp */
#undef USE_LIBEDIT
/* Use Linux audit module */
#undef USE_LINUX_AUDIT
/* Enable OpenSSL engine support */
#undef USE_OPENSSL_ENGINE
/* Define if you want to enable PAM support */
#undef USE_PAM
/* Use PIPES instead of a socketpair() */
#undef USE_PIPES
/* Define if you have Solaris privileges */
#undef USE_SOLARIS_PRIVS
/* Define if you have Solaris process contracts */
#undef USE_SOLARIS_PROCESS_CONTRACTS
/* Define if you have Solaris projects */
#undef USE_SOLARIS_PROJECTS
/* Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp */
#undef WITH_ABBREV_NO_TTY
/* Define if you want to enable AIX4's authenticate function */
#undef WITH_AIXAUTHENTICATE
/* Define if you have/want arrays (cluster-wide session managment, not C
arrays) */
#undef WITH_IRIX_ARRAY
/* Define if you want IRIX audit trails */
#undef WITH_IRIX_AUDIT
/* Define if you want IRIX kernel jobs */
#undef WITH_IRIX_JOBS
/* Define if you want IRIX project management */
#undef WITH_IRIX_PROJECT
/* use libcrypto for cryptography */
#undef WITH_OPENSSL
/* Define if you want SELinux support. */
#undef WITH_SELINUX
/* include SSH protocol version 1 support */
#undef WITH_SSH1
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
# undef WORDS_BIGENDIAN
# endif
#endif
/* Define if xauth is found in your path */
#undef XAUTH_PATH
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES
/* log for bad login attempts */
#undef _PATH_BTMP
/* Full path of your "passwd" program */
#undef _PATH_PASSWD_PROG
/* Specify location of ssh.pid */
#undef _PATH_SSH_PIDDIR
/* Define if we don't have struct __res_state in resolv.h */
#undef __res_state
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* type to use in place of socklen_t if not defined */
#undef socklen_t
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -54,8 +54,8 @@ AC_SUBST([TEST_SHELL], [sh]) ...@@ -54,8 +54,8 @@ AC_SUBST([TEST_SHELL], [sh])
AC_SUBST(NXCOMPINC) AC_SUBST(NXCOMPINC)
AC_SUBST(NXCOMPLIBS) AC_SUBST(NXCOMPLIBS)
NXCOMPINC="-I$includedir/nx" NXCOMPINC="-I../nxcomp"
NXCOMPLIBS="-lXcomp" NXCOMPLIBS="-L../nxcomp -lXcomp -lstdc++ -lpng -ljpeg -lz"
dnl select manpage formatter dnl select manpage formatter
if test "x$MANDOC" != "x" ; then if test "x$MANDOC" != "x" ; then
...@@ -582,7 +582,7 @@ case "$host" in ...@@ -582,7 +582,7 @@ case "$host" in
*-*-cygwin*) *-*-cygwin*)
check_for_libcrypt_later=1 check_for_libcrypt_later=1
dont_check_for_resolv=1 dont_check_for_resolv=1
LIBS="$LIBS /usr/lib/textmode.o /usr/lib/libminires.a" LIBS="$LIBS /usr/lib/textmode.o"
AC_DEFINE([HAVE_CYGWIN], [1], [Define if you are on Cygwin]) AC_DEFINE([HAVE_CYGWIN], [1], [Define if you are on Cygwin])
AC_DEFINE([USE_PIPES], [1], [Use PIPES instead of a socketpair()]) AC_DEFINE([USE_PIPES], [1], [Use PIPES instead of a socketpair()])
AC_DEFINE([NO_UID_RESTORATION_TEST], [1], AC_DEFINE([NO_UID_RESTORATION_TEST], [1],
...@@ -4182,11 +4182,28 @@ AC_ARG_WITH([selinux], ...@@ -4182,11 +4182,28 @@ AC_ARG_WITH([selinux],
AC_SUBST([SSHLIBS]) AC_SUBST([SSHLIBS])
AC_SUBST([SSHDLIBS]) AC_SUBST([SSHDLIBS])
# Check whether user wants SSPI support
SSPI_MSG="no"
AC_ARG_WITH([sspi],
[ --with-sspi Enable GSSAPI SSPI support],
[ if test "x$withval" != "xno" ; then
AC_DEFINE([SSPI], [1], [Define if you want SSPI support])
AC_DEFINE([GSSAPI], [1],
[Define this if you want GSSAPI support in the version 2 protocol])
AC_DEFINE([GSSAPI_SSPI], [1], [Define if you want GSSAPI SSPI support])
GSSLIBS="-lsecur32 -lws2_32"
SSPI_MSG="yes"
fi ]
)
# Check whether user wants Kerberos 5 support # Check whether user wants Kerberos 5 support
KRB5_MSG="no" KRB5_MSG="no"
AC_ARG_WITH([kerberos5], AC_ARG_WITH([kerberos5],
[ --with-kerberos5=PATH Enable Kerberos 5 support], [ --with-kerberos5=PATH Enable Kerberos 5 support],
[ if test "x$withval" != "xno" ; then [ if test "x$withval" != "xno" ; then
if test "x$SSPI_MSG" = "xyes" ; then
AC_MSG_ERROR([cannot use --with-sspi and --with-kerberos5 together, use one only])
fi
if test "x$withval" = "xyes" ; then if test "x$withval" = "xyes" ; then
KRB5ROOT="/usr/local" KRB5ROOT="/usr/local"
else else
...@@ -5104,6 +5121,7 @@ echo " Manpage format: $MANTYPE" ...@@ -5104,6 +5121,7 @@ echo " Manpage format: $MANTYPE"
echo " PAM support: $PAM_MSG" echo " PAM support: $PAM_MSG"
echo " OSF SIA support: $SIA_MSG" echo " OSF SIA support: $SIA_MSG"
echo " KerberosV support: $KRB5_MSG" echo " KerberosV support: $KRB5_MSG"
echo " SSPI support: $SSPI_MSG"
echo " SELinux support: $SELINUX_MSG" echo " SELinux support: $SELINUX_MSG"
echo " Smartcard support: $SCARD_MSG" echo " Smartcard support: $SCARD_MSG"
echo " S/KEY support: $SKEY_MSG" echo " S/KEY support: $SKEY_MSG"
......
#pragma once
// #ifndef __attribute__
// #define __attribute__(A)
// #endif
#include "../../../log.h"
#include "../../../ssherr.h"
/* Enable the following for verbose logging */
#if (0)
#define debug4 debug2
#define debug5 debug3
#else
#define debug4(a,...)
#define debug5(a,...)
#endif
\ No newline at end of file
/*
* Author: Bryan Berns <berns@uwalumni.com>
*
* 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.
*/
#pragma once
/*
* This file provides the GSSAPI interface to support Kerberos SSPI within
* OpenSSH. This is only a partial definition of the full GSSAPI specification
* since OpenSSH only requires a subset of the overall functionality.
*
* The definitions are derived from information provided in RFC2744. In
* addition, RFC2743 provides additional information on the GSSAPI
* specification and intended operation.
*/
#include <windows.h>
#include <stdint.h>
#define SECURITY_WIN32
#include <security.h>
/*
* Common Structures & Type Definitions
*/
typedef uint32_t OM_uint32;
typedef char *gss_name_struct, *gss_name_t;
typedef struct cred_st *gss_cred_id_t;
typedef CtxtHandle *gss_ctx_id_t;
typedef OM_uint32 gss_qop_t;
typedef OM_uint32 gss_cred_usage_t;
typedef struct gss_buffer_desc_struct
{
size_t length;
void *value;
}
gss_buffer_desc, *gss_buffer_t;
typedef struct gss_OID_desc_struct
{
OM_uint32 length;
void *elements;
}
gss_OID_desc, *gss_OID;
typedef struct gss_OID_set_desc_struct
{
size_t count;
gss_OID elements;
}
gss_OID_set_desc, *gss_OID_set;
typedef struct gss_channel_bindings_struct
{
OM_uint32 initiator_addrtype;
gss_buffer_desc initiator_address;
OM_uint32 acceptor_addrtype;
gss_buffer_desc acceptor_address;
gss_buffer_desc application_data;
}
gss_channel_bindings_desc, *gss_channel_bindings_t;
/*
* Input & Return Flags
*/
/* Credential Usage Indication Options */
#define GSS_C_BOTH 0
#define GSS_C_INITIATE 1
#define GSS_C_ACCEPT 2
/* Context Flag Options */
#define GSS_C_DELEG_FLAG 1
#define GSS_C_MUTUAL_FLAG 2
#define GSS_C_REPLAY_FLAG 4
#define GSS_C_SEQUENCE_FLAG 8
#define GSS_C_CONF_FLAG 16
#define GSS_C_INTEG_FLAG 32
#define GSS_C_ANON_FLAG 64
#define GSS_C_PROT_READY_FLAG 128
#define GSS_C_TRANS_FLAG 256
#define GSS_C_DELEG_POLICY_FLAG 32768
/* Display Status Code Types */
#define GSS_C_GSS_CODE 1
#define GSS_C_MECH_CODE 2
/* Convenience Null Castless Comparison Options */
#define GSS_C_NO_NAME ((gss_name_t) 0)
#define GSS_C_NO_BUFFER ((gss_buffer_t) 0)
#define GSS_C_NO_OID ((gss_OID) 0)
#define GSS_C_NO_OID_SET ((gss_OID_set) 0)
#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0)
#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0)
#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0)
/* Convenience Initializer For Empty Buffer */
#define GSS_C_EMPTY_BUFFER {0, NULL}
/* Default Quality of Protection Code */
#define GSS_C_QOP_DEFAULT 0
/* Infinite Context / Credential Value */
#define GSS_C_INDEFINITE ((OM_uint32) 0xfffffffful)
/*
* Status & Return Code Processing
*/
#define GSS_S_COMPLETE 0
#define GSS_C_CALLING_ERROR_OFFSET 24
#define GSS_C_ROUTINE_ERROR_OFFSET 16
#define GSS_C_SUPPLEMENTARY_OFFSET 0
#define GSS_C_CALLING_ERROR_MASK ((OM_uint32) 0377ul)
#define GSS_C_ROUTINE_ERROR_MASK ((OM_uint32) 0377ul)
#define GSS_CALLING_ERROR(x) ((x) & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET))
#define GSS_ROUTINE_ERROR(x) ((x) & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))
#define GSS_ERROR(x) ((x) & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)))
#define GSS_S_BAD_MECH (((OM_uint32) 1ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_NAME (((OM_uint32) 2ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_NAMETYPE (((OM_uint32) 3ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_BINDINGS (((OM_uint32) 4ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_STATUS (((OM_uint32) 5ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_SIG (((OM_uint32) 6ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_NO_CRED (((OM_uint32) 7ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_NO_CONTEXT (((OM_uint32) 8ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_DEFECTIVE_TOKEN (((OM_uint32) 9ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_DEFECTIVE_CREDENTIAL (((OM_uint32) 10ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_CREDENTIALS_EXPIRED (((OM_uint32) 11ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_CONTEXT_EXPIRED (((OM_uint32) 12ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_FAILURE (((OM_uint32) 13ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_BAD_QOP (((OM_uint32) 14ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_UNAUTHORIZED (((OM_uint32) 15ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_UNAVAILABLE (((OM_uint32) 16ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_DUPLICATE_ELEMENT (((OM_uint32) 17ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_NAME_NOT_MN (((OM_uint32) 18ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_CONTINUE_NEEDED (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 0))
#define GSS_S_DUPLICATE_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 1))
#define GSS_S_OLD_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 2))
#define GSS_S_UNSEQ_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 3))
#define GSS_S_GAP_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 4))
/*
* Function Prototypes
*/
OM_uint32
gss_accept_sec_context(OM_uint32 * minor_status, gss_ctx_id_t * context_handle,
gss_cred_id_t acceptor_cred_handle, gss_buffer_t input_token_buffer,
gss_channel_bindings_t input_chan_bindings, gss_name_t * src_name,
gss_OID * mech_type, gss_buffer_t output_token, OM_uint32 * ret_flags,
OM_uint32 * time_rec, gss_cred_id_t * delegated_cred_handle);
OM_uint32
gss_acquire_cred(OM_uint32 *minor_status, gss_name_t desired_name,
OM_uint32 time_req, gss_OID_set desired_mechs, gss_cred_usage_t cred_usage,
gss_cred_id_t * output_cred_handle, gss_OID_set *actual_mechs,
OM_uint32 *time_rec);
OM_uint32
gss_add_oid_set_member(OM_uint32 * minor_status, gss_OID member_oid,
gss_OID_set * oid_set);
OM_uint32
gss_create_empty_oid_set(OM_uint32 * minor_status, gss_OID_set * oid_set);
OM_uint32
gss_init_sec_context(
OM_uint32 * minor_status, gss_cred_id_t claimant_cred_handle, gss_ctx_id_t * context_handle,
gss_name_t target_name, gss_OID mech_type, OM_uint32 req_flags, OM_uint32 time_req, gss_channel_bindings_t input_chan_bindings,
gss_buffer_t input_token, gss_OID * actual_mech_type, gss_buffer_t output_token, OM_uint32 * ret_flags,
OM_uint32 * time_rec);
OM_uint32
gss_delete_sec_context(OM_uint32 * minor_status, gss_ctx_id_t * context_handle,
gss_buffer_t output_token);
OM_uint32
gss_display_name(OM_uint32 * minor_status, gss_name_t input_name,
gss_buffer_t output_name_buffer, gss_OID * output_name_type);
OM_uint32
gss_display_status(OM_uint32 * minor_status, OM_uint32 status_value,
int status_type, gss_OID mech_type, OM_uint32 * message_context,
gss_buffer_t status_string);
OM_uint32
gss_export_name(OM_uint32 * minor_status, const gss_name_t input_name,
gss_buffer_t exported_name);
OM_uint32
gss_get_mic(OM_uint32 * minor_status, gss_ctx_id_t context_handle,
gss_qop_t qop_req, gss_buffer_t message_buffer,
gss_buffer_t message_token);
OM_uint32
gss_import_name(OM_uint32 * minor_status, gss_buffer_t input_name_buffer,
gss_OID input_name_type, gss_name_t * output_name);
OM_uint32
gss_indicate_mechs(OM_uint32 * minor_status, gss_OID_set * mech_set);
OM_uint32
gss_release_buffer(OM_uint32 * minor_status, gss_buffer_t buffer);
OM_uint32
gss_release_cred(OM_uint32 * minor_status, gss_cred_id_t * cred_handle);
OM_uint32
gss_release_name(OM_uint32 * minor_status, gss_name_t * input_name);
OM_uint32
gss_release_oid_set(OM_uint32 * minor_status, gss_OID_set * set);
OM_uint32
gss_test_oid_set_member(OM_uint32 * minor_status, gss_OID member,
gss_OID_set set, int * present);
OM_uint32
gss_verify_mic(OM_uint32 * minor_status, gss_ctx_id_t context_handle,
gss_buffer_t message_buffer, gss_buffer_t message_token,
gss_qop_t * qop_state);
extern gss_OID GSS_C_NT_HOSTBASED_SERVICE;
\ No newline at end of file
...@@ -212,14 +212,15 @@ choose_dh(int min, int wantbits, int max) ...@@ -212,14 +212,15 @@ choose_dh(int min, int wantbits, int max)
/* diffie-hellman-groupN-sha1 */ /* diffie-hellman-groupN-sha1 */
int int
dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub)
{ {
int i; int i;
int n = BN_num_bits(dh_pub); int n = BN_num_bits(dh_pub);
int bits_set = 0; int bits_set = 0;
BIGNUM *tmp; BIGNUM *tmp;
const BIGNUM *p;
if (dh_pub->neg) { if (BN_is_negative(dh_pub)) {
logit("invalid public DH value: negative"); logit("invalid public DH value: negative");
return 0; return 0;
} }
...@@ -232,7 +233,8 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) ...@@ -232,7 +233,8 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
error("%s: BN_new failed", __func__); error("%s: BN_new failed", __func__);
return 0; return 0;
} }
if (!BN_sub(tmp, dh->p, BN_value_one()) || DH_get0_pqg(dh, &p, NULL, NULL);
if (!BN_sub(tmp, p, BN_value_one()) ||
BN_cmp(dh_pub, tmp) != -1) { /* pub_exp > p-2 */ BN_cmp(dh_pub, tmp) != -1) { /* pub_exp > p-2 */
BN_clear_free(tmp); BN_clear_free(tmp);
logit("invalid public DH value: >= p-1"); logit("invalid public DH value: >= p-1");
...@@ -243,14 +245,14 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) ...@@ -243,14 +245,14 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
for (i = 0; i <= n; i++) for (i = 0; i <= n; i++)
if (BN_is_bit_set(dh_pub, i)) if (BN_is_bit_set(dh_pub, i))
bits_set++; bits_set++;
debug2("bits set: %d/%d", bits_set, BN_num_bits(dh->p)); debug2("bits set: %d/%d", bits_set, BN_num_bits(p));
/* /*
* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial * if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial
*/ */
if (bits_set < 4) { if (bits_set < 4) {
logit("invalid public DH value (%d/%d)", logit("invalid public DH value (%d/%d)",
bits_set, BN_num_bits(dh->p)); bits_set, BN_num_bits(p));
return 0; return 0;
} }
return 1; return 1;
...@@ -260,9 +262,11 @@ int ...@@ -260,9 +262,11 @@ int
dh_gen_key(DH *dh, int need) dh_gen_key(DH *dh, int need)
{ {
int pbits; int pbits;
const BIGNUM *p, *pub_key;
if (need < 0 || dh->p == NULL || DH_get0_pqg(dh, &p, NULL, NULL);
(pbits = BN_num_bits(dh->p)) <= 0 || if (need < 0 || p == NULL ||
(pbits = BN_num_bits(p)) <= 0 ||
need > INT_MAX / 2 || 2 * need > pbits) need > INT_MAX / 2 || 2 * need > pbits)
return SSH_ERR_INVALID_ARGUMENT; return SSH_ERR_INVALID_ARGUMENT;
if (need < 256) if (need < 256)
...@@ -271,10 +275,11 @@ dh_gen_key(DH *dh, int need) ...@@ -271,10 +275,11 @@ dh_gen_key(DH *dh, int need)
* Pollard Rho, Big step/Little Step attacks are O(sqrt(n)), * Pollard Rho, Big step/Little Step attacks are O(sqrt(n)),
* so double requested need here. * so double requested need here.
*/ */
dh->length = MINIMUM(need * 2, pbits - 1); DH_set_length(dh, MINIMUM(need * 2, pbits - 1));
if (DH_generate_key(dh) == 0 || if (DH_generate_key(dh) == 0)
!dh_pub_is_valid(dh, dh->pub_key)) { return SSH_ERR_LIBCRYPTO_ERROR;
BN_clear_free(dh->priv_key); DH_get0_key(dh, &pub_key, NULL);
if (!dh_pub_is_valid(dh, pub_key)) {
return SSH_ERR_LIBCRYPTO_ERROR; return SSH_ERR_LIBCRYPTO_ERROR;
} }
return 0; return 0;
...@@ -284,15 +289,22 @@ DH * ...@@ -284,15 +289,22 @@ DH *
dh_new_group_asc(const char *gen, const char *modulus) dh_new_group_asc(const char *gen, const char *modulus)
{ {
DH *dh; DH *dh;
BIGNUM *p, *g;
if ((dh = DH_new()) == NULL)
return NULL; if ((dh = DH_new()) == NULL ||
if (BN_hex2bn(&dh->p, modulus) == 0 || (p = BN_new()) == NULL ||
BN_hex2bn(&dh->g, gen) == 0) { (g = BN_new()) == NULL)
goto err;
if (BN_hex2bn(&p, modulus) == 0 ||
BN_hex2bn(&g, gen) == 0 ||
DH_set0_pqg(dh, p, NULL, g) == 0)
goto err;
return (dh);
err:
DH_free(dh); DH_free(dh);
BN_free(p);
BN_free(g);
return NULL; return NULL;
}
return (dh);
} }
/* /*
...@@ -307,8 +319,7 @@ dh_new_group(BIGNUM *gen, BIGNUM *modulus) ...@@ -307,8 +319,7 @@ dh_new_group(BIGNUM *gen, BIGNUM *modulus)
if ((dh = DH_new()) == NULL) if ((dh = DH_new()) == NULL)
return NULL; return NULL;
dh->p = modulus; DH_set0_pqg(dh, modulus, NULL, gen);
dh->g = gen;
return (dh); return (dh);
} }
......
...@@ -42,7 +42,7 @@ DH *dh_new_group18(void); ...@@ -42,7 +42,7 @@ DH *dh_new_group18(void);
DH *dh_new_group_fallback(int); DH *dh_new_group_fallback(int);
int dh_gen_key(DH *, int); int dh_gen_key(DH *, int);
int dh_pub_is_valid(DH *, BIGNUM *); int dh_pub_is_valid(const DH *, const BIGNUM *);
u_int dh_estimate(int); u_int dh_estimate(int);
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
struct ssh_digest_ctx { struct ssh_digest_ctx {
int alg; int alg;
EVP_MD_CTX mdctx; EVP_MD_CTX *mdctx;
}; };
struct ssh_digest { struct ssh_digest {
...@@ -107,7 +107,7 @@ ssh_digest_bytes(int alg) ...@@ -107,7 +107,7 @@ ssh_digest_bytes(int alg)
size_t size_t
ssh_digest_blocksize(struct ssh_digest_ctx *ctx) ssh_digest_blocksize(struct ssh_digest_ctx *ctx)
{ {
return EVP_MD_CTX_block_size(&ctx->mdctx); return EVP_MD_CTX_block_size(ctx->mdctx);
} }
struct ssh_digest_ctx * struct ssh_digest_ctx *
...@@ -119,8 +119,9 @@ ssh_digest_start(int alg) ...@@ -119,8 +119,9 @@ ssh_digest_start(int alg)
if (digest == NULL || ((ret = calloc(1, sizeof(*ret))) == NULL)) if (digest == NULL || ((ret = calloc(1, sizeof(*ret))) == NULL))
return NULL; return NULL;
ret->alg = alg; ret->alg = alg;
EVP_MD_CTX_init(&ret->mdctx); ret->mdctx = EVP_MD_CTX_new();
if (EVP_DigestInit_ex(&ret->mdctx, digest->mdfunc(), NULL) != 1) { if (ret->mdctx == NULL ||
EVP_DigestInit_ex(ret->mdctx, digest->mdfunc(), NULL) != 1) {
free(ret); free(ret);
return NULL; return NULL;
} }
...@@ -133,7 +134,7 @@ ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to) ...@@ -133,7 +134,7 @@ ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
if (from->alg != to->alg) if (from->alg != to->alg)
return SSH_ERR_INVALID_ARGUMENT; return SSH_ERR_INVALID_ARGUMENT;
/* we have bcopy-style order while openssl has memcpy-style */ /* we have bcopy-style order while openssl has memcpy-style */
if (!EVP_MD_CTX_copy_ex(&to->mdctx, &from->mdctx)) if (!EVP_MD_CTX_copy_ex(to->mdctx, from->mdctx))
return SSH_ERR_LIBCRYPTO_ERROR; return SSH_ERR_LIBCRYPTO_ERROR;
return 0; return 0;
} }
...@@ -141,7 +142,7 @@ ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to) ...@@ -141,7 +142,7 @@ ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
int int
ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
{ {
if (EVP_DigestUpdate(&ctx->mdctx, m, mlen) != 1) if (EVP_DigestUpdate(ctx->mdctx, m, mlen) != 1)
return SSH_ERR_LIBCRYPTO_ERROR; return SSH_ERR_LIBCRYPTO_ERROR;
return 0; return 0;
} }
...@@ -162,7 +163,7 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen) ...@@ -162,7 +163,7 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
return SSH_ERR_INVALID_ARGUMENT; return SSH_ERR_INVALID_ARGUMENT;
if (dlen < digest->digest_len) /* No truncation allowed */ if (dlen < digest->digest_len) /* No truncation allowed */
return SSH_ERR_INVALID_ARGUMENT; return SSH_ERR_INVALID_ARGUMENT;
if (EVP_DigestFinal_ex(&ctx->mdctx, d, &l) != 1) if (EVP_DigestFinal_ex(ctx->mdctx, d, &l) != 1)
return SSH_ERR_LIBCRYPTO_ERROR; return SSH_ERR_LIBCRYPTO_ERROR;
if (l != digest->digest_len) /* sanity */ if (l != digest->digest_len) /* sanity */
return SSH_ERR_INTERNAL_ERROR; return SSH_ERR_INTERNAL_ERROR;
...@@ -173,7 +174,7 @@ void ...@@ -173,7 +174,7 @@ void
ssh_digest_free(struct ssh_digest_ctx *ctx) ssh_digest_free(struct ssh_digest_ctx *ctx)
{ {
if (ctx != NULL) { if (ctx != NULL) {
EVP_MD_CTX_cleanup(&ctx->mdctx); EVP_MD_CTX_free(ctx->mdctx);
explicit_bzero(ctx, sizeof(*ctx)); explicit_bzero(ctx, sizeof(*ctx));
free(ctx); free(ctx);
} }
......
/*
* Author: Bryan Berns <berns@uwalumni.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#ifdef GSSAPI
#ifdef SSPI
#define WIN32
#define OPENSSL_SYS_WIN32
#define _countof(array) (sizeof(array) / sizeof(array[0]))
#define _strdup strdup
#define _stricmp strcasecmp
#define _wcsnicmp wcsncasecmp
#include <windows.h>
#include <winsock2.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <wchar.h>
#include <time.h>
#include <pwd.h>
#include "contrib/win32/win32compat/debug.h"
#include "contrib/win32/win32compat/inc/gssapi.h"
/*
* This file provides the GSSAPI interface to support Kerberos SSPI within
* OpenSSH. This is only a partial definition of the full GSSAPI specification
* since OpenSSH only requires a subset of the overall functionality.
*
* The function definitions as well as the accompanying comments are derived
* from information provided in RFC2744. In addition, RFC2743 provides
* additional information on the GSSAPI specification and intended operation.
*/
/*
* Include the definitions necessary to implement some of the interface
* structure that are required for gss-serv.c to perform Kerberos operations.
*/
#include "buffer.h"
#undef HAVE_GSSAPI_H
#undef HAVE_GSSAPI_GSSAPI_H
#undef HAVE_GSSAPI_GENERIC_H
#undef HAVE_GSSAPI_GSSAPI_GENERIC_H
#include "ssh-gss.h"
/*on error returns NULL and sets errno*/
static wchar_t *
utf8_to_utf16(const char *utf8)
{
int needed = 0;
wchar_t* utf16 = NULL;
if ((needed = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0)) == 0 ||
(utf16 = malloc(needed * sizeof(wchar_t))) == NULL ||
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, needed) == 0) {
errno = ENOMEM;
return NULL;
}
return utf16;
}
static char *
utf16_to_utf8(const wchar_t* utf16)
{
int needed = 0;
char* utf8 = NULL;
if ((needed = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, NULL, NULL)) == 0 ||
(utf8 = malloc(needed)) == NULL ||
WideCharToMultiByte(CP_UTF8, 0, utf16, -1, utf8, needed, NULL, NULL) == 0)
return NULL;
return utf8;
}
/*
* This will be initialized to a function table that contains pointers to
* all standard security functions. The reason for using this instead of
* relying on the standard imports is because the OneCore libraries do
* not expose all the functions we need.
*/
PSecurityFunctionTableW SecFunctions = NULL;
/*
* GSS_C_NT_HOSTBASED_SERVICE is a oid value that is used to negotiate a
* a Kerberos transaction using an SPN in the format host@user@realm format.
*/
#define GSS_C_NT_HOSTBASED_SERVICE_STR "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"
gss_OID GSS_C_NT_HOSTBASED_SERVICE = &(gss_OID_desc)
{
sizeof(GSS_C_NT_HOSTBASED_SERVICE_STR) - 1,
(void *) GSS_C_NT_HOSTBASED_SERVICE_STR
};
/*
* This handle is used to relay the handle for the user to functions that
* ultimately call CreateProcessAsUser to spawn the user shell.
*/
HANDLE sspi_auth_user = 0;
struct cred_st {
int isToken;
union {
HANDLE token;
CredHandle credHandle;
};
};
/*
* This is called before each gssapi implementation function to ensure the
* environment is initialized properly. Any additional implementation setup
* should be added to this function.
*/
static int
ssh_gss_sspi_init(OM_uint32 * minor_status)
{
/* minor status never used - reset to zero*/
*minor_status = 0;
/* already initialized; return */
if (SecFunctions != NULL)
return 1;
/* get a pointer to a function table containing all the function pointers */
if ((SecFunctions = InitSecurityInterfaceW()) == NULL) {
/* failure */
debug("failed to acquire function table for sspi support.");
return 0;
}
/* success */
return 1;
}
/*
* Allows an application to determine which underlying security mechanisms are
* available.
*/
OM_uint32
gss_indicate_mechs(OM_uint32 * minor_status, gss_OID_set *mech_set)
{
if (ssh_gss_sspi_init(minor_status) == 0)
return GSS_S_FAILURE;
/* create an list that contains the one oid that we support */
if (gss_create_empty_oid_set(minor_status, mech_set) != GSS_S_COMPLETE)
return GSS_S_FAILURE;
if (gss_add_oid_set_member(minor_status, GSS_C_NT_HOSTBASED_SERVICE, mech_set) != GSS_S_COMPLETE) {
gss_release_oid_set(minor_status, mech_set);
return GSS_S_FAILURE;
}
return GSS_S_COMPLETE;
}
/*
* Create an object-identifier set containing no object identifiers, to which
* members may be subsequently added using the gss_add_oid_set_member() routine.
* These routines are intended to be used to construct sets of mechanism object
* identifiers, for input to gss_acquire_cred.
*/
OM_uint32
gss_create_empty_oid_set(OM_uint32 * minor_status, gss_OID_set * oid_set)
{
if (ssh_gss_sspi_init(minor_status) == 0)
return GSS_S_FAILURE;
/* allocate / initialize space for this new oid set */
if (((*oid_set) = calloc(1, sizeof(gss_OID_set_desc))) == NULL)
return GSS_S_FAILURE;
return GSS_S_COMPLETE;
}
/*
* Free storage associated with a GSSAPI-generated gss_OID_set object. The set
* parameter must refer to an OID-set that was returned from a GSS-API routine.
* gss_release_oid_set() will free the storage associated with each individual
* member OID, the OID set's elements array, and the gss_OID_set_desc.
*/
OM_uint32
gss_release_oid_set(OM_uint32 * minor_status, gss_OID_set * set)
{
if (ssh_gss_sspi_init(minor_status) == 0)
return GSS_S_FAILURE;
/* free all individual oid strings */
for (size_t oid_num = 0; oid_num < (*set)->count; oid_num++)
free((*set)->elements[oid_num].elements);
/* free overall oid set */
free((*set)->elements);
free(*set);
return GSS_S_COMPLETE;
}
/*
* Add an Object Identifier to an Object Identifier set. This routine is
* intended for use in conjunction with gss_create_empty_oid_set when
* constructing a set of mechanism OIDs for input to gss_acquire_cred. The
* oid_set parameter must refer to an OID-set that was created by GSS-API (e.g.
* a set returned by gss_create_empty_oid_set()). GSS-API creates a copy of the
* member_oid and inserts this copy into the set, expanding the storage
* allocated to the OID-set's elements array if necessary. The routine may add
* the new member OID anywhere within the elements array, and implementations
* should verify that the new member_oid is not already contained within the
* elements array; if the member_oid is already present, the oid_set should
* remain unchanged.
*/
OM_uint32
gss_add_oid_set_member(OM_uint32 * minor_status, gss_OID member_oid, gss_OID_set * oid_set)
{
OM_uint32 ret = GSS_S_FAILURE;
void * member_oid_elements = NULL;
if (ssh_gss_sspi_init(minor_status) == 0)
return GSS_S_FAILURE;
/* create our own copy of the oid entry itself to add to the set */
if ((member_oid_elements = malloc(member_oid->length)) == NULL)
goto cleanup;
memcpy(member_oid_elements, member_oid->elements, member_oid->length);
/* reallocate the new elements structure based on the increased size */
const size_t current_count = (*oid_set)->count;
(*oid_set)->elements = realloc((*oid_set)->elements, (current_count + 1) * sizeof(gss_OID_desc));
if ((*oid_set)->elements == NULL)
goto cleanup;
/* append the new oid to the end of the recently increased list */
(*oid_set)->elements[current_count].elements = member_oid_elements;
(*oid_set)->elements[current_count].length = member_oid->length;
(*oid_set)->count++;
member_oid_elements = NULL;
ret = GSS_S_COMPLETE;
cleanup:
if (member_oid_elements)
free(member_oid_elements);
return ret;
}
/*
* Interrogate an Object Identifier set to determine whether a specified Object
* Identifier is a member. This routine is intended to be used with OID sets
* returned by gss_indicate_mechs(), gss_acquire_cred(), and gss_inquire_cred(),
* but will also work with user-generated sets.
*/
OM_uint32
gss_test_oid_set_member(OM_uint32 * minor_status, gss_OID member,
gss_OID_set set, int * present)
{
if (ssh_gss_sspi_init(minor_status) == 0)
return GSS_S_FAILURE;
/* loop through each oid in the passed set */
for (size_t oid_num = 0; oid_num < set->count; oid_num++) {
/* do not bother doing memory comparison if sizes do not match */
if (set->elements[oid_num].length != member->length)
continue;
/* compare the binary storage of the test oid to the one in our list */
if (memcmp(set->elements[oid_num].elements, member->elements, member->length) == 0) {
/* match found */
*present = TRUE;
return GSS_S_COMPLETE;
}
}
/* no match found in the list */
*present = FALSE;
return GSS_S_COMPLETE;
}
/*
* Convert a contiguous string name to internal form. In general, the internal
* name returned (via the <output_name> parameter) will not be an MN; the
* exception to this is if the <input_name_type> indicates that the contiguous
* string provided via the <input_name_buffer> parameter is of type
* GSS_C_NT_EXPORT_NAME, in which case the returned internal name will be an MN
* for the mechanism that exported the name.
*/
OM_uint32
gss_import_name(OM_uint32 * minor_status, gss_buffer_t input_name_buffer,
gss_OID input_name_type, gss_name_t * output_name)
{
if (ssh_gss_sspi_init(minor_status) == 0)
return GSS_S_FAILURE;
/* make sure we support the passed type */
if (input_name_type->length != GSS_C_NT_HOSTBASED_SERVICE->length ||
memcmp(input_name_type->elements, GSS_C_NT_HOSTBASED_SERVICE->elements, input_name_type->length) != 0)
return GSS_S_BAD_NAMETYPE;
/* there is nothing special we have to do for this type so just duplicate
the */
(*output_name) = _strdup(input_name_buffer->value);
if (output_name == NULL)
return GSS_S_FAILURE;
return GSS_S_COMPLETE;
}
/*
* Free GSSAPI-allocated storage associated with an internal-form name.
* Implementations are encouraged to set the name to GSS_C_NO_NAME on successful
* completion of this call.
*/
OM_uint32
gss_release_name(OM_uint32 * minor_status, gss_name_t * input_name)
{
if (ssh_gss_sspi_init(minor_status) == 0)
return GSS_S_FAILURE;
/* validate input */
if (input_name == NULL || *input_name == NULL)
return GSS_S_BAD_NAME;
/* deallocate memory associated with the name */
free(*input_name);
*input_name = GSS_C_NO_NAME;
return GSS_S_COMPLETE;
}
/*
* To produce a canonical contiguous string representation of a mechanism name
* (MN), suitable for direct comparison (e.g. with memcmp) for use in
* authorization functions (e.g. matching entries in an access-control list).
* The <input_name> parameter must specify a or by gss_canonicalize_name).
*/
OM_uint32
gss_export_name(OM_uint32 * minor_status, const gss_name_t input_name,
gss_buffer_t exported_name)
{
if (ssh_gss_sspi_init(minor_status) == 0)
return GSS_S_FAILURE;
/* convenience pointer to shorten the void */
const gss_OID_desc* const ntoid = GSS_C_NT_HOSTBASED_SERVICE;
/* make sure we support the passed type */
if (strstr(input_name, "host@") == input_name)
return GSS_S_BAD_NAMETYPE;
/* get the lengths of all the parts of the string */
/* note: assumes short format for encoding oid length (i.e. less than 128)
*/
const uint16_t token_id = 0x0401;
const uint8_t oid_tag = 0x06;
const uint8_t oid_len = (uint8_t) ntoid->length;
const uint16_t oid_outer_len = sizeof(oid_tag) + sizeof(oid_len) + oid_len;
const uint32_t name_len = (uint16_t) strlen(input_name);
/* allocate space for the exported name */
exported_name->length = sizeof(token_id) + sizeof(oid_outer_len) + oid_outer_len + sizeof(name_len) + name_len;
exported_name->value = malloc(exported_name->length);
if (exported_name->value == NULL)
return GSS_S_FAILURE;
/* get big-endian values so we can just do a direct memcpy from the values
*/
const uint16_t token_id_be = htons(token_id);
const uint16_t oid_outer_len_be = htons(oid_outer_len);
const uint32_t name_len_be = htonl(name_len);
/* construct the encoded value */
uint8_t * output = exported_name->value;
memcpy(output, &token_id_be, sizeof(token_id_be)); output += sizeof(token_id_be);
memcpy(output, &oid_outer_len_be, sizeof(oid_outer_len_be)); output += sizeof(oid_outer_len_be);
memcpy(output, &oid_tag, sizeof(oid_tag)); output += sizeof(oid_tag);
memcpy(output, &oid_len, sizeof(oid_len)); output += sizeof(oid_len);
memcpy(output, ntoid->elements, ntoid->length); output += ntoid->length;
memcpy(output, &name_len_be, sizeof(name_len_be)); output += sizeof(name_len_be);
memcpy(output, input_name, name_len);
return GSS_S_COMPLETE;
}
/*
* Free storage associated with a buffer. The storage must have been allocated
* by a GSS-API routine. In addition to freeing the associated storage, the
* routine will zero the length field in the descriptor to which the buffer
* parameter refers, and implementations are encouraged to additionally set the
* pointer field in the descriptor to NULL. Any buffer object returned by a
* GSS-API routine may be passed to gss_release_buffer (even if there is no
* storage associated with the buffer).
*/
OM_uint32
gss_release_buffer(OM_uint32 * minor_status, gss_buffer_t buffer)
{
if (ssh_gss_sspi_init(minor_status) == 0)
return GSS_S_FAILURE;
/* deallocate the buffer associated with the buffer */
free(buffer->value);
buffer->length = 0;
buffer->value = NULL;
return GSS_S_COMPLETE;
}
/*
* Allows an application to acquire a handle for a pre-existing credential by
* name. GSS-API implementations must impose a local access-control policy on
* callers of this routine to prevent unauthorized callers from acquiring
* credentials to which they are not entitled. This routine is not intended to
* provide a "login to the network" function, as such a function would involve
* the creation of new credentials rather than merely acquiring a handle to
* existing credentials. Such functions, if required, should be defined in
* implementation-specific extensions to the API.
*/
OM_uint32
gss_acquire_cred(OM_uint32 *minor_status, gss_name_t desired_name,
OM_uint32 time_req, gss_OID_set desired_mechs, gss_cred_usage_t cred_usage,
gss_cred_id_t * output_cred_handle, gss_OID_set *actual_mechs, OM_uint32 *time_rec)
{
OM_uint32 ret = GSS_S_FAILURE;
SYSTEMTIME current_time_system;
wchar_t * desired_name_utf16 = NULL;
CredHandle cred_handle, *p_cred_handle = NULL;
if (output_cred_handle != NULL)
*output_cred_handle = NULL;
if (ssh_gss_sspi_init(minor_status) == 0)
goto done;
/* get the current time so we can determine expiration if requested */
GetSystemTime(&current_time_system);
/* translate credential usage parameters */
ULONG cred_usage_local = 0;
if (cred_usage == GSS_C_ACCEPT) cred_usage_local = SECPKG_CRED_INBOUND;
else if (cred_usage == GSS_C_INITIATE) cred_usage_local = SECPKG_CRED_OUTBOUND;
else if (cred_usage == GSS_C_BOTH) cred_usage_local = SECPKG_CRED_BOTH;
/* convert input name to unicode so we can process usernames with special characters */
if ((desired_name_utf16 = utf8_to_utf16(desired_name)) == NULL)
goto done;
/* acquire a handle to existing credentials -- in many cases the name will
* be null in which case the credentials of the current user are used */
TimeStamp expiry;
SECURITY_STATUS status = SecFunctions->AcquireCredentialsHandleW(desired_name_utf16, MICROSOFT_KERBEROS_NAME_W, cred_usage_local,
NULL, NULL, NULL, NULL, &cred_handle, &expiry);
/* fail immediately if errors occurred */
if (status != SEC_E_OK)
goto done;
p_cred_handle = &cred_handle;
/* copy credential data out of local buffer */
if (output_cred_handle != NULL) {
if ((*output_cred_handle = malloc(sizeof(struct cred_st))) == NULL)
goto done;
(*output_cred_handle)->isToken = 0;
(*output_cred_handle)->credHandle = cred_handle;
}
/* determine expiration if requested */
if (time_rec != NULL) {
FILETIME current_time;
if (SystemTimeToFileTime(&current_time_system, &current_time) != 0)
*time_rec = (OM_uint32)(expiry.QuadPart - ((PLARGE_INTEGER)&current_time)->QuadPart) / 10000;
else
error("SystemTimeToFileTime failed with %lu", GetLastError());
}
/* set actual supported mechs if requested */
if (actual_mechs != NULL && gss_indicate_mechs(minor_status, actual_mechs) != GSS_S_COMPLETE)
goto done;
ret = GSS_S_COMPLETE;
done:
if (desired_name_utf16)
free(desired_name_utf16);
if (ret != GSS_S_COMPLETE) {
if (p_cred_handle)
SecFunctions->FreeCredentialsHandle(p_cred_handle);
if (output_cred_handle && *output_cred_handle) {
free(*output_cred_handle);
*output_cred_handle = NULL;
}
}
return ret;
}
/*
* Initiates the establishment of a security context between the application and
* a remote peer. Initially, the input_token parameter should be specified
* either as GSS_C_NO_BUFFER, or as a pointer to a gss_buffer_desc object whose
* length field contains the value zero. The routine may return a output_token
* which should be transferred to the peer application, where the peer
* application will present it to gss_accept_sec_context.
*/
OM_uint32
gss_init_sec_context(
OM_uint32 * minor_status, gss_cred_id_t claimant_cred_handle, gss_ctx_id_t * context_handle,
gss_name_t target_name, gss_OID mech_type, OM_uint32 req_flags, OM_uint32 time_req, gss_channel_bindings_t input_chan_bindings,
gss_buffer_t input_token, gss_OID * actual_mech_type, gss_buffer_t output_token, OM_uint32 * ret_flags,
OM_uint32 * time_rec)
{
OM_uint32 ret = GSS_S_FAILURE;
wchar_t * target_name_utf16 = NULL;
gss_ctx_id_t p_ctx_h = NULL;
output_token->value = NULL;
if (ssh_gss_sspi_init(minor_status) == 0)
goto done;
/* make sure we support the passed type */
if (mech_type->length != GSS_C_NT_HOSTBASED_SERVICE->length ||
memcmp(mech_type->elements, GSS_C_NT_HOSTBASED_SERVICE->elements, mech_type->length) != 0) {
ret = GSS_S_BAD_NAMETYPE;
goto done;
}
unsigned long sspi_req_flags = ISC_REQ_ALLOCATE_MEMORY;
if (req_flags & GSS_C_MUTUAL_FLAG)
sspi_req_flags |= ISC_REQ_MUTUAL_AUTH;
if (req_flags & GSS_C_CONF_FLAG)
sspi_req_flags |= ISC_REQ_CONFIDENTIALITY;
if (req_flags & GSS_C_REPLAY_FLAG)
sspi_req_flags |= ISC_REQ_REPLAY_DETECT;
if (req_flags & GSS_C_DELEG_FLAG)
sspi_req_flags |= ISC_REQ_DELEGATE;
if (req_flags & GSS_C_INTEG_FLAG)
sspi_req_flags |= ISC_REQ_INTEGRITY;
if (req_flags & GSS_C_SEQUENCE_FLAG)
sspi_req_flags |= ISC_REQ_SEQUENCE_DETECT;
/* determine if this is the first call (no input buffer available) */
gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER;
const int no_input_buffer = (input_token == GSS_C_NO_BUFFER) || memcmp(input_token, &empty_buffer, sizeof(gss_buffer_desc)) == 0;
/* setup input buffer */
SecBuffer input_buffer_token = { (no_input_buffer) ? 0 : (unsigned long) input_token->length, SECBUFFER_TOKEN, (no_input_buffer) ? NULL : input_token->value };
SecBufferDesc input_buffer = { SECBUFFER_VERSION, 1, &input_buffer_token };
/* setup output buffer - will be dynamically allocated by function */
SecBuffer output_buffer_token = { 0, SECBUFFER_TOKEN, NULL };
SecBufferDesc output_buffer = { SECBUFFER_VERSION, 1, &output_buffer_token };
/* get the current time so we can determine expiration if requested */
SYSTEMTIME current_time_system;
GetSystemTime(&current_time_system);
/* acquire default cred handler if none specified */
CredHandle *pCredHandle = NULL;
if (claimant_cred_handle != NULL)
pCredHandle = &(claimant_cred_handle->credHandle);
if (pCredHandle == NULL) {
static CredHandle cred_handle = { 0, 0 };
pCredHandle = &cred_handle;
if (cred_handle.dwLower == 0 && cred_handle.dwUpper == 0) {
TimeStamp expiry_cred;
if (SecFunctions->AcquireCredentialsHandleW(NULL, MICROSOFT_KERBEROS_NAME_W, SECPKG_CRED_OUTBOUND,
NULL, NULL, NULL, NULL, &cred_handle, &expiry_cred) != SEC_E_OK)
goto done;
}
}
/* condition the string for windows */
if ((target_name_utf16 = utf8_to_utf16(target_name)) == NULL)
goto done;
if (wcsncmp(target_name_utf16, L"host@", wcslen(L"host@")) == 0)
*wcschr(target_name_utf16, L'@') = L'/';
TimeStamp expiry;
LONG sspi_ret_flags = 0;
CtxtHandle out_context;
const SECURITY_STATUS status = SecFunctions->InitializeSecurityContextW(pCredHandle,
(*context_handle == GSS_C_NO_CONTEXT) ? NULL : *context_handle,
target_name_utf16, sspi_req_flags, 0, SECURITY_NATIVE_DREP, (no_input_buffer) ? NULL : &input_buffer,
0, (*context_handle != NULL) ? NULL : &out_context, &output_buffer, &sspi_ret_flags, (time_rec == NULL) ? NULL : &expiry);
/* check if error occurred */
if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED)
goto done;
/* copy output token to output buffer */
output_token->length = output_buffer_token.cbBuffer;
if ((output_token->value = malloc(output_token->length)) == NULL)
goto done;
memcpy(output_token->value, output_buffer_token.pvBuffer, output_token->length);
SecFunctions->FreeContextBuffer(output_buffer_token.pvBuffer);
/* if requested, translate returned flags that are actually available */
if (ret_flags != NULL) {
*ret_flags = 0;
if (sspi_ret_flags & ISC_RET_MUTUAL_AUTH)
*ret_flags |= GSS_C_MUTUAL_FLAG;
if (sspi_ret_flags & ISC_RET_CONFIDENTIALITY)
*ret_flags |= GSS_C_CONF_FLAG;
if (sspi_ret_flags & ISC_RET_REPLAY_DETECT)
*ret_flags |= GSS_C_REPLAY_FLAG;
if (sspi_ret_flags & ISC_RET_DELEGATE)
*ret_flags |= GSS_C_DELEG_FLAG;
if (sspi_ret_flags & ISC_RET_INTEGRITY)
*ret_flags |= GSS_C_INTEG_FLAG;
if (sspi_ret_flags & ISC_RET_SEQUENCE_DETECT)
*ret_flags |= GSS_C_SEQUENCE_FLAG;
}
/* report if delegation was requested by not fulfilled */
if ((sspi_req_flags & ISC_REQ_DELEGATE) != 0 && (sspi_ret_flags & ISC_RET_DELEGATE) == 0)
debug("sspi delegation was requested but not fulfilled");
/* if requested, translate the expiration time to number of second */
if (time_rec != NULL) {
FILETIME current_time;
if (SystemTimeToFileTime(&current_time_system, &current_time) != 0)
*time_rec = (OM_uint32)(expiry.QuadPart - ((PLARGE_INTEGER)&current_time)->QuadPart) / 10000;
else
error("SystemTimeToFileTime failed with %lu", GetLastError());
}
/* if requested, return the supported mechanism oid */
if (actual_mech_type != NULL)
*actual_mech_type = GSS_C_NT_HOSTBASED_SERVICE;
/* copy the credential context structure to the caller */
if (*context_handle == GSS_C_NO_CONTEXT) {
if ((p_ctx_h = malloc(sizeof(out_context))) == NULL)
goto done;
*context_handle = p_ctx_h;
memcpy(*context_handle, &out_context, sizeof(out_context));
}
ret = (status == SEC_I_CONTINUE_NEEDED) ? GSS_S_CONTINUE_NEEDED : GSS_S_COMPLETE;
done:
if (target_name_utf16)
free(target_name_utf16);
if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
if (output_token->value) {
free(output_token->value);
output_token->value = NULL;
}
if (p_ctx_h)
free(p_ctx_h);
}
return ret;
}
/*
* Informs GSS-API that the specified credential handle is no longer required by
* the application, and frees associated resources. Implementations are
* encouraged to set the cred_handle to GSS_C_NO_CREDENTIAL on successful
* completion of this call.
*/
OM_uint32
gss_release_cred(OM_uint32 * minor_status, gss_cred_id_t * cred_handle)
{
if (ssh_gss_sspi_init(minor_status) == 0)
return GSS_S_FAILURE;
if (*cred_handle != GSS_C_NO_CREDENTIAL) {
if ((*cred_handle)->isToken) {
CloseHandle((*cred_handle)->token);
if ((*cred_handle)->token == sspi_auth_user)
sspi_auth_user = 0;
}
else
SecFunctions->FreeCredentialsHandle(&(*cred_handle)->credHandle);
free(*cred_handle);
*cred_handle = GSS_C_NO_CREDENTIAL;
}
return GSS_S_COMPLETE;
}
/*
* Delete a security context. gss_delete_sec_context will delete the local data
* structures associated with the specified security context, and may generate
* an output_token, which when passed to the peer gss_process_context_token will
* instruct it to do likewise. If no token is required by the mechanism, the
* GSS-API should set the length field of the output_token (if provided) to
* zero. No further security services may be obtained using the context
* specified by context_handle.
*/
OM_uint32
gss_delete_sec_context(OM_uint32 * minor_status, gss_ctx_id_t * context_handle,
gss_buffer_t output_token)
{
if (ssh_gss_sspi_init(minor_status) == 0)
return GSS_S_FAILURE;
/* input sanity checks */
if (context_handle == NULL)
return GSS_S_NO_CONTEXT;
if (output_token != GSS_C_NO_BUFFER) {
free(output_token->value);
output_token->value = NULL;
output_token->length = 0;
}
/* cleanup security context */
SecFunctions->DeleteSecurityContext(*context_handle);
free(*context_handle);
*context_handle = GSS_C_NO_CONTEXT;
return GSS_S_COMPLETE;
}
/*
* Verifies that a cryptographic MIC, contained in the token parameter, fits the
* supplied message. The qop_state parameter allows a message recipient to
* determine the strength of protection that was applied to the message.
*/
OM_uint32
gss_verify_mic(OM_uint32 * minor_status, gss_ctx_id_t context_handle,
gss_buffer_t message_buffer, gss_buffer_t message_token, gss_qop_t * qop_state)
{
if (ssh_gss_sspi_init(minor_status) == 0)
return GSS_S_FAILURE;
/* translate the message and token to a security buffer so we can verify it */
SecBuffer verify_buffer_set[] = {
{ (unsigned long) message_buffer->length, SECBUFFER_DATA, message_buffer->value },
{ (unsigned long) message_token->length, SECBUFFER_TOKEN, message_token->value } };
SecBufferDesc verify_buffer = { SECBUFFER_VERSION, _countof(verify_buffer_set), verify_buffer_set };
/* verify message and signature */
ULONG qop;
const SECURITY_STATUS status = SecFunctions->VerifySignature(context_handle, &verify_buffer, 0, &qop);
/* translate error codes */
OM_uint32 return_code = GSS_S_COMPLETE;
if (status != SEC_E_OK) {
/* translate specific error */
if (status == SEC_E_MESSAGE_ALTERED) return_code = GSS_S_BAD_SIG;
else if (status == SEC_E_OUT_OF_SEQUENCE) return_code = GSS_S_UNSEQ_TOKEN;
else if (status == SEC_E_INVALID_TOKEN) return_code = GSS_S_DEFECTIVE_TOKEN;
else if (status == SEC_E_CONTEXT_EXPIRED) return_code = GSS_S_CONTEXT_EXPIRED;
else if (status == SEC_E_QOP_NOT_SUPPORTED) return_code = GSS_S_BAD_QOP;
else return_code = GSS_S_FAILURE;
}
if (qop_state != NULL)
*qop_state = (OM_uint32) GSS_C_QOP_DEFAULT;
return return_code;
}
/*
* Generates a cryptographic MIC for the supplied message, and places the MIC in
* a token for transfer to the peer application. The qop_req parameter allows a
* choice between several cryptographic algorithms, if supported by the chosen
* mechanism.
*/
OM_uint32
gss_get_mic(OM_uint32 * minor_status, gss_ctx_id_t context_handle,
gss_qop_t qop_req, gss_buffer_t message_buffer, gss_buffer_t message_token)
{
OM_uint32 ret = GSS_S_FAILURE;
message_token->value = NULL;
if (ssh_gss_sspi_init(minor_status) == 0)
goto done;
/* determine the max possible signature and allocate memory to support it */
SecPkgContext_Sizes sizes;
if (SecFunctions->QueryContextAttributesW(context_handle, SECPKG_ATTR_SIZES, &sizes) != SEC_E_OK)
goto done;
if ((message_token->value = malloc(sizes.cbMaxSignature)) == NULL)
goto done;
message_token->length = sizes.cbMaxSignature;
/* translate the message and token to a security buffer so we can sign it */
SecBuffer sign_buffer_set[] = {
{ (unsigned long) message_buffer->length, SECBUFFER_DATA, message_buffer->value },
{ (unsigned long) message_token->length, SECBUFFER_TOKEN, message_token->value } };
SecBufferDesc sign_buffer = { SECBUFFER_VERSION, _countof(sign_buffer_set), sign_buffer_set };
/* attempt to sign the data */
ULONG qop = 0;
const SECURITY_STATUS status = SecFunctions->MakeSignature(context_handle, qop, &sign_buffer, 0);
/* translate error codes */
if (status != SEC_E_OK) {
if (status == SEC_E_CONTEXT_EXPIRED)
ret = GSS_S_CONTEXT_EXPIRED;
else if (status == SEC_E_QOP_NOT_SUPPORTED)
ret = GSS_S_BAD_QOP;
goto done;
}
ret = GSS_S_COMPLETE;
done:
if (ret != GSS_S_COMPLETE) {
if (message_token->value) {
free(message_token->value);
message_token->value = NULL;
}
}
return ret;
}
/*
* Allows a remotely initiated security context between the application and a
* remote peer to be established. The routine may return a output_token which
* should be transferred to the peer application, where the peer application
* will present it to gss_init_sec_context. If no token need be sent,
* gss_accept_sec_context will indicate this by setting the length field of the
* output_token argument to zero. To complete the context establishment, one or
* more reply tokens may be required from the peer application; if so,
* gss_accept_sec_context will return a status flag of GSS_S_CONTINUE_NEEDED, in
* which case it should be called again when the reply token is received from
* the peer application, passing the token to gss_accept_sec_context via the
* input_token parameters.
*/
OM_uint32
gss_accept_sec_context(OM_uint32 * minor_status, gss_ctx_id_t * context_handle,
gss_cred_id_t acceptor_cred_handle, gss_buffer_t input_token_buffer, gss_channel_bindings_t input_chan_bindings,
gss_name_t * src_name, gss_OID * mech_type, gss_buffer_t output_token,
OM_uint32 * ret_flags, OM_uint32 * time_rec, gss_cred_id_t * delegated_cred_handle)
{
OM_uint32 ret = GSS_S_FAILURE;
gss_ctx_id_t p_ctx_h = NULL;
*src_name = NULL;
if (delegated_cred_handle != NULL)
*delegated_cred_handle = NULL;
if (ssh_gss_sspi_init(minor_status) == 0)
goto done;
/* setup input buffer */
SecBuffer input_buffer_token = { (unsigned long) input_token_buffer->length,
SECBUFFER_TOKEN | SECBUFFER_READONLY, input_token_buffer->value };
SecBufferDesc input_buffer = { SECBUFFER_VERSION, 1, &input_buffer_token };
/* setup output buffer - will be dynamically allocated by function */
SecBuffer output_buffer_token = { 0, SECBUFFER_TOKEN, NULL };
SecBufferDesc output_buffer = { SECBUFFER_VERSION, 1, &output_buffer_token };
/* get the current time so we can determine expiration if requested */
SYSTEMTIME current_time_system;
GetSystemTime(&current_time_system);
TimeStamp expiry;
CtxtHandle sspi_context_handle;
ULONG sspi_ret_flags = 0;
ULONG sspi_req_flags = ASC_REQ_CONFIDENTIALITY | ASC_REQ_MUTUAL_AUTH | ASC_REQ_INTEGRITY |
ASC_REQ_DELEGATE | ASC_REQ_SEQUENCE_DETECT | ASC_REQ_ALLOCATE_MEMORY;
/* call sspi accept security context function */
const SECURITY_STATUS status = SecFunctions->AcceptSecurityContext(&acceptor_cred_handle->credHandle,
(*context_handle == GSS_C_NO_CONTEXT) ? NULL : *context_handle, &input_buffer,
sspi_req_flags, SECURITY_NATIVE_DREP,
(*context_handle == GSS_C_NO_CONTEXT) ? &sspi_context_handle : *context_handle,
&output_buffer, &sspi_ret_flags, &expiry);
/* translate error codes */
if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
if (status == SEC_E_INVALID_TOKEN)
ret = GSS_S_DEFECTIVE_TOKEN;
else if (status == SEC_E_INVALID_HANDLE)
ret = GSS_S_NO_CONTEXT;
goto done;
}
/* only do checks on the finalized context (no continue needed) */
if (status == SEC_E_OK) {
/* validate accepted context is actually a host service ticket */
SecPkgContext_NativeNamesW target;
if (SecFunctions->QueryContextAttributesW((*context_handle == GSS_C_NO_CONTEXT) ? &sspi_context_handle : *context_handle,
SECPKG_ATTR_NATIVE_NAMES, &target) != SEC_E_OK)
goto done;
const int valid_spn = _wcsnicmp(target.sServerName, L"host/", wcslen(L"host/")) == 0;
FreeContextBuffer(target.sServerName);
FreeContextBuffer(target.sClientName);
if (valid_spn == 0) {
debug("client passed an invalid principal name");
ret = GSS_S_FAILURE;
goto done;
}
}
/* copy the context handler to the caller */
if (*context_handle == GSS_C_NO_CONTEXT) {
if ((p_ctx_h = malloc(sizeof(CtxtHandle))) == NULL)
goto done;
*context_handle = p_ctx_h;
memcpy(*context_handle, &sspi_context_handle, sizeof(CtxtHandle));
}
/* if requested, translate returned flags that are actually available */
if (ret_flags != NULL) {
*ret_flags = 0;
if (sspi_ret_flags & ASC_RET_MUTUAL_AUTH)
*ret_flags |= GSS_C_MUTUAL_FLAG;
if (sspi_ret_flags & ASC_RET_CONFIDENTIALITY)
*ret_flags |= GSS_C_CONF_FLAG;
if (sspi_ret_flags & ASC_RET_REPLAY_DETECT)
*ret_flags |= GSS_C_REPLAY_FLAG;
if (sspi_ret_flags & ASC_RET_DELEGATE)
*ret_flags |= GSS_C_DELEG_FLAG;
if (sspi_ret_flags & ASC_RET_INTEGRITY)
*ret_flags |= GSS_C_INTEG_FLAG;
if (sspi_ret_flags & ASC_RET_SEQUENCE_DETECT)
*ret_flags |= GSS_C_SEQUENCE_FLAG;
}
/* report if delegation was requested by not fulfilled */
if ((sspi_req_flags & ASC_REQ_DELEGATE) != 0 && (sspi_ret_flags & ASC_RET_DELEGATE) == 0)
debug("%s: delegation was requested but not fulfilled", __FUNCTION__);
/* if provided, specify the mechanism */
if (mech_type != NULL)
*mech_type = GSS_C_NT_HOSTBASED_SERVICE;
/* if requested, translate the expiration time to number of second */
if (time_rec != NULL) {
FILETIME current_time;
if (SystemTimeToFileTime(&current_time_system, &current_time) != 0)
*time_rec = (OM_uint32)(expiry.QuadPart - ((PLARGE_INTEGER)&current_time)->QuadPart) / 10000;
else
error("SystemTimeToFileTime failed with %lu", GetLastError());
}
/* only do checks on the finalized context (no continue needed) */
if (status == SEC_E_OK) {
/* extract the username from the context handle will be domain\samaccountname format */
SecPkgContext_NamesW NamesBuffer;
if (SecFunctions->QueryContextAttributesW(*context_handle, SECPKG_ATTR_NAMES, &NamesBuffer) != SEC_E_OK)
goto done;
/* copy to internal utf8 string and free the sspi string */
if ((*src_name = utf16_to_utf8(NamesBuffer.sUserName)) == NULL)
goto done;
FreeContextBuffer(NamesBuffer.sUserName);
}
/* copy output token to output buffer */
output_token->length = output_buffer_token.cbBuffer;
output_token->value = malloc(output_token->length);
memcpy(output_token->value, output_buffer_token.pvBuffer, output_token->length);
SecFunctions->FreeContextBuffer(output_buffer_token.pvBuffer);
/* get the user token for impersonation */
if (delegated_cred_handle != NULL) {
if ((*delegated_cred_handle = malloc(sizeof(struct cred_st))) == NULL)
goto done;
if (SecFunctions->QuerySecurityContextToken(*context_handle, &sspi_auth_user) != SEC_E_OK)
goto done;
(*delegated_cred_handle)->isToken = 1;
(*delegated_cred_handle)->token = sspi_auth_user;
}
ret = (status == SEC_I_CONTINUE_NEEDED) ? GSS_S_CONTINUE_NEEDED : GSS_S_COMPLETE;
done:
if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
if (p_ctx_h)
free(p_ctx_h);
if (*src_name)
free(*src_name);
if (delegated_cred_handle && *delegated_cred_handle)
free(*delegated_cred_handle);
}
return ret;
}
/*
* Allows an application to obtain a textual representation of an opaque
* internal-form name for display purposes. The syntax of a printable name is
* defined by the GSS-API implementation.
*/
OM_uint32
gss_display_name(OM_uint32 * minor_status, gss_name_t input_name,
gss_buffer_t output_name_buffer, gss_OID * output_name_type)
{
if (ssh_gss_sspi_init(minor_status) == 0)
return GSS_S_FAILURE;
output_name_buffer->length = strlen(input_name) + 1;
if ((output_name_buffer->value = _strdup(input_name)) == NULL)
return GSS_S_FAILURE;
/* set the output oid type if requested */
if (output_name_type != NULL)
*output_name_type = GSS_C_NT_HOSTBASED_SERVICE;
return GSS_S_COMPLETE;
}
/*
* Allows an application to obtain a textual representation of a GSS-API status
* code, for display to the user or for logging purposes. Since some status
* values may indicate multiple conditions, applications may need to call
* gss_display_status multiple times, each call generating a single text string.
* The message_context parameter is used by gss_display_status to store state
* information about which error messages have already been extracted from a
* given status_value; message_context must be initialized to 0 by the
* application prior to the first call, and gss_display_status will return a
* non-zero value in this parameter if there are further messages to extract.
*/
OM_uint32
gss_display_status(OM_uint32 * minor_status, OM_uint32 status_value, int status_type,
gss_OID mech_type, OM_uint32 * message_context, gss_buffer_t status_string)
{
if (ssh_gss_sspi_init(minor_status) == 0)
return GSS_S_FAILURE;
/* lookup textual representation of the numeric status code */
char * message_string = NULL;
if (status_value == GSS_S_COMPLETE)
message_string = "GSS_S_COMPLETE";
else if (status_value == GSS_S_BAD_BINDINGS)
message_string = "GSS_S_BAD_BINDINGS";
else if (status_value == GSS_S_BAD_MECH)
message_string = "GSS_S_BAD_MECH";
else if (status_value == GSS_S_BAD_NAME)
message_string = "GSS_S_BAD_NAME";
else if (status_value == GSS_S_BAD_NAMETYPE)
message_string = "GSS_S_BAD_NAMETYPE";
else if (status_value == GSS_S_BAD_QOP)
message_string = "GSS_S_BAD_QOP";
else if (status_value == GSS_S_BAD_SIG)
message_string = "GSS_S_BAD_SIG";
else if (status_value == GSS_S_BAD_STATUS)
message_string = "GSS_S_BAD_STATUS";
else if (status_value == GSS_S_CONTEXT_EXPIRED)
message_string = "GSS_S_CONTEXT_EXPIRED";
else if (status_value == GSS_S_CONTINUE_NEEDED)
message_string = "GSS_S_CONTINUE_NEEDED";
else if (status_value == GSS_S_CREDENTIALS_EXPIRED)
message_string = "GSS_S_CREDENTIALS_EXPIRED";
else if (status_value == GSS_S_DEFECTIVE_CREDENTIAL)
message_string = "GSS_S_DEFECTIVE_CREDENTIAL";
else if (status_value == GSS_S_DEFECTIVE_TOKEN)
message_string = "GSS_S_DEFECTIVE_TOKEN";
else if (status_value == GSS_S_DUPLICATE_ELEMENT)
message_string = "GSS_S_DUPLICATE_ELEMENT";
else if (status_value == GSS_S_DUPLICATE_TOKEN)
message_string = "GSS_S_DUPLICATE_TOKEN";
else if (status_value == GSS_S_FAILURE)
message_string = "GSS_S_FAILURE";
else if (status_value == GSS_S_NAME_NOT_MN)
message_string = "GSS_S_NAME_NOT_MN";
else if (status_value == GSS_S_NO_CONTEXT)
message_string = "GSS_S_NO_CONTEXT";
else if (status_value == GSS_S_NO_CRED)
message_string = "GSS_S_NO_CRED";
else if (status_value == GSS_S_OLD_TOKEN)
message_string = "GSS_S_OLD_TOKEN";
else if (status_value == GSS_S_UNAUTHORIZED)
message_string = "GSS_S_UNAUTHORIZED";
else if (status_value == GSS_S_UNAVAILABLE)
message_string = "GSS_S_UNAVAILABLE";
else if (status_value == GSS_S_UNSEQ_TOKEN)
message_string = "GSS_S_UNSEQ_TOKEN";
/* copy local status string to the output buffer */
status_string->length = strlen(message_string) + 1;
if ((status_string->value = _strdup(message_string)) == NULL)
return GSS_S_FAILURE;
/* no supplementary messages available */
*message_context = 0;
return GSS_S_COMPLETE;
}
/*
* The function ssh_gssapi_krb5_userok and gssapi_kerberos_mech structure
* are referenced in gss-serv.c and are required in order for the calling
* code to accept negotiate a kerberos token.
*/
static int
ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
{
/*
* This check is important since it makes sure that the username string
* that the user passed (e.g. user@host) matches the user authenticated
* via SSPI. If this check fails, the authentication process will move
* onto the next available method.
*/
struct passwd * user = getpwnam(name);
if (user == NULL)
{
error("sspi getpwnam failed to get user from user-provided, resolved user '%s'", name);
return 0;
}
if (_stricmp(client->displayname.value, user->pw_name) != 0) {
/* check failed */
debug("sspi user '%s' did not match user-provided, resolved user '%s'",
(char *) client->displayname.value, name);
return 0;
}
return 1;
}
ssh_gssapi_mech gssapi_kerberos_mech = {
"toWM5Slw5Ew8Mqkay+al2g==",
"Kerberos",
{sizeof(GSS_C_NT_HOSTBASED_SERVICE_STR) - 1, GSS_C_NT_HOSTBASED_SERVICE_STR},
NULL,
&ssh_gssapi_krb5_userok,
NULL,
NULL
};
#endif /* KRB5 */
#endif /* GSSAPI */
\ No newline at end of file
...@@ -57,12 +57,12 @@ static ssh_gssapi_client gssapi_client = ...@@ -57,12 +57,12 @@ static ssh_gssapi_client gssapi_client =
ssh_gssapi_mech gssapi_null_mech = ssh_gssapi_mech gssapi_null_mech =
{ NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL}; { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL};
#ifdef KRB5 #if defined(KRB5) || defined (SSPI)
extern ssh_gssapi_mech gssapi_kerberos_mech; extern ssh_gssapi_mech gssapi_kerberos_mech;
#endif #endif
ssh_gssapi_mech* supported_mechs[]= { ssh_gssapi_mech* supported_mechs[]= {
#ifdef KRB5 #if defined(KRB5) || defined (SSPI)
&gssapi_kerberos_mech, &gssapi_kerberos_mech,
#endif #endif
&gssapi_null_mech, &gssapi_null_mech,
......
...@@ -163,6 +163,7 @@ ...@@ -163,6 +163,7 @@
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
#include <openssl/opensslv.h> /* For OPENSSL_VERSION_NUMBER */ #include <openssl/opensslv.h> /* For OPENSSL_VERSION_NUMBER */
#include "libcrypto-compat.h"
#endif #endif
#include "defines.h" #include "defines.h"
......
...@@ -56,6 +56,7 @@ kexdh_client(struct ssh *ssh) ...@@ -56,6 +56,7 @@ kexdh_client(struct ssh *ssh)
{ {
struct kex *kex = ssh->kex; struct kex *kex = ssh->kex;
int r; int r;
const BIGNUM *pub_key;
/* generate and send 'e', client DH public key */ /* generate and send 'e', client DH public key */
switch (kex->kex_type) { switch (kex->kex_type) {
...@@ -81,21 +82,27 @@ kexdh_client(struct ssh *ssh) ...@@ -81,21 +82,27 @@ kexdh_client(struct ssh *ssh)
goto out; goto out;
} }
debug("sending SSH2_MSG_KEXDH_INIT"); debug("sending SSH2_MSG_KEXDH_INIT");
if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0 || if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
(r = sshpkt_start(ssh, SSH2_MSG_KEXDH_INIT)) != 0 || goto out;
(r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || DH_get0_key(kex->dh, &pub_key, NULL);
if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_INIT)) != 0 ||
(r = sshpkt_put_bignum2(ssh, pub_key)) != 0 ||
(r = sshpkt_send(ssh)) != 0) (r = sshpkt_send(ssh)) != 0)
goto out; goto out;
#ifdef DEBUG_KEXDH #ifdef DEBUG_KEXDH
DHparams_print_fp(stderr, kex->dh); DHparams_print_fp(stderr, kex->dh);
fprintf(stderr, "pub= "); fprintf(stderr, "pub= ");
BN_print_fp(stderr, kex->dh->pub_key); BN_print_fp(stderr, pub_key);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
#endif #endif
debug("expecting SSH2_MSG_KEXDH_REPLY"); debug("expecting SSH2_MSG_KEXDH_REPLY");
ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_REPLY, &input_kex_dh); ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_REPLY, &input_kex_dh);
r = 0; r = 0;
out: out:
if (r != 0) {
DH_free(kex->dh);
kex->dh = NULL;
}
return r; return r;
} }
...@@ -110,6 +117,7 @@ input_kex_dh(int type, u_int32_t seq, void *ctxt) ...@@ -110,6 +117,7 @@ input_kex_dh(int type, u_int32_t seq, void *ctxt)
u_char hash[SSH_DIGEST_MAX_LENGTH]; u_char hash[SSH_DIGEST_MAX_LENGTH];
size_t klen = 0, slen, sbloblen, hashlen; size_t klen = 0, slen, sbloblen, hashlen;
int kout, r; int kout, r;
const BIGNUM *pub_key;
if (kex->verify_host_key == NULL) { if (kex->verify_host_key == NULL) {
r = SSH_ERR_INVALID_ARGUMENT; r = SSH_ERR_INVALID_ARGUMENT;
...@@ -169,6 +177,7 @@ input_kex_dh(int type, u_int32_t seq, void *ctxt) ...@@ -169,6 +177,7 @@ input_kex_dh(int type, u_int32_t seq, void *ctxt)
#endif #endif
/* calc and verify H */ /* calc and verify H */
DH_get0_key(kex->dh, &pub_key, NULL);
hashlen = sizeof(hash); hashlen = sizeof(hash);
if ((r = kex_dh_hash( if ((r = kex_dh_hash(
kex->hash_alg, kex->hash_alg,
...@@ -177,7 +186,7 @@ input_kex_dh(int type, u_int32_t seq, void *ctxt) ...@@ -177,7 +186,7 @@ input_kex_dh(int type, u_int32_t seq, void *ctxt)
sshbuf_ptr(kex->my), sshbuf_len(kex->my), sshbuf_ptr(kex->my), sshbuf_len(kex->my),
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
server_host_key_blob, sbloblen, server_host_key_blob, sbloblen,
kex->dh->pub_key, pub_key,
dh_server_pub, dh_server_pub,
shared_secret, shared_secret,
hash, &hashlen)) != 0) hash, &hashlen)) != 0)
......
...@@ -87,6 +87,10 @@ kexdh_server(struct ssh *ssh) ...@@ -87,6 +87,10 @@ kexdh_server(struct ssh *ssh)
ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_INIT, &input_kex_dh_init); ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_INIT, &input_kex_dh_init);
r = 0; r = 0;
out: out:
if (r != 0) {
DH_free(kex->dh);
kex->dh = NULL;
}
return r; return r;
} }
...@@ -102,6 +106,7 @@ input_kex_dh_init(int type, u_int32_t seq, void *ctxt) ...@@ -102,6 +106,7 @@ input_kex_dh_init(int type, u_int32_t seq, void *ctxt)
size_t sbloblen, slen; size_t sbloblen, slen;
size_t klen = 0, hashlen; size_t klen = 0, hashlen;
int kout, r; int kout, r;
const BIGNUM *pub_key;
if (kex->load_host_public_key == NULL || if (kex->load_host_public_key == NULL ||
kex->load_host_private_key == NULL) { kex->load_host_private_key == NULL) {
...@@ -164,6 +169,7 @@ input_kex_dh_init(int type, u_int32_t seq, void *ctxt) ...@@ -164,6 +169,7 @@ input_kex_dh_init(int type, u_int32_t seq, void *ctxt)
goto out; goto out;
/* calc H */ /* calc H */
hashlen = sizeof(hash); hashlen = sizeof(hash);
DH_get0_key(kex->dh, &pub_key, NULL);
if ((r = kex_dh_hash( if ((r = kex_dh_hash(
kex->hash_alg, kex->hash_alg,
kex->client_version_string, kex->client_version_string,
...@@ -172,7 +178,7 @@ input_kex_dh_init(int type, u_int32_t seq, void *ctxt) ...@@ -172,7 +178,7 @@ input_kex_dh_init(int type, u_int32_t seq, void *ctxt)
sshbuf_ptr(kex->my), sshbuf_len(kex->my), sshbuf_ptr(kex->my), sshbuf_len(kex->my),
server_host_key_blob, sbloblen, server_host_key_blob, sbloblen,
dh_client_pub, dh_client_pub,
kex->dh->pub_key, pub_key,
shared_secret, shared_secret,
hash, &hashlen)) != 0) hash, &hashlen)) != 0)
goto out; goto out;
...@@ -198,7 +204,7 @@ input_kex_dh_init(int type, u_int32_t seq, void *ctxt) ...@@ -198,7 +204,7 @@ input_kex_dh_init(int type, u_int32_t seq, void *ctxt)
/* send server hostkey, DH pubkey 'f' and singed H */ /* send server hostkey, DH pubkey 'f' and singed H */
if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 || if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 ||
(r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
(r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || /* f */ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || /* f */
(r = sshpkt_put_string(ssh, signature, slen)) != 0 || (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
(r = sshpkt_send(ssh)) != 0) (r = sshpkt_send(ssh)) != 0)
goto out; goto out;
......
...@@ -95,6 +95,7 @@ input_kex_dh_gex_group(int type, u_int32_t seq, void *ctxt) ...@@ -95,6 +95,7 @@ input_kex_dh_gex_group(int type, u_int32_t seq, void *ctxt)
struct kex *kex = ssh->kex; struct kex *kex = ssh->kex;
BIGNUM *p = NULL, *g = NULL; BIGNUM *p = NULL, *g = NULL;
int r, bits; int r, bits;
const BIGNUM *pub_key;
debug("got SSH2_MSG_KEX_DH_GEX_GROUP"); debug("got SSH2_MSG_KEX_DH_GEX_GROUP");
...@@ -119,26 +120,30 @@ input_kex_dh_gex_group(int type, u_int32_t seq, void *ctxt) ...@@ -119,26 +120,30 @@ input_kex_dh_gex_group(int type, u_int32_t seq, void *ctxt)
p = g = NULL; /* belong to kex->dh now */ p = g = NULL; /* belong to kex->dh now */
/* generate and send 'e', client DH public key */ /* generate and send 'e', client DH public key */
if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0 || if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
(r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT)) != 0 || goto out;
(r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || DH_get0_key(kex->dh, &pub_key, NULL);
if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT)) != 0 ||
(r = sshpkt_put_bignum2(ssh, pub_key)) != 0 ||
(r = sshpkt_send(ssh)) != 0) (r = sshpkt_send(ssh)) != 0)
goto out; goto out;
debug("SSH2_MSG_KEX_DH_GEX_INIT sent"); debug("SSH2_MSG_KEX_DH_GEX_INIT sent");
#ifdef DEBUG_KEXDH #ifdef DEBUG_KEXDH
DHparams_print_fp(stderr, kex->dh); DHparams_print_fp(stderr, kex->dh);
fprintf(stderr, "pub= "); fprintf(stderr, "pub= ");
BN_print_fp(stderr, kex->dh->pub_key); BN_print_fp(stderr, pub_key);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
#endif #endif
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, NULL); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, NULL);
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &input_kex_dh_gex_reply); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &input_kex_dh_gex_reply);
r = 0; r = 0;
out: out:
if (p)
BN_clear_free(p); BN_clear_free(p);
if (g)
BN_clear_free(g); BN_clear_free(g);
if (r != 0) {
DH_free(kex->dh);
kex->dh = NULL;
}
return r; return r;
} }
...@@ -153,6 +158,7 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, void *ctxt) ...@@ -153,6 +158,7 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, void *ctxt)
u_char hash[SSH_DIGEST_MAX_LENGTH]; u_char hash[SSH_DIGEST_MAX_LENGTH];
size_t klen = 0, slen, sbloblen, hashlen; size_t klen = 0, slen, sbloblen, hashlen;
int kout, r; int kout, r;
const BIGNUM *p, *g, *pub_key;
debug("got SSH2_MSG_KEX_DH_GEX_REPLY"); debug("got SSH2_MSG_KEX_DH_GEX_REPLY");
if (kex->verify_host_key == NULL) { if (kex->verify_host_key == NULL) {
...@@ -219,6 +225,8 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, void *ctxt) ...@@ -219,6 +225,8 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, void *ctxt)
kex->min = kex->max = -1; kex->min = kex->max = -1;
/* calc and verify H */ /* calc and verify H */
DH_get0_pqg(kex->dh, &p, NULL, &g);
DH_get0_key(kex->dh, &pub_key, NULL);
hashlen = sizeof(hash); hashlen = sizeof(hash);
if ((r = kexgex_hash( if ((r = kexgex_hash(
kex->hash_alg, kex->hash_alg,
...@@ -228,8 +236,8 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, void *ctxt) ...@@ -228,8 +236,8 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, void *ctxt)
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
server_host_key_blob, sbloblen, server_host_key_blob, sbloblen,
kex->min, kex->nbits, kex->max, kex->min, kex->nbits, kex->max,
kex->dh->p, kex->dh->g, p, g,
kex->dh->pub_key, pub_key,
dh_server_pub, dh_server_pub,
shared_secret, shared_secret,
hash, &hashlen)) != 0) hash, &hashlen)) != 0)
......
...@@ -73,6 +73,7 @@ input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt) ...@@ -73,6 +73,7 @@ input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt)
struct kex *kex = ssh->kex; struct kex *kex = ssh->kex;
int r; int r;
u_int min = 0, max = 0, nbits = 0; u_int min = 0, max = 0, nbits = 0;
const BIGNUM *p, *g;
debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); debug("SSH2_MSG_KEX_DH_GEX_REQUEST received");
if ((r = sshpkt_get_u32(ssh, &min)) != 0 || if ((r = sshpkt_get_u32(ssh, &min)) != 0 ||
...@@ -102,9 +103,10 @@ input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt) ...@@ -102,9 +103,10 @@ input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt)
goto out; goto out;
} }
debug("SSH2_MSG_KEX_DH_GEX_GROUP sent"); debug("SSH2_MSG_KEX_DH_GEX_GROUP sent");
DH_get0_pqg(kex->dh, &p, NULL, &g);
if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_GROUP)) != 0 || if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_GROUP)) != 0 ||
(r = sshpkt_put_bignum2(ssh, kex->dh->p)) != 0 || (r = sshpkt_put_bignum2(ssh, p)) != 0 ||
(r = sshpkt_put_bignum2(ssh, kex->dh->g)) != 0 || (r = sshpkt_put_bignum2(ssh, g)) != 0 ||
(r = sshpkt_send(ssh)) != 0) (r = sshpkt_send(ssh)) != 0)
goto out; goto out;
...@@ -116,6 +118,10 @@ input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt) ...@@ -116,6 +118,10 @@ input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt)
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &input_kex_dh_gex_init); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &input_kex_dh_gex_init);
r = 0; r = 0;
out: out:
if (r != 0) {
DH_free(kex->dh);
kex->dh = NULL;
}
return r; return r;
} }
...@@ -131,6 +137,7 @@ input_kex_dh_gex_init(int type, u_int32_t seq, void *ctxt) ...@@ -131,6 +137,7 @@ input_kex_dh_gex_init(int type, u_int32_t seq, void *ctxt)
size_t sbloblen, slen; size_t sbloblen, slen;
size_t klen = 0, hashlen; size_t klen = 0, hashlen;
int kout, r; int kout, r;
const BIGNUM *p, *g, *pub_key;
if (kex->load_host_public_key == NULL || if (kex->load_host_public_key == NULL ||
kex->load_host_private_key == NULL) { kex->load_host_private_key == NULL) {
...@@ -193,6 +200,8 @@ input_kex_dh_gex_init(int type, u_int32_t seq, void *ctxt) ...@@ -193,6 +200,8 @@ input_kex_dh_gex_init(int type, u_int32_t seq, void *ctxt)
goto out; goto out;
/* calc H */ /* calc H */
hashlen = sizeof(hash); hashlen = sizeof(hash);
DH_get0_pqg(kex->dh, &p, NULL, &g);
DH_get0_key(kex->dh, &pub_key, NULL);
if ((r = kexgex_hash( if ((r = kexgex_hash(
kex->hash_alg, kex->hash_alg,
kex->client_version_string, kex->client_version_string,
...@@ -201,9 +210,9 @@ input_kex_dh_gex_init(int type, u_int32_t seq, void *ctxt) ...@@ -201,9 +210,9 @@ input_kex_dh_gex_init(int type, u_int32_t seq, void *ctxt)
sshbuf_ptr(kex->my), sshbuf_len(kex->my), sshbuf_ptr(kex->my), sshbuf_len(kex->my),
server_host_key_blob, sbloblen, server_host_key_blob, sbloblen,
kex->min, kex->nbits, kex->max, kex->min, kex->nbits, kex->max,
kex->dh->p, kex->dh->g, p, g,
dh_client_pub, dh_client_pub,
kex->dh->pub_key, pub_key,
shared_secret, shared_secret,
hash, &hashlen)) != 0) hash, &hashlen)) != 0)
goto out; goto out;
...@@ -229,7 +238,7 @@ input_kex_dh_gex_init(int type, u_int32_t seq, void *ctxt) ...@@ -229,7 +238,7 @@ input_kex_dh_gex_init(int type, u_int32_t seq, void *ctxt)
/* send server hostkey, DH pubkey 'f' and singed H */ /* send server hostkey, DH pubkey 'f' and singed H */
if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 || if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 ||
(r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
(r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || /* f */ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || /* f */
(r = sshpkt_put_string(ssh, signature, slen)) != 0 || (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
(r = sshpkt_send(ssh)) != 0) (r = sshpkt_send(ssh)) != 0)
goto out; goto out;
......
/*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "includes.h"
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#include <string.h>
#include <openssl/engine.h>
static void *OPENSSL_zalloc(size_t num)
{
void *ret = OPENSSL_malloc(num);
if (ret != NULL)
memset(ret, 0, num);
return ret;
}
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
{
/* If the fields n and e in r are NULL, the corresponding input
* parameters MUST be non-NULL for n and e. d may be
* left NULL (in case only the public key is used).
*/
if ((r->n == NULL && n == NULL)
|| (r->e == NULL && e == NULL))
return 0;
if (n != NULL) {
BN_free(r->n);
r->n = n;
}
if (e != NULL) {
BN_free(r->e);
r->e = e;
}
if (d != NULL) {
BN_free(r->d);
r->d = d;
}
return 1;
}
int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
{
/* If the fields p and q in r are NULL, the corresponding input
* parameters MUST be non-NULL.
*/
if ((r->p == NULL && p == NULL)
|| (r->q == NULL && q == NULL))
return 0;
if (p != NULL) {
BN_free(r->p);
r->p = p;
}
if (q != NULL) {
BN_free(r->q);
r->q = q;
}
return 1;
}
int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
{
/* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input
* parameters MUST be non-NULL.
*/
if ((r->dmp1 == NULL && dmp1 == NULL)
|| (r->dmq1 == NULL && dmq1 == NULL)
|| (r->iqmp == NULL && iqmp == NULL))
return 0;
if (dmp1 != NULL) {
BN_free(r->dmp1);
r->dmp1 = dmp1;
}
if (dmq1 != NULL) {
BN_free(r->dmq1);
r->dmq1 = dmq1;
}
if (iqmp != NULL) {
BN_free(r->iqmp);
r->iqmp = iqmp;
}
return 1;
}
void RSA_get0_key(const RSA *r,
const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
{
if (n != NULL)
*n = r->n;
if (e != NULL)
*e = r->e;
if (d != NULL)
*d = r->d;
}
void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
{
if (p != NULL)
*p = r->p;
if (q != NULL)
*q = r->q;
}
void RSA_get0_crt_params(const RSA *r,
const BIGNUM **dmp1, const BIGNUM **dmq1,
const BIGNUM **iqmp)
{
if (dmp1 != NULL)
*dmp1 = r->dmp1;
if (dmq1 != NULL)
*dmq1 = r->dmq1;
if (iqmp != NULL)
*iqmp = r->iqmp;
}
void DSA_get0_pqg(const DSA *d,
const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
{
if (p != NULL)
*p = d->p;
if (q != NULL)
*q = d->q;
if (g != NULL)
*g = d->g;
}
int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
{
/* If the fields p, q and g in d are NULL, the corresponding input
* parameters MUST be non-NULL.
*/
if ((d->p == NULL && p == NULL)
|| (d->q == NULL && q == NULL)
|| (d->g == NULL && g == NULL))
return 0;
if (p != NULL) {
BN_free(d->p);
d->p = p;
}
if (q != NULL) {
BN_free(d->q);
d->q = q;
}
if (g != NULL) {
BN_free(d->g);
d->g = g;
}
return 1;
}
void DSA_get0_key(const DSA *d,
const BIGNUM **pub_key, const BIGNUM **priv_key)
{
if (pub_key != NULL)
*pub_key = d->pub_key;
if (priv_key != NULL)
*priv_key = d->priv_key;
}
int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
{
/* If the field pub_key in d is NULL, the corresponding input
* parameters MUST be non-NULL. The priv_key field may
* be left NULL.
*/
if (d->pub_key == NULL && pub_key == NULL)
return 0;
if (pub_key != NULL) {
BN_free(d->pub_key);
d->pub_key = pub_key;
}
if (priv_key != NULL) {
BN_free(d->priv_key);
d->priv_key = priv_key;
}
return 1;
}
void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
{
if (pr != NULL)
*pr = sig->r;
if (ps != NULL)
*ps = sig->s;
}
int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
{
if (r == NULL || s == NULL)
return 0;
BN_clear_free(sig->r);
BN_clear_free(sig->s);
sig->r = r;
sig->s = s;
return 1;
}
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
{
if (pr != NULL)
*pr = sig->r;
if (ps != NULL)
*ps = sig->s;
}
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
{
if (r == NULL || s == NULL)
return 0;
BN_clear_free(sig->r);
BN_clear_free(sig->s);
sig->r = r;
sig->s = s;
return 1;
}
void DH_get0_pqg(const DH *dh,
const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
{
if (p != NULL)
*p = dh->p;
if (q != NULL)
*q = dh->q;
if (g != NULL)
*g = dh->g;
}
int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
{
/* If the fields p and g in d are NULL, the corresponding input
* parameters MUST be non-NULL. q may remain NULL.
*/
if ((dh->p == NULL && p == NULL)
|| (dh->g == NULL && g == NULL))
return 0;
if (p != NULL) {
BN_free(dh->p);
dh->p = p;
}
if (q != NULL) {
BN_free(dh->q);
dh->q = q;
}
if (g != NULL) {
BN_free(dh->g);
dh->g = g;
}
if (q != NULL) {
dh->length = BN_num_bits(q);
}
return 1;
}
void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
{
if (pub_key != NULL)
*pub_key = dh->pub_key;
if (priv_key != NULL)
*priv_key = dh->priv_key;
}
int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
{
/* If the field pub_key in dh is NULL, the corresponding input
* parameters MUST be non-NULL. The priv_key field may
* be left NULL.
*/
if (dh->pub_key == NULL && pub_key == NULL)
return 0;
if (pub_key != NULL) {
BN_free(dh->pub_key);
dh->pub_key = pub_key;
}
if (priv_key != NULL) {
BN_free(dh->priv_key);
dh->priv_key = priv_key;
}
return 1;
}
int DH_set_length(DH *dh, long length)
{
dh->length = length;
return 1;
}
const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx)
{
return ctx->iv;
}
unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx)
{
return ctx->iv;
}
EVP_MD_CTX *EVP_MD_CTX_new(void)
{
return OPENSSL_zalloc(sizeof(EVP_MD_CTX));
}
static void OPENSSL_clear_free(void *str, size_t num)
{
if (str == NULL)
return;
if (num)
OPENSSL_cleanse(str, num);
OPENSSL_free(str);
}
/* This call frees resources associated with the context */
int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
{
if (ctx == NULL)
return 1;
/*
* Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because
* sometimes only copies of the context are ever finalised.
*/
if (ctx->digest && ctx->digest->cleanup
&& !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED))
ctx->digest->cleanup(ctx);
if (ctx->digest && ctx->digest->ctx_size && ctx->md_data
&& !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) {
OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
}
EVP_PKEY_CTX_free(ctx->pctx);
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(ctx->engine);
#endif
OPENSSL_cleanse(ctx, sizeof(*ctx));
return 1;
}
void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
{
EVP_MD_CTX_reset(ctx);
OPENSSL_free(ctx);
}
RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth)
{
RSA_METHOD *ret;
ret = OPENSSL_malloc(sizeof(RSA_METHOD));
if (ret != NULL) {
memcpy(ret, meth, sizeof(*meth));
ret->name = OPENSSL_strdup(meth->name);
if (ret->name == NULL) {
OPENSSL_free(ret);
return NULL;
}
}
return ret;
}
int RSA_meth_set1_name(RSA_METHOD *meth, const char *name)
{
char *tmpname;
tmpname = OPENSSL_strdup(name);
if (tmpname == NULL) {
return 0;
}
OPENSSL_free((char *)meth->name);
meth->name = tmpname;
return 1;
}
int RSA_meth_set_priv_enc(RSA_METHOD *meth,
int (*priv_enc) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding))
{
meth->rsa_priv_enc = priv_enc;
return 1;
}
int RSA_meth_set_priv_dec(RSA_METHOD *meth,
int (*priv_dec) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa,
int padding))
{
meth->rsa_priv_dec = priv_dec;
return 1;
}
int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa))
{
meth->finish = finish;
return 1;
}
void RSA_meth_free(RSA_METHOD *meth)
{
if (meth != NULL) {
OPENSSL_free((char *)meth->name);
OPENSSL_free(meth);
}
}
int RSA_bits(const RSA *r)
{
return (BN_num_bits(r->n));
}
int DSA_bits(const DSA *dsa)
{
return BN_num_bits(dsa->p);
}
RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey)
{
if (pkey->type != EVP_PKEY_RSA) {
return NULL;
}
return pkey->pkey.rsa;
}
EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len)
{
EVP_CIPHER *cipher = OPENSSL_zalloc(sizeof(EVP_CIPHER));
if (cipher != NULL) {
cipher->nid = cipher_type;
cipher->block_size = block_size;
cipher->key_len = key_len;
}
return cipher;
}
void EVP_CIPHER_meth_free(EVP_CIPHER *cipher)
{
OPENSSL_free(cipher);
}
int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len)
{
cipher->iv_len = iv_len;
return 1;
}
int EVP_CIPHER_meth_set_flags(EVP_CIPHER *cipher, unsigned long flags)
{
cipher->flags = flags;
return 1;
}
int EVP_CIPHER_meth_set_init(EVP_CIPHER *cipher,
int (*init) (EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv,
int enc))
{
cipher->init = init;
return 1;
}
int EVP_CIPHER_meth_set_do_cipher(EVP_CIPHER *cipher,
int (*do_cipher) (EVP_CIPHER_CTX *ctx,
unsigned char *out,
const unsigned char *in,
size_t inl))
{
cipher->do_cipher = do_cipher;
return 1;
}
int EVP_CIPHER_meth_set_cleanup(EVP_CIPHER *cipher,
int (*cleanup) (EVP_CIPHER_CTX *))
{
cipher->cleanup = cleanup;
return 1;
}
int EVP_CIPHER_meth_set_ctrl(EVP_CIPHER *cipher,
int (*ctrl) (EVP_CIPHER_CTX *, int type,
int arg, void *ptr))
{
cipher->ctrl = ctrl;
return 1;
}
int (*EVP_CIPHER_meth_get_init(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv,
int enc)
{
return cipher->init;
}
int (*EVP_CIPHER_meth_get_do_cipher(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx,
unsigned char *out,
const unsigned char *in,
size_t inl)
{
return cipher->do_cipher;
}
int (*EVP_CIPHER_meth_get_cleanup(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *)
{
return cipher->cleanup;
}
int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
int type, int arg,
void *ptr)
{
return cipher->ctrl;
}
int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx)
{
return ctx->encrypt;
}
#endif /* OPENSSL_VERSION_NUMBER */
#ifndef LIBCRYPTO_COMPAT_H
#define LIBCRYPTO_COMPAT_H
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/ecdsa.h>
#include <openssl/dh.h>
#include <openssl/evp.h>
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);
void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d);
void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q);
void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp);
void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);
void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key);
int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);
void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s);
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key);
int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
int DH_set_length(DH *dh, long length);
const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx);
unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx);
int EVP_MD_CTX_reset(EVP_MD_CTX *ctx);
EVP_MD_CTX *EVP_MD_CTX_new(void);
void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
#define EVP_CIPHER_impl_ctx_size(e) e->ctx_size
#define EVP_CIPHER_CTX_get_cipher_data(ctx) ctx->cipher_data
RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth);
int RSA_meth_set1_name(RSA_METHOD *meth, const char *name);
#define RSA_meth_get_finish(meth) meth->finish
int RSA_meth_set_priv_enc(RSA_METHOD *meth, int (*priv_enc) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding));
int RSA_meth_set_priv_dec(RSA_METHOD *meth, int (*priv_dec) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding));
int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa));
void RSA_meth_free(RSA_METHOD *meth);
int RSA_bits(const RSA *r);
int DSA_bits(const DSA *d);
RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey);
EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len);
void EVP_CIPHER_meth_free(EVP_CIPHER *cipher);
int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len);
int EVP_CIPHER_meth_set_flags(EVP_CIPHER *cipher, unsigned long flags);
int EVP_CIPHER_meth_set_init(EVP_CIPHER *cipher,
int (*init) (EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv,
int enc));
int EVP_CIPHER_meth_set_do_cipher(EVP_CIPHER *cipher,
int (*do_cipher) (EVP_CIPHER_CTX *ctx,
unsigned char *out,
const unsigned char *in,
size_t inl));
int EVP_CIPHER_meth_set_cleanup(EVP_CIPHER *cipher,
int (*cleanup) (EVP_CIPHER_CTX *));
int EVP_CIPHER_meth_set_ctrl(EVP_CIPHER *cipher,
int (*ctrl) (EVP_CIPHER_CTX *, int type,
int arg, void *ptr));
int (*EVP_CIPHER_meth_get_init(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv,
int enc);
int (*EVP_CIPHER_meth_get_do_cipher(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx,
unsigned char *out,
const unsigned char *in,
size_t inl);
int (*EVP_CIPHER_meth_get_cleanup(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *);
int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
int type, int arg,
void *ptr);
#define EVP_CIPHER_CTX_reset(c) EVP_CIPHER_CTX_init(c)
int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx);
#endif /* OPENSSL_VERSION_NUMBER */
#endif /* LIBCRYPTO_COMPAT_H */
#ifndef LIBCRYPTO_COMPAT_H
#define LIBCRYPTO_COMPAT_H
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/ecdsa.h>
#include <openssl/dh.h>
#include <openssl/evp.h>
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);
void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d);
void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q);
void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp);
void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);
void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key);
int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);
void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s);
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key);
int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
int DH_set_length(DH *dh, long length);
const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx);
unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx);
int EVP_MD_CTX_reset(EVP_MD_CTX *ctx);
EVP_MD_CTX *EVP_MD_CTX_new(void);
void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
#define EVP_CIPHER_impl_ctx_size(e) e->ctx_size
#define EVP_CIPHER_CTX_get_cipher_data(ctx) ctx->cipher_data
RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth);
int RSA_meth_set1_name(RSA_METHOD *meth, const char *name);
#define RSA_meth_get_finish(meth) meth->finish
int RSA_meth_set_priv_enc(RSA_METHOD *meth, int (*priv_enc) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding));
int RSA_meth_set_priv_dec(RSA_METHOD *meth, int (*priv_dec) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding));
int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa));
void RSA_meth_free(RSA_METHOD *meth);
int RSA_bits(const RSA *r);
int DSA_bits(const DSA *d);
RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey);
EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len);
void EVP_CIPHER_meth_free(EVP_CIPHER *cipher);
int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len);
int EVP_CIPHER_meth_set_flags(EVP_CIPHER *cipher, unsigned long flags);
int EVP_CIPHER_meth_set_init(EVP_CIPHER *cipher,
int (*init) (EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv,
int enc));
int EVP_CIPHER_meth_set_do_cipher(EVP_CIPHER *cipher,
int (*do_cipher) (EVP_CIPHER_CTX *ctx,
unsigned char *out,
const unsigned char *in,
size_t inl));
int EVP_CIPHER_meth_set_cleanup(EVP_CIPHER *cipher,
int (*cleanup) (EVP_CIPHER_CTX *));
int EVP_CIPHER_meth_set_ctrl(EVP_CIPHER *cipher,
int (*ctrl) (EVP_CIPHER_CTX *, int type,
int arg, void *ptr));
int (*EVP_CIPHER_meth_get_init(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv,
int enc);
int (*EVP_CIPHER_meth_get_do_cipher(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx,
unsigned char *out,
const unsigned char *in,
size_t inl);
int (*EVP_CIPHER_meth_get_cleanup(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *);
int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
int type, int arg,
void *ptr);
#define EVP_CIPHER_CTX_reset(c) EVP_CIPHER_CTX_init(c)
int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx);
#endif /* OPENSSL_VERSION_NUMBER */
#endif /* LIBCRYPTO_COMPAT_H */
#ifndef LIBCRYPTO_COMPAT_H
#define LIBCRYPTO_COMPAT_H
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/ecdsa.h>
#include <openssl/dh.h>
#include <openssl/evp.h>
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);
void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d);
void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q);
void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp);
void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);
void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key);
int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);
void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s);
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key);
int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
int DH_set_length(DH *dh, long length);
const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx);
unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx);
int EVP_MD_CTX_reset(EVP_MD_CTX *ctx);
EVP_MD_CTX *EVP_MD_CTX_new(void);
void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
#define EVP_CIPHER_impl_ctx_size(e) e->ctx_size
#define EVP_CIPHER_CTX_get_cipher_data(ctx) ctx->cipher_data
RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth);
int RSA_meth_set1_name(RSA_METHOD *meth, const char *name);
#define RSA_meth_get_finish(meth) meth->finish
int RSA_meth_set_priv_enc(RSA_METHOD *meth, int (*priv_enc) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding));
int RSA_meth_set_priv_dec(RSA_METHOD *meth, int (*priv_dec) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding));
int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa));
void RSA_meth_free(RSA_METHOD *meth);
int RSA_bits(const RSA *r);
int DSA_bits(const DSA *d);
RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey);
EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len);
void EVP_CIPHER_meth_free(EVP_CIPHER *cipher);
int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len);
int EVP_CIPHER_meth_set_flags(EVP_CIPHER *cipher, unsigned long flags);
int EVP_CIPHER_meth_set_init(EVP_CIPHER *cipher,
int (*init) (EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv,
int enc));
int EVP_CIPHER_meth_set_do_cipher(EVP_CIPHER *cipher,
int (*do_cipher) (EVP_CIPHER_CTX *ctx,
unsigned char *out,
const unsigned char *in,
size_t inl));
int EVP_CIPHER_meth_set_cleanup(EVP_CIPHER *cipher,
int (*cleanup) (EVP_CIPHER_CTX *));
int EVP_CIPHER_meth_set_ctrl(EVP_CIPHER *cipher,
int (*ctrl) (EVP_CIPHER_CTX *, int type,
int arg, void *ptr));
int (*EVP_CIPHER_meth_get_init(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv,
int enc);
int (*EVP_CIPHER_meth_get_do_cipher(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx,
unsigned char *out,
const unsigned char *in,
size_t inl);
int (*EVP_CIPHER_meth_get_cleanup(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *);
int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
int type, int arg,
void *ptr);
#define EVP_CIPHER_CTX_reset(c) EVP_CIPHER_CTX_init(c)
int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx);
#endif /* OPENSSL_VERSION_NUMBER */
#endif /* LIBCRYPTO_COMPAT_H */
...@@ -581,9 +581,12 @@ mm_answer_moduli(int sock, Buffer *m) ...@@ -581,9 +581,12 @@ mm_answer_moduli(int sock, Buffer *m)
return (0); return (0);
} else { } else {
/* Send first bignum */ /* Send first bignum */
const BIGNUM *p, *g;
DH_get0_pqg(dh, &p, NULL, &g);
buffer_put_char(m, 1); buffer_put_char(m, 1);
buffer_put_bignum2(m, dh->p); buffer_put_bignum2(m, p);
buffer_put_bignum2(m, dh->g); buffer_put_bignum2(m, g);
DH_free(dh); DH_free(dh);
} }
......
...@@ -70,12 +70,19 @@ ssh_compatible_openssl(long headerver, long libver) ...@@ -70,12 +70,19 @@ ssh_compatible_openssl(long headerver, long libver)
void void
ssh_OpenSSL_add_all_algorithms(void) ssh_OpenSSL_add_all_algorithms(void)
{ {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
/* Enable use of crypto hardware */ /* Enable use of crypto hardware */
ENGINE_load_builtin_engines(); ENGINE_load_builtin_engines();
#if OPENSSL_VERSION_NUMBER < 0x10001000L
ENGINE_register_all_complete(); ENGINE_register_all_complete();
#endif
OPENSSL_config(NULL); OPENSSL_config(NULL);
#else
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS |
OPENSSL_INIT_ADD_ALL_DIGESTS | OPENSSL_INIT_LOAD_CONFIG, NULL);
#endif
} }
#endif #endif
......
diff --git a/configure.ac b/configure.ac
index 7470dfc..1f0934b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -54,8 +54,8 @@ AC_SUBST([TEST_SHELL], [sh])
AC_SUBST(NXCOMPINC)
AC_SUBST(NXCOMPLIBS)
-NXCOMPINC="-I$includedir/nx"
-NXCOMPLIBS="-lXcomp"
+NXCOMPINC="-I../nxcomp"
+NXCOMPLIBS="-L../nxcomp -lXcomp -lstdc++ -lpng -ljpeg -lz"
dnl select manpage formatter
if test "x$MANDOC" != "x" ; then
@@ -582,7 +582,7 @@ case "$host" in
*-*-cygwin*)
check_for_libcrypt_later=1
dont_check_for_resolv=1
- LIBS="$LIBS /usr/lib/textmode.o /usr/lib/libminires.a"
+ LIBS="$LIBS /usr/lib/textmode.o"
AC_DEFINE([HAVE_CYGWIN], [1], [Define if you are on Cygwin])
AC_DEFINE([USE_PIPES], [1], [Use PIPES instead of a socketpair()])
AC_DEFINE([NO_UID_RESTORATION_TEST], [1],
diff --git a/Makefile.in b/Makefile.in
index e149e74..59db511 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -98,7 +98,8 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
platform-pledge.o platform-tracing.o libcrypto-compat.o
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
- sshconnect.o sshconnect1.o sshconnect2.o mux.o proxy.o
+ sshconnect.o sshconnect1.o sshconnect2.o mux.o proxy.o \
+ gss-serv-sspi.o
SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \
audit.o audit-bsm.o audit-linux.o platform.o \
@@ -108,7 +109,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \
auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
auth2-none.o auth2-passwd.o auth2-pubkey.o \
monitor.o monitor_wrap.o auth-krb5.o \
- auth2-gss.o gss-serv.o gss-serv-krb5.o \
+ auth2-gss.o gss-serv.o gss-serv-krb5.o gss-serv-sspi.o \
loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
sftp-server.o sftp-common.o \
sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
diff --git a/configure.ac b/configure.ac
index 1f0934b..5961157 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4182,11 +4182,28 @@ AC_ARG_WITH([selinux],
AC_SUBST([SSHLIBS])
AC_SUBST([SSHDLIBS])
+# Check whether user wants SSPI support
+SSPI_MSG="no"
+AC_ARG_WITH([sspi],
+ [ --with-sspi Enable GSSAPI SSPI support],
+ [ if test "x$withval" != "xno" ; then
+ AC_DEFINE([SSPI], [1], [Define if you want SSPI support])
+ AC_DEFINE([GSSAPI], [1],
+ [Define this if you want GSSAPI support in the version 2 protocol])
+ AC_DEFINE([GSSAPI_SSPI], [1], [Define if you want GSSAPI SSPI support])
+ GSSLIBS="-lsecur32 -lws2_32"
+ SSPI_MSG="yes"
+ fi ]
+)
+
# Check whether user wants Kerberos 5 support
KRB5_MSG="no"
AC_ARG_WITH([kerberos5],
[ --with-kerberos5=PATH Enable Kerberos 5 support],
[ if test "x$withval" != "xno" ; then
+ if test "x$SSPI_MSG" = "xyes" ; then
+ AC_MSG_ERROR([cannot use --with-sspi and --with-kerberos5 together, use one only])
+ fi
if test "x$withval" = "xyes" ; then
KRB5ROOT="/usr/local"
else
@@ -5104,6 +5121,7 @@ echo " Manpage format: $MANTYPE"
echo " PAM support: $PAM_MSG"
echo " OSF SIA support: $SIA_MSG"
echo " KerberosV support: $KRB5_MSG"
+echo " SSPI support: $SSPI_MSG"
echo " SELinux support: $SELINUX_MSG"
echo " Smartcard support: $SCARD_MSG"
echo " S/KEY support: $SKEY_MSG"
diff --git a/contrib/win32/win32compat/debug.h b/contrib/win32/win32compat/debug.h
new file mode 100644
index 0000000..9966ad5
--- /dev/null
+++ b/contrib/win32/win32compat/debug.h
@@ -0,0 +1,15 @@
+#pragma once
+// #ifndef __attribute__
+// #define __attribute__(A)
+// #endif
+
+#include "../../../log.h"
+#include "../../../ssherr.h"
+/* Enable the following for verbose logging */
+#if (0)
+#define debug4 debug2
+#define debug5 debug3
+#else
+#define debug4(a,...)
+#define debug5(a,...)
+#endif
\ No newline at end of file
diff --git a/contrib/win32/win32compat/inc/gssapi.h b/contrib/win32/win32compat/inc/gssapi.h
new file mode 100644
index 0000000..e4c99ef
--- /dev/null
+++ b/contrib/win32/win32compat/inc/gssapi.h
@@ -0,0 +1,253 @@
+/*
+ * Author: Bryan Berns <berns@uwalumni.com>
+ *
+ * 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.
+ */
+
+#pragma once
+
+ /*
+ * This file provides the GSSAPI interface to support Kerberos SSPI within
+ * OpenSSH. This is only a partial definition of the full GSSAPI specification
+ * since OpenSSH only requires a subset of the overall functionality.
+ *
+ * The definitions are derived from information provided in RFC2744. In
+ * addition, RFC2743 provides additional information on the GSSAPI
+ * specification and intended operation.
+ */
+
+#include <windows.h>
+#include <stdint.h>
+
+#define SECURITY_WIN32
+#include <security.h>
+
+/*
+ * Common Structures & Type Definitions
+ */
+
+typedef uint32_t OM_uint32;
+
+typedef char *gss_name_struct, *gss_name_t;
+
+typedef struct cred_st *gss_cred_id_t;
+typedef CtxtHandle *gss_ctx_id_t;
+
+typedef OM_uint32 gss_qop_t;
+typedef OM_uint32 gss_cred_usage_t;
+
+typedef struct gss_buffer_desc_struct
+{
+ size_t length;
+ void *value;
+}
+gss_buffer_desc, *gss_buffer_t;
+
+typedef struct gss_OID_desc_struct
+{
+ OM_uint32 length;
+ void *elements;
+}
+gss_OID_desc, *gss_OID;
+
+typedef struct gss_OID_set_desc_struct
+{
+ size_t count;
+ gss_OID elements;
+}
+gss_OID_set_desc, *gss_OID_set;
+
+typedef struct gss_channel_bindings_struct
+{
+ OM_uint32 initiator_addrtype;
+ gss_buffer_desc initiator_address;
+ OM_uint32 acceptor_addrtype;
+ gss_buffer_desc acceptor_address;
+ gss_buffer_desc application_data;
+}
+gss_channel_bindings_desc, *gss_channel_bindings_t;
+
+/*
+ * Input & Return Flags
+ */
+
+/* Credential Usage Indication Options */
+#define GSS_C_BOTH 0
+#define GSS_C_INITIATE 1
+#define GSS_C_ACCEPT 2
+
+/* Context Flag Options */
+#define GSS_C_DELEG_FLAG 1
+#define GSS_C_MUTUAL_FLAG 2
+#define GSS_C_REPLAY_FLAG 4
+#define GSS_C_SEQUENCE_FLAG 8
+#define GSS_C_CONF_FLAG 16
+#define GSS_C_INTEG_FLAG 32
+#define GSS_C_ANON_FLAG 64
+#define GSS_C_PROT_READY_FLAG 128
+#define GSS_C_TRANS_FLAG 256
+#define GSS_C_DELEG_POLICY_FLAG 32768
+
+/* Display Status Code Types */
+#define GSS_C_GSS_CODE 1
+#define GSS_C_MECH_CODE 2
+
+/* Convenience Null Castless Comparison Options */
+#define GSS_C_NO_NAME ((gss_name_t) 0)
+#define GSS_C_NO_BUFFER ((gss_buffer_t) 0)
+#define GSS_C_NO_OID ((gss_OID) 0)
+#define GSS_C_NO_OID_SET ((gss_OID_set) 0)
+#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0)
+#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0)
+#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0)
+
+/* Convenience Initializer For Empty Buffer */
+#define GSS_C_EMPTY_BUFFER {0, NULL}
+
+/* Default Quality of Protection Code */
+#define GSS_C_QOP_DEFAULT 0
+
+ /* Infinite Context / Credential Value */
+#define GSS_C_INDEFINITE ((OM_uint32) 0xfffffffful)
+
+/*
+ * Status & Return Code Processing
+ */
+
+#define GSS_S_COMPLETE 0
+
+#define GSS_C_CALLING_ERROR_OFFSET 24
+#define GSS_C_ROUTINE_ERROR_OFFSET 16
+#define GSS_C_SUPPLEMENTARY_OFFSET 0
+#define GSS_C_CALLING_ERROR_MASK ((OM_uint32) 0377ul)
+#define GSS_C_ROUTINE_ERROR_MASK ((OM_uint32) 0377ul)
+
+#define GSS_CALLING_ERROR(x) ((x) & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET))
+#define GSS_ROUTINE_ERROR(x) ((x) & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))
+#define GSS_ERROR(x) ((x) & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)))
+
+#define GSS_S_BAD_MECH (((OM_uint32) 1ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_NAME (((OM_uint32) 2ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_NAMETYPE (((OM_uint32) 3ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_BINDINGS (((OM_uint32) 4ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_STATUS (((OM_uint32) 5ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_SIG (((OM_uint32) 6ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_NO_CRED (((OM_uint32) 7ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_NO_CONTEXT (((OM_uint32) 8ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_DEFECTIVE_TOKEN (((OM_uint32) 9ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_DEFECTIVE_CREDENTIAL (((OM_uint32) 10ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_CREDENTIALS_EXPIRED (((OM_uint32) 11ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_CONTEXT_EXPIRED (((OM_uint32) 12ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_FAILURE (((OM_uint32) 13ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_QOP (((OM_uint32) 14ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_UNAUTHORIZED (((OM_uint32) 15ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_UNAVAILABLE (((OM_uint32) 16ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_DUPLICATE_ELEMENT (((OM_uint32) 17ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_NAME_NOT_MN (((OM_uint32) 18ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+
+#define GSS_S_CONTINUE_NEEDED (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 0))
+#define GSS_S_DUPLICATE_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 1))
+#define GSS_S_OLD_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 2))
+#define GSS_S_UNSEQ_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 3))
+#define GSS_S_GAP_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 4))
+
+/*
+ * Function Prototypes
+ */
+
+OM_uint32
+gss_accept_sec_context(OM_uint32 * minor_status, gss_ctx_id_t * context_handle,
+ gss_cred_id_t acceptor_cred_handle, gss_buffer_t input_token_buffer,
+ gss_channel_bindings_t input_chan_bindings, gss_name_t * src_name,
+ gss_OID * mech_type, gss_buffer_t output_token, OM_uint32 * ret_flags,
+ OM_uint32 * time_rec, gss_cred_id_t * delegated_cred_handle);
+
+OM_uint32
+gss_acquire_cred(OM_uint32 *minor_status, gss_name_t desired_name,
+ OM_uint32 time_req, gss_OID_set desired_mechs, gss_cred_usage_t cred_usage,
+ gss_cred_id_t * output_cred_handle, gss_OID_set *actual_mechs,
+ OM_uint32 *time_rec);
+
+OM_uint32
+gss_add_oid_set_member(OM_uint32 * minor_status, gss_OID member_oid,
+ gss_OID_set * oid_set);
+
+OM_uint32
+gss_create_empty_oid_set(OM_uint32 * minor_status, gss_OID_set * oid_set);
+
+OM_uint32
+gss_init_sec_context(
+ OM_uint32 * minor_status, gss_cred_id_t claimant_cred_handle, gss_ctx_id_t * context_handle,
+ gss_name_t target_name, gss_OID mech_type, OM_uint32 req_flags, OM_uint32 time_req, gss_channel_bindings_t input_chan_bindings,
+ gss_buffer_t input_token, gss_OID * actual_mech_type, gss_buffer_t output_token, OM_uint32 * ret_flags,
+ OM_uint32 * time_rec);
+
+OM_uint32
+gss_delete_sec_context(OM_uint32 * minor_status, gss_ctx_id_t * context_handle,
+ gss_buffer_t output_token);
+
+OM_uint32
+gss_display_name(OM_uint32 * minor_status, gss_name_t input_name,
+ gss_buffer_t output_name_buffer, gss_OID * output_name_type);
+
+OM_uint32
+gss_display_status(OM_uint32 * minor_status, OM_uint32 status_value,
+ int status_type, gss_OID mech_type, OM_uint32 * message_context,
+ gss_buffer_t status_string);
+
+OM_uint32
+gss_export_name(OM_uint32 * minor_status, const gss_name_t input_name,
+ gss_buffer_t exported_name);
+
+OM_uint32
+gss_get_mic(OM_uint32 * minor_status, gss_ctx_id_t context_handle,
+ gss_qop_t qop_req, gss_buffer_t message_buffer,
+ gss_buffer_t message_token);
+
+OM_uint32
+gss_import_name(OM_uint32 * minor_status, gss_buffer_t input_name_buffer,
+ gss_OID input_name_type, gss_name_t * output_name);
+
+OM_uint32
+gss_indicate_mechs(OM_uint32 * minor_status, gss_OID_set * mech_set);
+
+OM_uint32
+gss_release_buffer(OM_uint32 * minor_status, gss_buffer_t buffer);
+
+OM_uint32
+gss_release_cred(OM_uint32 * minor_status, gss_cred_id_t * cred_handle);
+
+OM_uint32
+gss_release_name(OM_uint32 * minor_status, gss_name_t * input_name);
+
+OM_uint32
+gss_release_oid_set(OM_uint32 * minor_status, gss_OID_set * set);
+
+OM_uint32
+gss_test_oid_set_member(OM_uint32 * minor_status, gss_OID member,
+ gss_OID_set set, int * present);
+
+OM_uint32
+gss_verify_mic(OM_uint32 * minor_status, gss_ctx_id_t context_handle,
+ gss_buffer_t message_buffer, gss_buffer_t message_token,
+ gss_qop_t * qop_state);
+
+extern gss_OID GSS_C_NT_HOSTBASED_SERVICE;
\ No newline at end of file
diff --git a/gss-serv-sspi.c b/gss-serv-sspi.c
new file mode 100644
index 0000000..bdd67cb
--- /dev/null
+++ b/gss-serv-sspi.c
@@ -0,0 +1,1155 @@
+/*
+ * Author: Bryan Berns <berns@uwalumni.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#ifdef GSSAPI
+#ifdef SSPI
+
+#define WIN32
+
+#define OPENSSL_SYS_WIN32
+#define _countof(array) (sizeof(array) / sizeof(array[0]))
+#define _strdup strdup
+
+#define _stricmp strcasecmp
+#define _wcsnicmp wcsncasecmp
+
+#include <windows.h>
+#include <winsock2.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <wchar.h>
+#include <time.h>
+#include <pwd.h>
+
+#include "contrib/win32/win32compat/debug.h"
+#include "contrib/win32/win32compat/inc/gssapi.h"
+
+ /*
+ * This file provides the GSSAPI interface to support Kerberos SSPI within
+ * OpenSSH. This is only a partial definition of the full GSSAPI specification
+ * since OpenSSH only requires a subset of the overall functionality.
+ *
+ * The function definitions as well as the accompanying comments are derived
+ * from information provided in RFC2744. In addition, RFC2743 provides
+ * additional information on the GSSAPI specification and intended operation.
+ */
+
+/*
+ * Include the definitions necessary to implement some of the interface
+ * structure that are required for gss-serv.c to perform Kerberos operations.
+ */
+#include "buffer.h"
+#undef HAVE_GSSAPI_H
+#undef HAVE_GSSAPI_GSSAPI_H
+#undef HAVE_GSSAPI_GENERIC_H
+#undef HAVE_GSSAPI_GSSAPI_GENERIC_H
+#include "ssh-gss.h"
+
+/*on error returns NULL and sets errno*/
+static wchar_t *
+utf8_to_utf16(const char *utf8)
+{
+ int needed = 0;
+ wchar_t* utf16 = NULL;
+ if ((needed = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0)) == 0 ||
+ (utf16 = malloc(needed * sizeof(wchar_t))) == NULL ||
+ MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, needed) == 0) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ return utf16;
+}
+
+static char *
+utf16_to_utf8(const wchar_t* utf16)
+{
+ int needed = 0;
+ char* utf8 = NULL;
+ if ((needed = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, NULL, NULL)) == 0 ||
+ (utf8 = malloc(needed)) == NULL ||
+ WideCharToMultiByte(CP_UTF8, 0, utf16, -1, utf8, needed, NULL, NULL) == 0)
+ return NULL;
+
+ return utf8;
+}
+
+/*
+ * This will be initialized to a function table that contains pointers to
+ * all standard security functions. The reason for using this instead of
+ * relying on the standard imports is because the OneCore libraries do
+ * not expose all the functions we need.
+ */
+PSecurityFunctionTableW SecFunctions = NULL;
+
+/*
+ * GSS_C_NT_HOSTBASED_SERVICE is a oid value that is used to negotiate a
+ * a Kerberos transaction using an SPN in the format host@user@realm format.
+ */
+#define GSS_C_NT_HOSTBASED_SERVICE_STR "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"
+gss_OID GSS_C_NT_HOSTBASED_SERVICE = &(gss_OID_desc)
+{
+ sizeof(GSS_C_NT_HOSTBASED_SERVICE_STR) - 1,
+ (void *) GSS_C_NT_HOSTBASED_SERVICE_STR
+};
+
+/*
+ * This handle is used to relay the handle for the user to functions that
+ * ultimately call CreateProcessAsUser to spawn the user shell.
+ */
+HANDLE sspi_auth_user = 0;
+
+struct cred_st {
+ int isToken;
+ union {
+ HANDLE token;
+ CredHandle credHandle;
+ };
+};
+
+/*
+ * This is called before each gssapi implementation function to ensure the
+ * environment is initialized properly. Any additional implementation setup
+ * should be added to this function.
+ */
+static int
+ssh_gss_sspi_init(OM_uint32 * minor_status)
+{
+ /* minor status never used - reset to zero*/
+ *minor_status = 0;
+
+ /* already initialized; return */
+ if (SecFunctions != NULL)
+ return 1;
+
+ /* get a pointer to a function table containing all the function pointers */
+ if ((SecFunctions = InitSecurityInterfaceW()) == NULL) {
+ /* failure */
+ debug("failed to acquire function table for sspi support.");
+ return 0;
+ }
+
+ /* success */
+ return 1;
+}
+
+/*
+ * Allows an application to determine which underlying security mechanisms are
+ * available.
+ */
+OM_uint32
+gss_indicate_mechs(OM_uint32 * minor_status, gss_OID_set *mech_set)
+{
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ return GSS_S_FAILURE;
+
+ /* create an list that contains the one oid that we support */
+ if (gss_create_empty_oid_set(minor_status, mech_set) != GSS_S_COMPLETE)
+ return GSS_S_FAILURE;
+
+ if (gss_add_oid_set_member(minor_status, GSS_C_NT_HOSTBASED_SERVICE, mech_set) != GSS_S_COMPLETE) {
+ gss_release_oid_set(minor_status, mech_set);
+ return GSS_S_FAILURE;
+ }
+
+ return GSS_S_COMPLETE;
+}
+
+/*
+ * Create an object-identifier set containing no object identifiers, to which
+ * members may be subsequently added using the gss_add_oid_set_member() routine.
+ * These routines are intended to be used to construct sets of mechanism object
+ * identifiers, for input to gss_acquire_cred.
+ */
+OM_uint32
+gss_create_empty_oid_set(OM_uint32 * minor_status, gss_OID_set * oid_set)
+{
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ return GSS_S_FAILURE;
+
+ /* allocate / initialize space for this new oid set */
+ if (((*oid_set) = calloc(1, sizeof(gss_OID_set_desc))) == NULL)
+ return GSS_S_FAILURE;
+
+ return GSS_S_COMPLETE;
+}
+
+/*
+ * Free storage associated with a GSSAPI-generated gss_OID_set object. The set
+ * parameter must refer to an OID-set that was returned from a GSS-API routine.
+ * gss_release_oid_set() will free the storage associated with each individual
+ * member OID, the OID set's elements array, and the gss_OID_set_desc.
+ */
+OM_uint32
+gss_release_oid_set(OM_uint32 * minor_status, gss_OID_set * set)
+{
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ return GSS_S_FAILURE;
+
+ /* free all individual oid strings */
+ for (size_t oid_num = 0; oid_num < (*set)->count; oid_num++)
+ free((*set)->elements[oid_num].elements);
+
+ /* free overall oid set */
+ free((*set)->elements);
+ free(*set);
+
+ return GSS_S_COMPLETE;
+}
+
+/*
+ * Add an Object Identifier to an Object Identifier set. This routine is
+ * intended for use in conjunction with gss_create_empty_oid_set when
+ * constructing a set of mechanism OIDs for input to gss_acquire_cred. The
+ * oid_set parameter must refer to an OID-set that was created by GSS-API (e.g.
+ * a set returned by gss_create_empty_oid_set()). GSS-API creates a copy of the
+ * member_oid and inserts this copy into the set, expanding the storage
+ * allocated to the OID-set's elements array if necessary. The routine may add
+ * the new member OID anywhere within the elements array, and implementations
+ * should verify that the new member_oid is not already contained within the
+ * elements array; if the member_oid is already present, the oid_set should
+ * remain unchanged.
+ */
+OM_uint32
+gss_add_oid_set_member(OM_uint32 * minor_status, gss_OID member_oid, gss_OID_set * oid_set)
+{
+ OM_uint32 ret = GSS_S_FAILURE;
+ void * member_oid_elements = NULL;
+
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ return GSS_S_FAILURE;
+
+ /* create our own copy of the oid entry itself to add to the set */
+ if ((member_oid_elements = malloc(member_oid->length)) == NULL)
+ goto cleanup;
+ memcpy(member_oid_elements, member_oid->elements, member_oid->length);
+
+ /* reallocate the new elements structure based on the increased size */
+ const size_t current_count = (*oid_set)->count;
+ (*oid_set)->elements = realloc((*oid_set)->elements, (current_count + 1) * sizeof(gss_OID_desc));
+ if ((*oid_set)->elements == NULL)
+ goto cleanup;
+
+ /* append the new oid to the end of the recently increased list */
+ (*oid_set)->elements[current_count].elements = member_oid_elements;
+ (*oid_set)->elements[current_count].length = member_oid->length;
+ (*oid_set)->count++;
+
+ member_oid_elements = NULL;
+ ret = GSS_S_COMPLETE;
+cleanup:
+ if (member_oid_elements)
+ free(member_oid_elements);
+
+ return ret;
+}
+
+/*
+ * Interrogate an Object Identifier set to determine whether a specified Object
+ * Identifier is a member. This routine is intended to be used with OID sets
+ * returned by gss_indicate_mechs(), gss_acquire_cred(), and gss_inquire_cred(),
+ * but will also work with user-generated sets.
+ */
+OM_uint32
+gss_test_oid_set_member(OM_uint32 * minor_status, gss_OID member,
+ gss_OID_set set, int * present)
+{
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ return GSS_S_FAILURE;
+
+ /* loop through each oid in the passed set */
+ for (size_t oid_num = 0; oid_num < set->count; oid_num++) {
+ /* do not bother doing memory comparison if sizes do not match */
+ if (set->elements[oid_num].length != member->length)
+ continue;
+
+ /* compare the binary storage of the test oid to the one in our list */
+ if (memcmp(set->elements[oid_num].elements, member->elements, member->length) == 0) {
+ /* match found */
+ *present = TRUE;
+ return GSS_S_COMPLETE;
+ }
+ }
+
+ /* no match found in the list */
+ *present = FALSE;
+ return GSS_S_COMPLETE;
+}
+
+/*
+ * Convert a contiguous string name to internal form. In general, the internal
+ * name returned (via the <output_name> parameter) will not be an MN; the
+ * exception to this is if the <input_name_type> indicates that the contiguous
+ * string provided via the <input_name_buffer> parameter is of type
+ * GSS_C_NT_EXPORT_NAME, in which case the returned internal name will be an MN
+ * for the mechanism that exported the name.
+ */
+OM_uint32
+gss_import_name(OM_uint32 * minor_status, gss_buffer_t input_name_buffer,
+ gss_OID input_name_type, gss_name_t * output_name)
+{
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ return GSS_S_FAILURE;
+
+ /* make sure we support the passed type */
+ if (input_name_type->length != GSS_C_NT_HOSTBASED_SERVICE->length ||
+ memcmp(input_name_type->elements, GSS_C_NT_HOSTBASED_SERVICE->elements, input_name_type->length) != 0)
+ return GSS_S_BAD_NAMETYPE;
+
+ /* there is nothing special we have to do for this type so just duplicate
+ the */
+ (*output_name) = _strdup(input_name_buffer->value);
+
+ if (output_name == NULL)
+ return GSS_S_FAILURE;
+
+ return GSS_S_COMPLETE;
+}
+
+/*
+ * Free GSSAPI-allocated storage associated with an internal-form name.
+ * Implementations are encouraged to set the name to GSS_C_NO_NAME on successful
+ * completion of this call.
+ */
+OM_uint32
+gss_release_name(OM_uint32 * minor_status, gss_name_t * input_name)
+{
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ return GSS_S_FAILURE;
+
+ /* validate input */
+ if (input_name == NULL || *input_name == NULL)
+ return GSS_S_BAD_NAME;
+
+ /* deallocate memory associated with the name */
+ free(*input_name);
+ *input_name = GSS_C_NO_NAME;
+
+ return GSS_S_COMPLETE;
+}
+
+/*
+ * To produce a canonical contiguous string representation of a mechanism name
+ * (MN), suitable for direct comparison (e.g. with memcmp) for use in
+ * authorization functions (e.g. matching entries in an access-control list).
+ * The <input_name> parameter must specify a or by gss_canonicalize_name).
+ */
+OM_uint32
+gss_export_name(OM_uint32 * minor_status, const gss_name_t input_name,
+ gss_buffer_t exported_name)
+{
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ return GSS_S_FAILURE;
+
+ /* convenience pointer to shorten the void */
+ const gss_OID_desc* const ntoid = GSS_C_NT_HOSTBASED_SERVICE;
+
+ /* make sure we support the passed type */
+ if (strstr(input_name, "host@") == input_name)
+ return GSS_S_BAD_NAMETYPE;
+
+ /* get the lengths of all the parts of the string */
+ /* note: assumes short format for encoding oid length (i.e. less than 128)
+ */
+ const uint16_t token_id = 0x0401;
+ const uint8_t oid_tag = 0x06;
+ const uint8_t oid_len = (uint8_t) ntoid->length;
+ const uint16_t oid_outer_len = sizeof(oid_tag) + sizeof(oid_len) + oid_len;
+ const uint32_t name_len = (uint16_t) strlen(input_name);
+
+ /* allocate space for the exported name */
+ exported_name->length = sizeof(token_id) + sizeof(oid_outer_len) + oid_outer_len + sizeof(name_len) + name_len;
+ exported_name->value = malloc(exported_name->length);
+ if (exported_name->value == NULL)
+ return GSS_S_FAILURE;
+
+ /* get big-endian values so we can just do a direct memcpy from the values
+ */
+ const uint16_t token_id_be = htons(token_id);
+ const uint16_t oid_outer_len_be = htons(oid_outer_len);
+ const uint32_t name_len_be = htonl(name_len);
+
+ /* construct the encoded value */
+ uint8_t * output = exported_name->value;
+ memcpy(output, &token_id_be, sizeof(token_id_be)); output += sizeof(token_id_be);
+ memcpy(output, &oid_outer_len_be, sizeof(oid_outer_len_be)); output += sizeof(oid_outer_len_be);
+ memcpy(output, &oid_tag, sizeof(oid_tag)); output += sizeof(oid_tag);
+ memcpy(output, &oid_len, sizeof(oid_len)); output += sizeof(oid_len);
+ memcpy(output, ntoid->elements, ntoid->length); output += ntoid->length;
+ memcpy(output, &name_len_be, sizeof(name_len_be)); output += sizeof(name_len_be);
+ memcpy(output, input_name, name_len);
+
+ return GSS_S_COMPLETE;
+}
+
+/*
+ * Free storage associated with a buffer. The storage must have been allocated
+ * by a GSS-API routine. In addition to freeing the associated storage, the
+ * routine will zero the length field in the descriptor to which the buffer
+ * parameter refers, and implementations are encouraged to additionally set the
+ * pointer field in the descriptor to NULL. Any buffer object returned by a
+ * GSS-API routine may be passed to gss_release_buffer (even if there is no
+ * storage associated with the buffer).
+ */
+OM_uint32
+gss_release_buffer(OM_uint32 * minor_status, gss_buffer_t buffer)
+{
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ return GSS_S_FAILURE;
+
+ /* deallocate the buffer associated with the buffer */
+ free(buffer->value);
+ buffer->length = 0;
+ buffer->value = NULL;
+
+ return GSS_S_COMPLETE;
+}
+
+/*
+ * Allows an application to acquire a handle for a pre-existing credential by
+ * name. GSS-API implementations must impose a local access-control policy on
+ * callers of this routine to prevent unauthorized callers from acquiring
+ * credentials to which they are not entitled. This routine is not intended to
+ * provide a "login to the network" function, as such a function would involve
+ * the creation of new credentials rather than merely acquiring a handle to
+ * existing credentials. Such functions, if required, should be defined in
+ * implementation-specific extensions to the API.
+ */
+OM_uint32
+gss_acquire_cred(OM_uint32 *minor_status, gss_name_t desired_name,
+ OM_uint32 time_req, gss_OID_set desired_mechs, gss_cred_usage_t cred_usage,
+ gss_cred_id_t * output_cred_handle, gss_OID_set *actual_mechs, OM_uint32 *time_rec)
+{
+ OM_uint32 ret = GSS_S_FAILURE;
+ SYSTEMTIME current_time_system;
+ wchar_t * desired_name_utf16 = NULL;
+ CredHandle cred_handle, *p_cred_handle = NULL;
+
+
+ if (output_cred_handle != NULL)
+ *output_cred_handle = NULL;
+
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ goto done;
+
+ /* get the current time so we can determine expiration if requested */
+ GetSystemTime(&current_time_system);
+
+ /* translate credential usage parameters */
+ ULONG cred_usage_local = 0;
+ if (cred_usage == GSS_C_ACCEPT) cred_usage_local = SECPKG_CRED_INBOUND;
+ else if (cred_usage == GSS_C_INITIATE) cred_usage_local = SECPKG_CRED_OUTBOUND;
+ else if (cred_usage == GSS_C_BOTH) cred_usage_local = SECPKG_CRED_BOTH;
+
+ /* convert input name to unicode so we can process usernames with special characters */
+ if ((desired_name_utf16 = utf8_to_utf16(desired_name)) == NULL)
+ goto done;
+
+ /* acquire a handle to existing credentials -- in many cases the name will
+ * be null in which case the credentials of the current user are used */
+ TimeStamp expiry;
+ SECURITY_STATUS status = SecFunctions->AcquireCredentialsHandleW(desired_name_utf16, MICROSOFT_KERBEROS_NAME_W, cred_usage_local,
+ NULL, NULL, NULL, NULL, &cred_handle, &expiry);
+
+ /* fail immediately if errors occurred */
+ if (status != SEC_E_OK)
+ goto done;
+
+ p_cred_handle = &cred_handle;
+ /* copy credential data out of local buffer */
+ if (output_cred_handle != NULL) {
+ if ((*output_cred_handle = malloc(sizeof(struct cred_st))) == NULL)
+ goto done;
+ (*output_cred_handle)->isToken = 0;
+ (*output_cred_handle)->credHandle = cred_handle;
+ }
+
+ /* determine expiration if requested */
+ if (time_rec != NULL) {
+ FILETIME current_time;
+ if (SystemTimeToFileTime(&current_time_system, &current_time) != 0)
+ *time_rec = (OM_uint32)(expiry.QuadPart - ((PLARGE_INTEGER)&current_time)->QuadPart) / 10000;
+ else
+ error("SystemTimeToFileTime failed with %lu", GetLastError());
+ }
+
+ /* set actual supported mechs if requested */
+ if (actual_mechs != NULL && gss_indicate_mechs(minor_status, actual_mechs) != GSS_S_COMPLETE)
+ goto done;
+
+ ret = GSS_S_COMPLETE;
+done:
+ if (desired_name_utf16)
+ free(desired_name_utf16);
+ if (ret != GSS_S_COMPLETE) {
+ if (p_cred_handle)
+ SecFunctions->FreeCredentialsHandle(p_cred_handle);
+ if (output_cred_handle && *output_cred_handle) {
+ free(*output_cred_handle);
+ *output_cred_handle = NULL;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Initiates the establishment of a security context between the application and
+ * a remote peer. Initially, the input_token parameter should be specified
+ * either as GSS_C_NO_BUFFER, or as a pointer to a gss_buffer_desc object whose
+ * length field contains the value zero. The routine may return a output_token
+ * which should be transferred to the peer application, where the peer
+ * application will present it to gss_accept_sec_context.
+ */
+OM_uint32
+gss_init_sec_context(
+ OM_uint32 * minor_status, gss_cred_id_t claimant_cred_handle, gss_ctx_id_t * context_handle,
+ gss_name_t target_name, gss_OID mech_type, OM_uint32 req_flags, OM_uint32 time_req, gss_channel_bindings_t input_chan_bindings,
+ gss_buffer_t input_token, gss_OID * actual_mech_type, gss_buffer_t output_token, OM_uint32 * ret_flags,
+ OM_uint32 * time_rec)
+{
+ OM_uint32 ret = GSS_S_FAILURE;
+ wchar_t * target_name_utf16 = NULL;
+ gss_ctx_id_t p_ctx_h = NULL;
+
+ output_token->value = NULL;
+
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ goto done;
+
+ /* make sure we support the passed type */
+ if (mech_type->length != GSS_C_NT_HOSTBASED_SERVICE->length ||
+ memcmp(mech_type->elements, GSS_C_NT_HOSTBASED_SERVICE->elements, mech_type->length) != 0) {
+ ret = GSS_S_BAD_NAMETYPE;
+ goto done;
+ }
+
+ unsigned long sspi_req_flags = ISC_REQ_ALLOCATE_MEMORY;
+ if (req_flags & GSS_C_MUTUAL_FLAG)
+ sspi_req_flags |= ISC_REQ_MUTUAL_AUTH;
+ if (req_flags & GSS_C_CONF_FLAG)
+ sspi_req_flags |= ISC_REQ_CONFIDENTIALITY;
+ if (req_flags & GSS_C_REPLAY_FLAG)
+ sspi_req_flags |= ISC_REQ_REPLAY_DETECT;
+ if (req_flags & GSS_C_DELEG_FLAG)
+ sspi_req_flags |= ISC_REQ_DELEGATE;
+ if (req_flags & GSS_C_INTEG_FLAG)
+ sspi_req_flags |= ISC_REQ_INTEGRITY;
+ if (req_flags & GSS_C_SEQUENCE_FLAG)
+ sspi_req_flags |= ISC_REQ_SEQUENCE_DETECT;
+
+ /* determine if this is the first call (no input buffer available) */
+ gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER;
+ const int no_input_buffer = (input_token == GSS_C_NO_BUFFER) || memcmp(input_token, &empty_buffer, sizeof(gss_buffer_desc)) == 0;
+
+ /* setup input buffer */
+ SecBuffer input_buffer_token = { (no_input_buffer) ? 0 : (unsigned long) input_token->length, SECBUFFER_TOKEN, (no_input_buffer) ? NULL : input_token->value };
+ SecBufferDesc input_buffer = { SECBUFFER_VERSION, 1, &input_buffer_token };
+
+ /* setup output buffer - will be dynamically allocated by function */
+ SecBuffer output_buffer_token = { 0, SECBUFFER_TOKEN, NULL };
+ SecBufferDesc output_buffer = { SECBUFFER_VERSION, 1, &output_buffer_token };
+
+ /* get the current time so we can determine expiration if requested */
+ SYSTEMTIME current_time_system;
+ GetSystemTime(&current_time_system);
+
+ /* acquire default cred handler if none specified */
+ CredHandle *pCredHandle = NULL;
+ if (claimant_cred_handle != NULL)
+ pCredHandle = &(claimant_cred_handle->credHandle);
+
+ if (pCredHandle == NULL) {
+ static CredHandle cred_handle = { 0, 0 };
+ pCredHandle = &cred_handle;
+ if (cred_handle.dwLower == 0 && cred_handle.dwUpper == 0) {
+ TimeStamp expiry_cred;
+ if (SecFunctions->AcquireCredentialsHandleW(NULL, MICROSOFT_KERBEROS_NAME_W, SECPKG_CRED_OUTBOUND,
+ NULL, NULL, NULL, NULL, &cred_handle, &expiry_cred) != SEC_E_OK)
+ goto done;
+ }
+ }
+
+ /* condition the string for windows */
+ if ((target_name_utf16 = utf8_to_utf16(target_name)) == NULL)
+ goto done;
+
+ if (wcsncmp(target_name_utf16, L"host@", wcslen(L"host@")) == 0)
+ *wcschr(target_name_utf16, L'@') = L'/';
+
+ TimeStamp expiry;
+ LONG sspi_ret_flags = 0;
+ CtxtHandle out_context;
+
+ const SECURITY_STATUS status = SecFunctions->InitializeSecurityContextW(pCredHandle,
+ (*context_handle == GSS_C_NO_CONTEXT) ? NULL : *context_handle,
+ target_name_utf16, sspi_req_flags, 0, SECURITY_NATIVE_DREP, (no_input_buffer) ? NULL : &input_buffer,
+ 0, (*context_handle != NULL) ? NULL : &out_context, &output_buffer, &sspi_ret_flags, (time_rec == NULL) ? NULL : &expiry);
+
+ /* check if error occurred */
+ if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED)
+ goto done;
+
+ /* copy output token to output buffer */
+ output_token->length = output_buffer_token.cbBuffer;
+ if ((output_token->value = malloc(output_token->length)) == NULL)
+ goto done;
+
+ memcpy(output_token->value, output_buffer_token.pvBuffer, output_token->length);
+ SecFunctions->FreeContextBuffer(output_buffer_token.pvBuffer);
+
+ /* if requested, translate returned flags that are actually available */
+ if (ret_flags != NULL) {
+ *ret_flags = 0;
+ if (sspi_ret_flags & ISC_RET_MUTUAL_AUTH)
+ *ret_flags |= GSS_C_MUTUAL_FLAG;
+ if (sspi_ret_flags & ISC_RET_CONFIDENTIALITY)
+ *ret_flags |= GSS_C_CONF_FLAG;
+ if (sspi_ret_flags & ISC_RET_REPLAY_DETECT)
+ *ret_flags |= GSS_C_REPLAY_FLAG;
+ if (sspi_ret_flags & ISC_RET_DELEGATE)
+ *ret_flags |= GSS_C_DELEG_FLAG;
+ if (sspi_ret_flags & ISC_RET_INTEGRITY)
+ *ret_flags |= GSS_C_INTEG_FLAG;
+ if (sspi_ret_flags & ISC_RET_SEQUENCE_DETECT)
+ *ret_flags |= GSS_C_SEQUENCE_FLAG;
+ }
+
+ /* report if delegation was requested by not fulfilled */
+ if ((sspi_req_flags & ISC_REQ_DELEGATE) != 0 && (sspi_ret_flags & ISC_RET_DELEGATE) == 0)
+ debug("sspi delegation was requested but not fulfilled");
+
+ /* if requested, translate the expiration time to number of second */
+ if (time_rec != NULL) {
+ FILETIME current_time;
+ if (SystemTimeToFileTime(&current_time_system, &current_time) != 0)
+ *time_rec = (OM_uint32)(expiry.QuadPart - ((PLARGE_INTEGER)&current_time)->QuadPart) / 10000;
+ else
+ error("SystemTimeToFileTime failed with %lu", GetLastError());
+ }
+
+ /* if requested, return the supported mechanism oid */
+ if (actual_mech_type != NULL)
+ *actual_mech_type = GSS_C_NT_HOSTBASED_SERVICE;
+
+ /* copy the credential context structure to the caller */
+ if (*context_handle == GSS_C_NO_CONTEXT) {
+ if ((p_ctx_h = malloc(sizeof(out_context))) == NULL)
+ goto done;
+ *context_handle = p_ctx_h;
+ memcpy(*context_handle, &out_context, sizeof(out_context));
+ }
+
+ ret = (status == SEC_I_CONTINUE_NEEDED) ? GSS_S_CONTINUE_NEEDED : GSS_S_COMPLETE;
+done:
+ if (target_name_utf16)
+ free(target_name_utf16);
+
+ if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
+ if (output_token->value) {
+ free(output_token->value);
+ output_token->value = NULL;
+ }
+ if (p_ctx_h)
+ free(p_ctx_h);
+
+ }
+
+ return ret;
+}
+
+/*
+ * Informs GSS-API that the specified credential handle is no longer required by
+ * the application, and frees associated resources. Implementations are
+ * encouraged to set the cred_handle to GSS_C_NO_CREDENTIAL on successful
+ * completion of this call.
+ */
+OM_uint32
+gss_release_cred(OM_uint32 * minor_status, gss_cred_id_t * cred_handle)
+{
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ return GSS_S_FAILURE;
+
+ if (*cred_handle != GSS_C_NO_CREDENTIAL) {
+ if ((*cred_handle)->isToken) {
+ CloseHandle((*cred_handle)->token);
+ if ((*cred_handle)->token == sspi_auth_user)
+ sspi_auth_user = 0;
+ }
+ else
+ SecFunctions->FreeCredentialsHandle(&(*cred_handle)->credHandle);
+ free(*cred_handle);
+ *cred_handle = GSS_C_NO_CREDENTIAL;
+ }
+
+ return GSS_S_COMPLETE;
+}
+
+/*
+ * Delete a security context. gss_delete_sec_context will delete the local data
+ * structures associated with the specified security context, and may generate
+ * an output_token, which when passed to the peer gss_process_context_token will
+ * instruct it to do likewise. If no token is required by the mechanism, the
+ * GSS-API should set the length field of the output_token (if provided) to
+ * zero. No further security services may be obtained using the context
+ * specified by context_handle.
+ */
+OM_uint32
+gss_delete_sec_context(OM_uint32 * minor_status, gss_ctx_id_t * context_handle,
+ gss_buffer_t output_token)
+{
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ return GSS_S_FAILURE;
+
+ /* input sanity checks */
+ if (context_handle == NULL)
+ return GSS_S_NO_CONTEXT;
+
+ if (output_token != GSS_C_NO_BUFFER) {
+ free(output_token->value);
+ output_token->value = NULL;
+ output_token->length = 0;
+ }
+
+ /* cleanup security context */
+ SecFunctions->DeleteSecurityContext(*context_handle);
+ free(*context_handle);
+ *context_handle = GSS_C_NO_CONTEXT;
+
+ return GSS_S_COMPLETE;
+}
+
+/*
+ * Verifies that a cryptographic MIC, contained in the token parameter, fits the
+ * supplied message. The qop_state parameter allows a message recipient to
+ * determine the strength of protection that was applied to the message.
+ */
+OM_uint32
+gss_verify_mic(OM_uint32 * minor_status, gss_ctx_id_t context_handle,
+ gss_buffer_t message_buffer, gss_buffer_t message_token, gss_qop_t * qop_state)
+{
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ return GSS_S_FAILURE;
+
+ /* translate the message and token to a security buffer so we can verify it */
+ SecBuffer verify_buffer_set[] = {
+ { (unsigned long) message_buffer->length, SECBUFFER_DATA, message_buffer->value },
+ { (unsigned long) message_token->length, SECBUFFER_TOKEN, message_token->value } };
+ SecBufferDesc verify_buffer = { SECBUFFER_VERSION, _countof(verify_buffer_set), verify_buffer_set };
+
+ /* verify message and signature */
+ ULONG qop;
+ const SECURITY_STATUS status = SecFunctions->VerifySignature(context_handle, &verify_buffer, 0, &qop);
+
+ /* translate error codes */
+ OM_uint32 return_code = GSS_S_COMPLETE;
+ if (status != SEC_E_OK) {
+ /* translate specific error */
+ if (status == SEC_E_MESSAGE_ALTERED) return_code = GSS_S_BAD_SIG;
+ else if (status == SEC_E_OUT_OF_SEQUENCE) return_code = GSS_S_UNSEQ_TOKEN;
+ else if (status == SEC_E_INVALID_TOKEN) return_code = GSS_S_DEFECTIVE_TOKEN;
+ else if (status == SEC_E_CONTEXT_EXPIRED) return_code = GSS_S_CONTEXT_EXPIRED;
+ else if (status == SEC_E_QOP_NOT_SUPPORTED) return_code = GSS_S_BAD_QOP;
+ else return_code = GSS_S_FAILURE;
+ }
+
+ if (qop_state != NULL)
+ *qop_state = (OM_uint32) GSS_C_QOP_DEFAULT;
+
+ return return_code;
+}
+
+/*
+ * Generates a cryptographic MIC for the supplied message, and places the MIC in
+ * a token for transfer to the peer application. The qop_req parameter allows a
+ * choice between several cryptographic algorithms, if supported by the chosen
+ * mechanism.
+ */
+OM_uint32
+gss_get_mic(OM_uint32 * minor_status, gss_ctx_id_t context_handle,
+ gss_qop_t qop_req, gss_buffer_t message_buffer, gss_buffer_t message_token)
+{
+ OM_uint32 ret = GSS_S_FAILURE;
+
+ message_token->value = NULL;
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ goto done;
+
+ /* determine the max possible signature and allocate memory to support it */
+ SecPkgContext_Sizes sizes;
+ if (SecFunctions->QueryContextAttributesW(context_handle, SECPKG_ATTR_SIZES, &sizes) != SEC_E_OK)
+ goto done;
+ if ((message_token->value = malloc(sizes.cbMaxSignature)) == NULL)
+ goto done;
+
+ message_token->length = sizes.cbMaxSignature;
+
+ /* translate the message and token to a security buffer so we can sign it */
+ SecBuffer sign_buffer_set[] = {
+ { (unsigned long) message_buffer->length, SECBUFFER_DATA, message_buffer->value },
+ { (unsigned long) message_token->length, SECBUFFER_TOKEN, message_token->value } };
+ SecBufferDesc sign_buffer = { SECBUFFER_VERSION, _countof(sign_buffer_set), sign_buffer_set };
+
+ /* attempt to sign the data */
+ ULONG qop = 0;
+ const SECURITY_STATUS status = SecFunctions->MakeSignature(context_handle, qop, &sign_buffer, 0);
+
+ /* translate error codes */
+ if (status != SEC_E_OK) {
+ if (status == SEC_E_CONTEXT_EXPIRED)
+ ret = GSS_S_CONTEXT_EXPIRED;
+ else if (status == SEC_E_QOP_NOT_SUPPORTED)
+ ret = GSS_S_BAD_QOP;
+ goto done;
+ }
+
+ ret = GSS_S_COMPLETE;
+
+done:
+ if (ret != GSS_S_COMPLETE) {
+ if (message_token->value) {
+ free(message_token->value);
+ message_token->value = NULL;
+ }
+ }
+ return ret;
+}
+
+/*
+ * Allows a remotely initiated security context between the application and a
+ * remote peer to be established. The routine may return a output_token which
+ * should be transferred to the peer application, where the peer application
+ * will present it to gss_init_sec_context. If no token need be sent,
+ * gss_accept_sec_context will indicate this by setting the length field of the
+ * output_token argument to zero. To complete the context establishment, one or
+ * more reply tokens may be required from the peer application; if so,
+ * gss_accept_sec_context will return a status flag of GSS_S_CONTINUE_NEEDED, in
+ * which case it should be called again when the reply token is received from
+ * the peer application, passing the token to gss_accept_sec_context via the
+ * input_token parameters.
+ */
+OM_uint32
+gss_accept_sec_context(OM_uint32 * minor_status, gss_ctx_id_t * context_handle,
+ gss_cred_id_t acceptor_cred_handle, gss_buffer_t input_token_buffer, gss_channel_bindings_t input_chan_bindings,
+ gss_name_t * src_name, gss_OID * mech_type, gss_buffer_t output_token,
+ OM_uint32 * ret_flags, OM_uint32 * time_rec, gss_cred_id_t * delegated_cred_handle)
+{
+ OM_uint32 ret = GSS_S_FAILURE;
+ gss_ctx_id_t p_ctx_h = NULL;
+
+ *src_name = NULL;
+
+ if (delegated_cred_handle != NULL)
+ *delegated_cred_handle = NULL;
+
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ goto done;
+
+ /* setup input buffer */
+ SecBuffer input_buffer_token = { (unsigned long) input_token_buffer->length,
+ SECBUFFER_TOKEN | SECBUFFER_READONLY, input_token_buffer->value };
+ SecBufferDesc input_buffer = { SECBUFFER_VERSION, 1, &input_buffer_token };
+
+ /* setup output buffer - will be dynamically allocated by function */
+ SecBuffer output_buffer_token = { 0, SECBUFFER_TOKEN, NULL };
+ SecBufferDesc output_buffer = { SECBUFFER_VERSION, 1, &output_buffer_token };
+
+ /* get the current time so we can determine expiration if requested */
+ SYSTEMTIME current_time_system;
+ GetSystemTime(&current_time_system);
+
+ TimeStamp expiry;
+ CtxtHandle sspi_context_handle;
+ ULONG sspi_ret_flags = 0;
+ ULONG sspi_req_flags = ASC_REQ_CONFIDENTIALITY | ASC_REQ_MUTUAL_AUTH | ASC_REQ_INTEGRITY |
+ ASC_REQ_DELEGATE | ASC_REQ_SEQUENCE_DETECT | ASC_REQ_ALLOCATE_MEMORY;
+
+ /* call sspi accept security context function */
+ const SECURITY_STATUS status = SecFunctions->AcceptSecurityContext(&acceptor_cred_handle->credHandle,
+ (*context_handle == GSS_C_NO_CONTEXT) ? NULL : *context_handle, &input_buffer,
+ sspi_req_flags, SECURITY_NATIVE_DREP,
+ (*context_handle == GSS_C_NO_CONTEXT) ? &sspi_context_handle : *context_handle,
+ &output_buffer, &sspi_ret_flags, &expiry);
+
+ /* translate error codes */
+ if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
+ if (status == SEC_E_INVALID_TOKEN)
+ ret = GSS_S_DEFECTIVE_TOKEN;
+ else if (status == SEC_E_INVALID_HANDLE)
+ ret = GSS_S_NO_CONTEXT;
+ goto done;
+ }
+
+ /* only do checks on the finalized context (no continue needed) */
+ if (status == SEC_E_OK) {
+ /* validate accepted context is actually a host service ticket */
+ SecPkgContext_NativeNamesW target;
+ if (SecFunctions->QueryContextAttributesW((*context_handle == GSS_C_NO_CONTEXT) ? &sspi_context_handle : *context_handle,
+ SECPKG_ATTR_NATIVE_NAMES, &target) != SEC_E_OK)
+ goto done;
+
+ const int valid_spn = _wcsnicmp(target.sServerName, L"host/", wcslen(L"host/")) == 0;
+ FreeContextBuffer(target.sServerName);
+ FreeContextBuffer(target.sClientName);
+ if (valid_spn == 0) {
+ debug("client passed an invalid principal name");
+ ret = GSS_S_FAILURE;
+ goto done;
+ }
+ }
+
+ /* copy the context handler to the caller */
+ if (*context_handle == GSS_C_NO_CONTEXT) {
+ if ((p_ctx_h = malloc(sizeof(CtxtHandle))) == NULL)
+ goto done;
+ *context_handle = p_ctx_h;
+ memcpy(*context_handle, &sspi_context_handle, sizeof(CtxtHandle));
+ }
+
+ /* if requested, translate returned flags that are actually available */
+ if (ret_flags != NULL) {
+ *ret_flags = 0;
+ if (sspi_ret_flags & ASC_RET_MUTUAL_AUTH)
+ *ret_flags |= GSS_C_MUTUAL_FLAG;
+ if (sspi_ret_flags & ASC_RET_CONFIDENTIALITY)
+ *ret_flags |= GSS_C_CONF_FLAG;
+ if (sspi_ret_flags & ASC_RET_REPLAY_DETECT)
+ *ret_flags |= GSS_C_REPLAY_FLAG;
+ if (sspi_ret_flags & ASC_RET_DELEGATE)
+ *ret_flags |= GSS_C_DELEG_FLAG;
+ if (sspi_ret_flags & ASC_RET_INTEGRITY)
+ *ret_flags |= GSS_C_INTEG_FLAG;
+ if (sspi_ret_flags & ASC_RET_SEQUENCE_DETECT)
+ *ret_flags |= GSS_C_SEQUENCE_FLAG;
+ }
+
+ /* report if delegation was requested by not fulfilled */
+ if ((sspi_req_flags & ASC_REQ_DELEGATE) != 0 && (sspi_ret_flags & ASC_RET_DELEGATE) == 0)
+ debug("%s: delegation was requested but not fulfilled", __FUNCTION__);
+
+ /* if provided, specify the mechanism */
+ if (mech_type != NULL)
+ *mech_type = GSS_C_NT_HOSTBASED_SERVICE;
+
+ /* if requested, translate the expiration time to number of second */
+ if (time_rec != NULL) {
+ FILETIME current_time;
+ if (SystemTimeToFileTime(&current_time_system, &current_time) != 0)
+ *time_rec = (OM_uint32)(expiry.QuadPart - ((PLARGE_INTEGER)&current_time)->QuadPart) / 10000;
+ else
+ error("SystemTimeToFileTime failed with %lu", GetLastError());
+ }
+
+ /* only do checks on the finalized context (no continue needed) */
+ if (status == SEC_E_OK) {
+ /* extract the username from the context handle will be domain\samaccountname format */
+ SecPkgContext_NamesW NamesBuffer;
+ if (SecFunctions->QueryContextAttributesW(*context_handle, SECPKG_ATTR_NAMES, &NamesBuffer) != SEC_E_OK)
+ goto done;
+
+ /* copy to internal utf8 string and free the sspi string */
+ if ((*src_name = utf16_to_utf8(NamesBuffer.sUserName)) == NULL)
+ goto done;
+
+ FreeContextBuffer(NamesBuffer.sUserName);
+ }
+
+ /* copy output token to output buffer */
+ output_token->length = output_buffer_token.cbBuffer;
+ output_token->value = malloc(output_token->length);
+ memcpy(output_token->value, output_buffer_token.pvBuffer, output_token->length);
+ SecFunctions->FreeContextBuffer(output_buffer_token.pvBuffer);
+
+ /* get the user token for impersonation */
+ if (delegated_cred_handle != NULL) {
+ if ((*delegated_cred_handle = malloc(sizeof(struct cred_st))) == NULL)
+ goto done;
+ if (SecFunctions->QuerySecurityContextToken(*context_handle, &sspi_auth_user) != SEC_E_OK)
+ goto done;
+ (*delegated_cred_handle)->isToken = 1;
+ (*delegated_cred_handle)->token = sspi_auth_user;
+ }
+
+ ret = (status == SEC_I_CONTINUE_NEEDED) ? GSS_S_CONTINUE_NEEDED : GSS_S_COMPLETE;
+
+done:
+ if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
+ if (p_ctx_h)
+ free(p_ctx_h);
+ if (*src_name)
+ free(*src_name);
+ if (delegated_cred_handle && *delegated_cred_handle)
+ free(*delegated_cred_handle);
+ }
+ return ret;
+}
+
+/*
+ * Allows an application to obtain a textual representation of an opaque
+ * internal-form name for display purposes. The syntax of a printable name is
+ * defined by the GSS-API implementation.
+ */
+OM_uint32
+gss_display_name(OM_uint32 * minor_status, gss_name_t input_name,
+ gss_buffer_t output_name_buffer, gss_OID * output_name_type)
+{
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ return GSS_S_FAILURE;
+
+ output_name_buffer->length = strlen(input_name) + 1;
+ if ((output_name_buffer->value = _strdup(input_name)) == NULL)
+ return GSS_S_FAILURE;
+
+ /* set the output oid type if requested */
+ if (output_name_type != NULL)
+ *output_name_type = GSS_C_NT_HOSTBASED_SERVICE;
+
+ return GSS_S_COMPLETE;
+}
+
+/*
+ * Allows an application to obtain a textual representation of a GSS-API status
+ * code, for display to the user or for logging purposes. Since some status
+ * values may indicate multiple conditions, applications may need to call
+ * gss_display_status multiple times, each call generating a single text string.
+ * The message_context parameter is used by gss_display_status to store state
+ * information about which error messages have already been extracted from a
+ * given status_value; message_context must be initialized to 0 by the
+ * application prior to the first call, and gss_display_status will return a
+ * non-zero value in this parameter if there are further messages to extract.
+ */
+OM_uint32
+gss_display_status(OM_uint32 * minor_status, OM_uint32 status_value, int status_type,
+ gss_OID mech_type, OM_uint32 * message_context, gss_buffer_t status_string)
+{
+ if (ssh_gss_sspi_init(minor_status) == 0)
+ return GSS_S_FAILURE;
+
+ /* lookup textual representation of the numeric status code */
+ char * message_string = NULL;
+ if (status_value == GSS_S_COMPLETE)
+ message_string = "GSS_S_COMPLETE";
+ else if (status_value == GSS_S_BAD_BINDINGS)
+ message_string = "GSS_S_BAD_BINDINGS";
+ else if (status_value == GSS_S_BAD_MECH)
+ message_string = "GSS_S_BAD_MECH";
+ else if (status_value == GSS_S_BAD_NAME)
+ message_string = "GSS_S_BAD_NAME";
+ else if (status_value == GSS_S_BAD_NAMETYPE)
+ message_string = "GSS_S_BAD_NAMETYPE";
+ else if (status_value == GSS_S_BAD_QOP)
+ message_string = "GSS_S_BAD_QOP";
+ else if (status_value == GSS_S_BAD_SIG)
+ message_string = "GSS_S_BAD_SIG";
+ else if (status_value == GSS_S_BAD_STATUS)
+ message_string = "GSS_S_BAD_STATUS";
+ else if (status_value == GSS_S_CONTEXT_EXPIRED)
+ message_string = "GSS_S_CONTEXT_EXPIRED";
+ else if (status_value == GSS_S_CONTINUE_NEEDED)
+ message_string = "GSS_S_CONTINUE_NEEDED";
+ else if (status_value == GSS_S_CREDENTIALS_EXPIRED)
+ message_string = "GSS_S_CREDENTIALS_EXPIRED";
+ else if (status_value == GSS_S_DEFECTIVE_CREDENTIAL)
+ message_string = "GSS_S_DEFECTIVE_CREDENTIAL";
+ else if (status_value == GSS_S_DEFECTIVE_TOKEN)
+ message_string = "GSS_S_DEFECTIVE_TOKEN";
+ else if (status_value == GSS_S_DUPLICATE_ELEMENT)
+ message_string = "GSS_S_DUPLICATE_ELEMENT";
+ else if (status_value == GSS_S_DUPLICATE_TOKEN)
+ message_string = "GSS_S_DUPLICATE_TOKEN";
+ else if (status_value == GSS_S_FAILURE)
+ message_string = "GSS_S_FAILURE";
+ else if (status_value == GSS_S_NAME_NOT_MN)
+ message_string = "GSS_S_NAME_NOT_MN";
+ else if (status_value == GSS_S_NO_CONTEXT)
+ message_string = "GSS_S_NO_CONTEXT";
+ else if (status_value == GSS_S_NO_CRED)
+ message_string = "GSS_S_NO_CRED";
+ else if (status_value == GSS_S_OLD_TOKEN)
+ message_string = "GSS_S_OLD_TOKEN";
+ else if (status_value == GSS_S_UNAUTHORIZED)
+ message_string = "GSS_S_UNAUTHORIZED";
+ else if (status_value == GSS_S_UNAVAILABLE)
+ message_string = "GSS_S_UNAVAILABLE";
+ else if (status_value == GSS_S_UNSEQ_TOKEN)
+ message_string = "GSS_S_UNSEQ_TOKEN";
+
+ /* copy local status string to the output buffer */
+ status_string->length = strlen(message_string) + 1;
+ if ((status_string->value = _strdup(message_string)) == NULL)
+ return GSS_S_FAILURE;
+
+ /* no supplementary messages available */
+ *message_context = 0;
+
+ return GSS_S_COMPLETE;
+}
+
+/*
+ * The function ssh_gssapi_krb5_userok and gssapi_kerberos_mech structure
+ * are referenced in gss-serv.c and are required in order for the calling
+ * code to accept negotiate a kerberos token.
+ */
+
+static int
+ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
+{
+ /*
+ * This check is important since it makes sure that the username string
+ * that the user passed (e.g. user@host) matches the user authenticated
+ * via SSPI. If this check fails, the authentication process will move
+ * onto the next available method.
+ */
+ struct passwd * user = getpwnam(name);
+ if (user == NULL)
+ {
+ error("sspi getpwnam failed to get user from user-provided, resolved user '%s'", name);
+ return 0;
+ }
+ if (_stricmp(client->displayname.value, user->pw_name) != 0) {
+ /* check failed */
+ debug("sspi user '%s' did not match user-provided, resolved user '%s'",
+ (char *) client->displayname.value, name);
+ return 0;
+ }
+
+ return 1;
+}
+
+ssh_gssapi_mech gssapi_kerberos_mech = {
+ "toWM5Slw5Ew8Mqkay+al2g==",
+ "Kerberos",
+ {sizeof(GSS_C_NT_HOSTBASED_SERVICE_STR) - 1, GSS_C_NT_HOSTBASED_SERVICE_STR},
+ NULL,
+ &ssh_gssapi_krb5_userok,
+ NULL,
+ NULL
+};
+
+#endif /* KRB5 */
+#endif /* GSSAPI */
\ No newline at end of file
diff --git a/gss-serv.c b/gss-serv.c
index 53993d6..27da39e 100644
--- a/gss-serv.c
+++ b/gss-serv.c
@@ -57,12 +57,12 @@ static ssh_gssapi_client gssapi_client =
ssh_gssapi_mech gssapi_null_mech =
{ NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL};
-#ifdef KRB5
+#if defined(KRB5) || defined (SSPI)
extern ssh_gssapi_mech gssapi_kerberos_mech;
#endif
ssh_gssapi_mech* supported_mechs[]= {
-#ifdef KRB5
+#if defined(KRB5) || defined (SSPI)
&gssapi_kerberos_mech,
#endif
&gssapi_null_mech,
diff --git a/ssh-gss.h b/ssh-gss.h
index a99d7f0..2c90eb2 100644
--- a/ssh-gss.h
+++ b/ssh-gss.h
@@ -28,6 +28,14 @@
#ifdef GSSAPI
+#ifdef SSPI
+#include "contrib/win32/win32compat/inc/gssapi.h"
+#undef HAVE_GSSAPI_H
+#undef HAVE_GSSAPI_GSSAPI_H
+#undef HAVE_GSSAPI_GENERIC_H
+#undef HAVE_GSSAPI_GSSAPI_GENERIC_H
+#endif
+
#ifdef HAVE_GSSAPI_H
#include <gssapi.h>
#elif defined(HAVE_GSSAPI_GSSAPI_H)
...@@ -46,6 +46,7 @@ sshkey_file_tests(void) ...@@ -46,6 +46,7 @@ sshkey_file_tests(void)
struct sshbuf *buf, *pw; struct sshbuf *buf, *pw;
BIGNUM *a, *b, *c; BIGNUM *a, *b, *c;
char *cp; char *cp;
const BIGNUM *n, *p, *q, *g, *pub_key, *priv_key;
TEST_START("load passphrase"); TEST_START("load passphrase");
pw = load_text_file("pw"); pw = load_text_file("pw");
...@@ -58,7 +59,8 @@ sshkey_file_tests(void) ...@@ -58,7 +59,8 @@ sshkey_file_tests(void)
sshbuf_free(buf); sshbuf_free(buf);
ASSERT_PTR_NE(k1, NULL); ASSERT_PTR_NE(k1, NULL);
a = load_bignum("rsa1_1.param.n"); a = load_bignum("rsa1_1.param.n");
ASSERT_BIGNUM_EQ(k1->rsa->n, a); RSA_get0_key(k1->rsa, &n, NULL, NULL);
ASSERT_BIGNUM_EQ(n, a);
BN_free(a); BN_free(a);
TEST_DONE(); TEST_DONE();
...@@ -109,9 +111,11 @@ sshkey_file_tests(void) ...@@ -109,9 +111,11 @@ sshkey_file_tests(void)
a = load_bignum("rsa_1.param.n"); a = load_bignum("rsa_1.param.n");
b = load_bignum("rsa_1.param.p"); b = load_bignum("rsa_1.param.p");
c = load_bignum("rsa_1.param.q"); c = load_bignum("rsa_1.param.q");
ASSERT_BIGNUM_EQ(k1->rsa->n, a); RSA_get0_key(k1->rsa, &n, NULL, NULL);
ASSERT_BIGNUM_EQ(k1->rsa->p, b); RSA_get0_factors(k1->rsa, &p, &q);
ASSERT_BIGNUM_EQ(k1->rsa->q, c); ASSERT_BIGNUM_EQ(n, a);
ASSERT_BIGNUM_EQ(p, b);
ASSERT_BIGNUM_EQ(q, c);
BN_free(a); BN_free(a);
BN_free(b); BN_free(b);
BN_free(c); BN_free(c);
...@@ -200,9 +204,11 @@ sshkey_file_tests(void) ...@@ -200,9 +204,11 @@ sshkey_file_tests(void)
a = load_bignum("dsa_1.param.g"); a = load_bignum("dsa_1.param.g");
b = load_bignum("dsa_1.param.priv"); b = load_bignum("dsa_1.param.priv");
c = load_bignum("dsa_1.param.pub"); c = load_bignum("dsa_1.param.pub");
ASSERT_BIGNUM_EQ(k1->dsa->g, a); DSA_get0_pqg(k1->dsa, NULL, NULL, &g);
ASSERT_BIGNUM_EQ(k1->dsa->priv_key, b); DSA_get0_key(k1->dsa, &pub_key, &priv_key);
ASSERT_BIGNUM_EQ(k1->dsa->pub_key, c); ASSERT_BIGNUM_EQ(g, a);
ASSERT_BIGNUM_EQ(priv_key, b);
ASSERT_BIGNUM_EQ(pub_key, c);
BN_free(a); BN_free(a);
BN_free(b); BN_free(b);
BN_free(c); BN_free(c);
......
...@@ -197,9 +197,6 @@ sshkey_tests(void) ...@@ -197,9 +197,6 @@ sshkey_tests(void)
k1 = sshkey_new(KEY_RSA1); k1 = sshkey_new(KEY_RSA1);
ASSERT_PTR_NE(k1, NULL); ASSERT_PTR_NE(k1, NULL);
ASSERT_PTR_NE(k1->rsa, NULL); ASSERT_PTR_NE(k1->rsa, NULL);
ASSERT_PTR_NE(k1->rsa->n, NULL);
ASSERT_PTR_NE(k1->rsa->e, NULL);
ASSERT_PTR_EQ(k1->rsa->p, NULL);
sshkey_free(k1); sshkey_free(k1);
TEST_DONE(); TEST_DONE();
...@@ -207,9 +204,6 @@ sshkey_tests(void) ...@@ -207,9 +204,6 @@ sshkey_tests(void)
k1 = sshkey_new(KEY_RSA); k1 = sshkey_new(KEY_RSA);
ASSERT_PTR_NE(k1, NULL); ASSERT_PTR_NE(k1, NULL);
ASSERT_PTR_NE(k1->rsa, NULL); ASSERT_PTR_NE(k1->rsa, NULL);
ASSERT_PTR_NE(k1->rsa->n, NULL);
ASSERT_PTR_NE(k1->rsa->e, NULL);
ASSERT_PTR_EQ(k1->rsa->p, NULL);
sshkey_free(k1); sshkey_free(k1);
TEST_DONE(); TEST_DONE();
...@@ -217,8 +211,6 @@ sshkey_tests(void) ...@@ -217,8 +211,6 @@ sshkey_tests(void)
k1 = sshkey_new(KEY_DSA); k1 = sshkey_new(KEY_DSA);
ASSERT_PTR_NE(k1, NULL); ASSERT_PTR_NE(k1, NULL);
ASSERT_PTR_NE(k1->dsa, NULL); ASSERT_PTR_NE(k1->dsa, NULL);
ASSERT_PTR_NE(k1->dsa->g, NULL);
ASSERT_PTR_EQ(k1->dsa->priv_key, NULL);
sshkey_free(k1); sshkey_free(k1);
TEST_DONE(); TEST_DONE();
...@@ -244,9 +236,6 @@ sshkey_tests(void) ...@@ -244,9 +236,6 @@ sshkey_tests(void)
k1 = sshkey_new_private(KEY_RSA); k1 = sshkey_new_private(KEY_RSA);
ASSERT_PTR_NE(k1, NULL); ASSERT_PTR_NE(k1, NULL);
ASSERT_PTR_NE(k1->rsa, NULL); ASSERT_PTR_NE(k1->rsa, NULL);
ASSERT_PTR_NE(k1->rsa->n, NULL);
ASSERT_PTR_NE(k1->rsa->e, NULL);
ASSERT_PTR_NE(k1->rsa->p, NULL);
ASSERT_INT_EQ(sshkey_add_private(k1), 0); ASSERT_INT_EQ(sshkey_add_private(k1), 0);
sshkey_free(k1); sshkey_free(k1);
TEST_DONE(); TEST_DONE();
...@@ -255,8 +244,6 @@ sshkey_tests(void) ...@@ -255,8 +244,6 @@ sshkey_tests(void)
k1 = sshkey_new_private(KEY_DSA); k1 = sshkey_new_private(KEY_DSA);
ASSERT_PTR_NE(k1, NULL); ASSERT_PTR_NE(k1, NULL);
ASSERT_PTR_NE(k1->dsa, NULL); ASSERT_PTR_NE(k1->dsa, NULL);
ASSERT_PTR_NE(k1->dsa->g, NULL);
ASSERT_PTR_NE(k1->dsa->priv_key, NULL);
ASSERT_INT_EQ(sshkey_add_private(k1), 0); ASSERT_INT_EQ(sshkey_add_private(k1), 0);
sshkey_free(k1); sshkey_free(k1);
TEST_DONE(); TEST_DONE();
...@@ -295,18 +282,13 @@ sshkey_tests(void) ...@@ -295,18 +282,13 @@ sshkey_tests(void)
ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1024, &kr), 0); ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1024, &kr), 0);
ASSERT_PTR_NE(kr, NULL); ASSERT_PTR_NE(kr, NULL);
ASSERT_PTR_NE(kr->rsa, NULL); ASSERT_PTR_NE(kr->rsa, NULL);
ASSERT_PTR_NE(kr->rsa->n, NULL); ASSERT_INT_EQ(RSA_bits(kr->rsa), 1024);
ASSERT_PTR_NE(kr->rsa->e, NULL);
ASSERT_PTR_NE(kr->rsa->p, NULL);
ASSERT_INT_EQ(BN_num_bits(kr->rsa->n), 1024);
TEST_DONE(); TEST_DONE();
TEST_START("generate KEY_DSA"); TEST_START("generate KEY_DSA");
ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &kd), 0); ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &kd), 0);
ASSERT_PTR_NE(kd, NULL); ASSERT_PTR_NE(kd, NULL);
ASSERT_PTR_NE(kd->dsa, NULL); ASSERT_PTR_NE(kd->dsa, NULL);
ASSERT_PTR_NE(kd->dsa->g, NULL);
ASSERT_PTR_NE(kd->dsa->priv_key, NULL);
TEST_DONE(); TEST_DONE();
#ifdef OPENSSL_HAS_ECC #ifdef OPENSSL_HAS_ECC
...@@ -333,9 +315,6 @@ sshkey_tests(void) ...@@ -333,9 +315,6 @@ sshkey_tests(void)
ASSERT_PTR_NE(kr, k1); ASSERT_PTR_NE(kr, k1);
ASSERT_INT_EQ(k1->type, KEY_RSA); ASSERT_INT_EQ(k1->type, KEY_RSA);
ASSERT_PTR_NE(k1->rsa, NULL); ASSERT_PTR_NE(k1->rsa, NULL);
ASSERT_PTR_NE(k1->rsa->n, NULL);
ASSERT_PTR_NE(k1->rsa->e, NULL);
ASSERT_PTR_EQ(k1->rsa->p, NULL);
TEST_DONE(); TEST_DONE();
TEST_START("equal KEY_RSA/demoted KEY_RSA"); TEST_START("equal KEY_RSA/demoted KEY_RSA");
...@@ -349,8 +328,6 @@ sshkey_tests(void) ...@@ -349,8 +328,6 @@ sshkey_tests(void)
ASSERT_PTR_NE(kd, k1); ASSERT_PTR_NE(kd, k1);
ASSERT_INT_EQ(k1->type, KEY_DSA); ASSERT_INT_EQ(k1->type, KEY_DSA);
ASSERT_PTR_NE(k1->dsa, NULL); ASSERT_PTR_NE(k1->dsa, NULL);
ASSERT_PTR_NE(k1->dsa->g, NULL);
ASSERT_PTR_EQ(k1->dsa->priv_key, NULL);
TEST_DONE(); TEST_DONE();
TEST_START("equal KEY_DSA/demoted KEY_DSA"); TEST_START("equal KEY_DSA/demoted KEY_DSA");
......
...@@ -76,11 +76,14 @@ rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key) ...@@ -76,11 +76,14 @@ rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
{ {
u_char *inbuf = NULL, *outbuf = NULL; u_char *inbuf = NULL, *outbuf = NULL;
int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR; int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR;
const BIGNUM *e, *n;
if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e)) RSA_get0_key(key, &n, &e, NULL);
if (BN_num_bits(e) < 2 || !BN_is_odd(e))
return SSH_ERR_INVALID_ARGUMENT; return SSH_ERR_INVALID_ARGUMENT;
olen = BN_num_bytes(key->n); olen = BN_num_bytes(n);
if ((outbuf = malloc(olen)) == NULL) { if ((outbuf = malloc(olen)) == NULL) {
r = SSH_ERR_ALLOC_FAIL; r = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
...@@ -122,8 +125,11 @@ rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key) ...@@ -122,8 +125,11 @@ rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
{ {
u_char *inbuf = NULL, *outbuf = NULL; u_char *inbuf = NULL, *outbuf = NULL;
int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR; int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR;
const BIGNUM *n;
RSA_get0_key(key, &n, NULL, NULL);
olen = BN_num_bytes(key->n); olen = BN_num_bytes(n);
if ((outbuf = malloc(olen)) == NULL) { if ((outbuf = malloc(olen)) == NULL) {
r = SSH_ERR_ALLOC_FAIL; r = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
...@@ -157,31 +163,42 @@ rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key) ...@@ -157,31 +163,42 @@ rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
return r; return r;
} }
/* calculate p-1 and q-1 */ /* calculate d mod p-1 and d mod q-1 */
int int
rsa_generate_additional_parameters(RSA *rsa) rsa_generate_additional_parameters(RSA *rsa, BIGNUM *iqmp)
{ {
BIGNUM *aux = NULL; BIGNUM *aux = NULL;
BN_CTX *ctx = NULL; BN_CTX *ctx = NULL;
int r; int r;
const BIGNUM *p, *q, *d;
BIGNUM *dmp1 = NULL, *dmq1 = NULL;
RSA_get0_factors(rsa, &p, &q);
RSA_get0_key(rsa, NULL, NULL, &d);
if ((ctx = BN_CTX_new()) == NULL) if ((ctx = BN_CTX_new()) == NULL ||
return SSH_ERR_ALLOC_FAIL; (aux = BN_new()) == NULL ||
if ((aux = BN_new()) == NULL) { (dmp1 = BN_new()) == NULL ||
(dmq1 = BN_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL; r = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
} }
if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) || if ((BN_sub(aux, q, BN_value_one()) == 0) ||
(BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) || (BN_mod(dmq1, d, aux, ctx) == 0) ||
(BN_sub(aux, rsa->p, BN_value_one()) == 0) || (BN_sub(aux, p, BN_value_one()) == 0) ||
(BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) { (BN_mod(dmp1, d, aux, ctx) == 0) ||
(RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp) == 0)) {
r = SSH_ERR_LIBCRYPTO_ERROR; r = SSH_ERR_LIBCRYPTO_ERROR;
goto out; goto out;
} }
dmp1 = NULL;
dmq1 = NULL;
r = 0; r = 0;
out: out:
BN_clear_free(aux); BN_clear_free(aux);
BN_clear_free(dmp1);
BN_clear_free(dmq1);
BN_CTX_free(ctx); BN_CTX_free(ctx);
return r; return r;
} }
......
...@@ -21,6 +21,6 @@ ...@@ -21,6 +21,6 @@
int rsa_public_encrypt(BIGNUM *, BIGNUM *, RSA *); int rsa_public_encrypt(BIGNUM *, BIGNUM *, RSA *);
int rsa_private_decrypt(BIGNUM *, BIGNUM *, RSA *); int rsa_private_decrypt(BIGNUM *, BIGNUM *, RSA *);
int rsa_generate_additional_parameters(RSA *); int rsa_generate_additional_parameters(RSA *, BIGNUM *);
#endif /* RSA_H */ #endif /* RSA_H */
...@@ -258,12 +258,12 @@ process_request_identities(SocketEntry *e, int version) ...@@ -258,12 +258,12 @@ process_request_identities(SocketEntry *e, int version)
TAILQ_FOREACH(id, &tab->idlist, next) { TAILQ_FOREACH(id, &tab->idlist, next) {
if (id->key->type == KEY_RSA1) { if (id->key->type == KEY_RSA1) {
#ifdef WITH_SSH1 #ifdef WITH_SSH1
const BIGNUM *r_n, *r_e;
RSA_get0_key(id->key->rsa, &r_n, &r_e, NULL);
if ((r = sshbuf_put_u32(msg, if ((r = sshbuf_put_u32(msg,
BN_num_bits(id->key->rsa->n))) != 0 || BN_num_bits(r_n))) != 0 ||
(r = sshbuf_put_bignum1(msg, (r = sshbuf_put_bignum1(msg, r_e)) != 0 ||
id->key->rsa->e)) != 0 || (r = sshbuf_put_bignum1(msg, r_n)) != 0)
(r = sshbuf_put_bignum1(msg,
id->key->rsa->n)) != 0)
fatal("%s: buffer error: %s", fatal("%s: buffer error: %s",
__func__, ssh_err(r)); __func__, ssh_err(r));
#endif #endif
...@@ -302,6 +302,7 @@ process_authentication_challenge1(SocketEntry *e) ...@@ -302,6 +302,7 @@ process_authentication_challenge1(SocketEntry *e)
struct sshbuf *msg; struct sshbuf *msg;
struct ssh_digest_ctx *md; struct ssh_digest_ctx *md;
struct sshkey *key; struct sshkey *key;
BIGNUM *r_n = NULL, *r_e = NULL;
if ((msg = sshbuf_new()) == NULL) if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__); fatal("%s: sshbuf_new failed", __func__);
...@@ -310,11 +311,16 @@ process_authentication_challenge1(SocketEntry *e) ...@@ -310,11 +311,16 @@ process_authentication_challenge1(SocketEntry *e)
if ((challenge = BN_new()) == NULL) if ((challenge = BN_new()) == NULL)
fatal("%s: BN_new failed", __func__); fatal("%s: BN_new failed", __func__);
if ((r = sshbuf_get_u32(e->request, NULL)) != 0 || /* ignored */ if ((r_n = BN_new()) == NULL || (r_e = BN_new()) == NULL ||
(r = sshbuf_get_bignum1(e->request, key->rsa->e)) != 0 || (r = sshbuf_get_u32(e->request, NULL)) != 0 || /* ignored */
(r = sshbuf_get_bignum1(e->request, key->rsa->n)) != 0 || (r = sshbuf_get_bignum1(e->request, r_e)) != 0 ||
(r = sshbuf_get_bignum1(e->request, challenge))) (r = sshbuf_get_bignum1(e->request, r_n)) != 0 ||
(r = sshbuf_get_bignum1(e->request, challenge)) ||
RSA_set0_key(key->rsa, r_n, r_e, NULL) == 0) {
BN_free(r_n);
BN_free(r_e);
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
/* Only protocol 1.1 is supported */ /* Only protocol 1.1 is supported */
if (sshbuf_len(e->request) == 0) if (sshbuf_len(e->request) == 0)
...@@ -450,6 +456,7 @@ process_remove_identity(SocketEntry *e, int version) ...@@ -450,6 +456,7 @@ process_remove_identity(SocketEntry *e, int version)
u_char *blob; u_char *blob;
#ifdef WITH_SSH1 #ifdef WITH_SSH1
u_int bits; u_int bits;
BIGNUM *r_n = NULL, *r_e = NULL;
#endif /* WITH_SSH1 */ #endif /* WITH_SSH1 */
switch (version) { switch (version) {
...@@ -459,10 +466,15 @@ process_remove_identity(SocketEntry *e, int version) ...@@ -459,10 +466,15 @@ process_remove_identity(SocketEntry *e, int version)
error("%s: sshkey_new failed", __func__); error("%s: sshkey_new failed", __func__);
return; return;
} }
if ((r = sshbuf_get_u32(e->request, &bits)) != 0 || if ((r_n = BN_new()) == NULL || (r_e = BN_new()) == NULL ||
(r = sshbuf_get_bignum1(e->request, key->rsa->e)) != 0 || (r = sshbuf_get_u32(e->request, &bits)) != 0 ||
(r = sshbuf_get_bignum1(e->request, key->rsa->n)) != 0) (r = sshbuf_get_bignum1(e->request, r_e)) != 0 ||
(r = sshbuf_get_bignum1(e->request, r_n)) != 0 ||
RSA_set0_key(key->rsa, r_n, r_e, NULL) == 0) {
BN_free(r_n);
BN_free(r_e);
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
if (bits != sshkey_size(key)) if (bits != sshkey_size(key))
logit("Warning: identity keysize mismatch: " logit("Warning: identity keysize mismatch: "
...@@ -565,23 +577,46 @@ agent_decode_rsa1(struct sshbuf *m, struct sshkey **kp) ...@@ -565,23 +577,46 @@ agent_decode_rsa1(struct sshbuf *m, struct sshkey **kp)
{ {
struct sshkey *k = NULL; struct sshkey *k = NULL;
int r = SSH_ERR_INTERNAL_ERROR; int r = SSH_ERR_INTERNAL_ERROR;
BIGNUM *n = NULL, *e = NULL, *d = NULL,
*iqmp = NULL, *q = NULL, *p = NULL;
*kp = NULL; *kp = NULL;
if ((k = sshkey_new_private(KEY_RSA1)) == NULL) if ((k = sshkey_new_private(KEY_RSA1)) == NULL)
return SSH_ERR_ALLOC_FAIL; return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_get_u32(m, NULL)) != 0 || /* ignored */ if ((n = BN_new()) == NULL || (e = BN_new()) == NULL ||
(r = sshbuf_get_bignum1(m, k->rsa->n)) != 0 || (d = BN_new()) == NULL || (iqmp = BN_new()) == NULL ||
(r = sshbuf_get_bignum1(m, k->rsa->e)) != 0 || (q = BN_new()) == NULL || (p = BN_new()) == NULL ||
(r = sshbuf_get_bignum1(m, k->rsa->d)) != 0 || (r = sshbuf_get_u32(m, NULL)) != 0 || /* ignored */
(r = sshbuf_get_bignum1(m, k->rsa->iqmp)) != 0 || (r = sshbuf_get_bignum1(m, n)) != 0 ||
(r = sshbuf_get_bignum1(m, e)) != 0 ||
(r = sshbuf_get_bignum1(m, d)) != 0 ||
(r = sshbuf_get_bignum1(m, iqmp)) != 0 ||
/* SSH1 and SSL have p and q swapped */ /* SSH1 and SSL have p and q swapped */
(r = sshbuf_get_bignum1(m, k->rsa->q)) != 0 || /* p */ (r = sshbuf_get_bignum1(m, q)) != 0 || /* p */
(r = sshbuf_get_bignum1(m, k->rsa->p)) != 0) /* q */ (r = sshbuf_get_bignum1(m, p)) != 0 || /* q */
RSA_set0_key(k->rsa, n, e, d) == 0) {
BN_free(n);
BN_free(e);
BN_free(d);
BN_free(p);
BN_free(q);
BN_free(iqmp);
goto out;
}
if (RSA_set0_factors(k->rsa, p, q) == 0) {
BN_free(p);
BN_free(q);
BN_free(iqmp);
goto out; goto out;
}
if (RSA_set0_crt_params(k->rsa, NULL, NULL, iqmp) == 0) {
BN_free(iqmp);
goto out;
}
/* Generate additional parameters */ /* Generate additional parameters */
if ((r = rsa_generate_additional_parameters(k->rsa)) != 0) if ((r = rsa_generate_additional_parameters(k->rsa, NULL)) != 0)
goto out; goto out;
/* enable blinding */ /* enable blinding */
if (RSA_blinding_on(k->rsa, NULL) != 1) { if (RSA_blinding_on(k->rsa, NULL) != 1) {
......
...@@ -55,6 +55,7 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, ...@@ -55,6 +55,7 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
struct sshbuf *b = NULL; struct sshbuf *b = NULL;
int ret = SSH_ERR_INVALID_ARGUMENT; int ret = SSH_ERR_INVALID_ARGUMENT;
const BIGNUM *r, *s;
if (lenp != NULL) if (lenp != NULL)
*lenp = 0; *lenp = 0;
...@@ -76,15 +77,16 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, ...@@ -76,15 +77,16 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
goto out; goto out;
} }
rlen = BN_num_bytes(sig->r); DSA_SIG_get0(sig, &r, &s);
slen = BN_num_bytes(sig->s); rlen = BN_num_bytes(r);
slen = BN_num_bytes(s);
if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
ret = SSH_ERR_INTERNAL_ERROR; ret = SSH_ERR_INTERNAL_ERROR;
goto out; goto out;
} }
explicit_bzero(sigblob, SIGBLOB_LEN); explicit_bzero(sigblob, SIGBLOB_LEN);
BN_bn2bin(sig->r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen); BN_bn2bin(r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen);
BN_bn2bin(sig->s, sigblob + SIGBLOB_LEN - slen); BN_bn2bin(s, sigblob + SIGBLOB_LEN - slen);
if (compat & SSH_BUG_SIGBLOB) { if (compat & SSH_BUG_SIGBLOB) {
if (sigp != NULL) { if (sigp != NULL) {
...@@ -137,6 +139,7 @@ ssh_dss_verify(const struct sshkey *key, ...@@ -137,6 +139,7 @@ ssh_dss_verify(const struct sshkey *key,
int ret = SSH_ERR_INTERNAL_ERROR; int ret = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *b = NULL; struct sshbuf *b = NULL;
char *ktype = NULL; char *ktype = NULL;
BIGNUM *r = NULL, *s = NULL;
if (key == NULL || key->dsa == NULL || if (key == NULL || key->dsa == NULL ||
sshkey_type_plain(key->type) != KEY_DSA || sshkey_type_plain(key->type) != KEY_DSA ||
...@@ -177,16 +180,19 @@ ssh_dss_verify(const struct sshkey *key, ...@@ -177,16 +180,19 @@ ssh_dss_verify(const struct sshkey *key,
/* parse signature */ /* parse signature */
if ((sig = DSA_SIG_new()) == NULL || if ((sig = DSA_SIG_new()) == NULL ||
(sig->r = BN_new()) == NULL || (r = BN_new()) == NULL ||
(sig->s = BN_new()) == NULL) { (s = BN_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL; ret = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
} }
if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) || if ((BN_bin2bn(sigblob, INTBLOB_LEN, r) == NULL) ||
(BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL)) { (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, s) == NULL) ||
(DSA_SIG_set0(sig, r, s) == 0)) {
ret = SSH_ERR_LIBCRYPTO_ERROR; ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out; goto out;
} }
r = NULL;
s = NULL;
/* sha1 the data */ /* sha1 the data */
if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
...@@ -207,7 +213,8 @@ ssh_dss_verify(const struct sshkey *key, ...@@ -207,7 +213,8 @@ ssh_dss_verify(const struct sshkey *key,
out: out:
explicit_bzero(digest, sizeof(digest)); explicit_bzero(digest, sizeof(digest));
if (sig != NULL) BN_free(r);
BN_free(s);
DSA_SIG_free(sig); DSA_SIG_free(sig);
sshbuf_free(b); sshbuf_free(b);
free(ktype); free(ktype);
......
...@@ -54,6 +54,7 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, ...@@ -54,6 +54,7 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
size_t len, dlen; size_t len, dlen;
struct sshbuf *b = NULL, *bb = NULL; struct sshbuf *b = NULL, *bb = NULL;
int ret = SSH_ERR_INTERNAL_ERROR; int ret = SSH_ERR_INTERNAL_ERROR;
const BIGNUM *r, *s;
if (lenp != NULL) if (lenp != NULL)
*lenp = 0; *lenp = 0;
...@@ -80,8 +81,9 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, ...@@ -80,8 +81,9 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
ret = SSH_ERR_ALLOC_FAIL; ret = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
} }
if ((ret = sshbuf_put_bignum2(bb, sig->r)) != 0 || ECDSA_SIG_get0(sig, &r, &s);
(ret = sshbuf_put_bignum2(bb, sig->s)) != 0) if ((ret = sshbuf_put_bignum2(bb, r)) != 0 ||
(ret = sshbuf_put_bignum2(bb, s)) != 0)
goto out; goto out;
if ((ret = sshbuf_put_cstring(b, sshkey_ssh_name_plain(key))) != 0 || if ((ret = sshbuf_put_cstring(b, sshkey_ssh_name_plain(key))) != 0 ||
(ret = sshbuf_put_stringb(b, bb)) != 0) (ret = sshbuf_put_stringb(b, bb)) != 0)
...@@ -119,6 +121,7 @@ ssh_ecdsa_verify(const struct sshkey *key, ...@@ -119,6 +121,7 @@ ssh_ecdsa_verify(const struct sshkey *key,
int ret = SSH_ERR_INTERNAL_ERROR; int ret = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *b = NULL, *sigbuf = NULL; struct sshbuf *b = NULL, *sigbuf = NULL;
char *ktype = NULL; char *ktype = NULL;
BIGNUM *r = NULL, *s = NULL;
if (key == NULL || key->ecdsa == NULL || if (key == NULL || key->ecdsa == NULL ||
sshkey_type_plain(key->type) != KEY_ECDSA || sshkey_type_plain(key->type) != KEY_ECDSA ||
...@@ -147,15 +150,23 @@ ssh_ecdsa_verify(const struct sshkey *key, ...@@ -147,15 +150,23 @@ ssh_ecdsa_verify(const struct sshkey *key,
} }
/* parse signature */ /* parse signature */
if ((sig = ECDSA_SIG_new()) == NULL) { if ((sig = ECDSA_SIG_new()) == NULL ||
(r = BN_new()) == NULL ||
(s = BN_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL; ret = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
} }
if (sshbuf_get_bignum2(sigbuf, sig->r) != 0 || if (sshbuf_get_bignum2(sigbuf, r) != 0 ||
sshbuf_get_bignum2(sigbuf, sig->s) != 0) { sshbuf_get_bignum2(sigbuf, s) != 0) {
ret = SSH_ERR_INVALID_FORMAT; ret = SSH_ERR_INVALID_FORMAT;
goto out; goto out;
} }
if (ECDSA_SIG_set0(sig, r, s) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
r = NULL;
s = NULL;
if (sshbuf_len(sigbuf) != 0) { if (sshbuf_len(sigbuf) != 0) {
ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
goto out; goto out;
...@@ -180,7 +191,8 @@ ssh_ecdsa_verify(const struct sshkey *key, ...@@ -180,7 +191,8 @@ ssh_ecdsa_verify(const struct sshkey *key,
explicit_bzero(digest, sizeof(digest)); explicit_bzero(digest, sizeof(digest));
sshbuf_free(sigbuf); sshbuf_free(sigbuf);
sshbuf_free(b); sshbuf_free(b);
if (sig != NULL) BN_free(r);
BN_free(s);
ECDSA_SIG_free(sig); ECDSA_SIG_free(sig);
free(ktype); free(ktype);
return ret; return ret;
......
...@@ -28,6 +28,14 @@ ...@@ -28,6 +28,14 @@
#ifdef GSSAPI #ifdef GSSAPI
#ifdef SSPI
#include "contrib/win32/win32compat/inc/gssapi.h"
#undef HAVE_GSSAPI_H
#undef HAVE_GSSAPI_GSSAPI_H
#undef HAVE_GSSAPI_GENERIC_H
#undef HAVE_GSSAPI_GSSAPI_GENERIC_H
#endif
#ifdef HAVE_GSSAPI_H #ifdef HAVE_GSSAPI_H
#include <gssapi.h> #include <gssapi.h>
#elif defined(HAVE_GSSAPI_GSSAPI_H) #elif defined(HAVE_GSSAPI_GSSAPI_H)
......
...@@ -495,14 +495,37 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) ...@@ -495,14 +495,37 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
free(type); free(type);
switch (key->type) { switch (key->type) {
case KEY_DSA: case KEY_DSA: {
buffer_get_bignum_bits(b, key->dsa->p); BIGNUM *p = NULL, *g = NULL, *q = NULL, *pub_key = NULL, *priv_key = NULL;
buffer_get_bignum_bits(b, key->dsa->g);
buffer_get_bignum_bits(b, key->dsa->q); if ((p = BN_new()) == NULL ||
buffer_get_bignum_bits(b, key->dsa->pub_key); (g = BN_new()) == NULL ||
buffer_get_bignum_bits(b, key->dsa->priv_key); (q = BN_new()) == NULL ||
break; (pub_key = BN_new()) == NULL ||
case KEY_RSA: (priv_key = BN_new()) == NULL)
fatal("BN_new() failed");
buffer_get_bignum_bits(b, p);
buffer_get_bignum_bits(b, g);
buffer_get_bignum_bits(b, q);
buffer_get_bignum_bits(b, pub_key);
buffer_get_bignum_bits(b, priv_key);
if (DSA_set0_pqg(key->dsa, p, q, g) == 0 ||
DSA_set0_key(key->dsa, pub_key, priv_key) == 0) {
fatal("failed to set DSA key");
}
}
break;
case KEY_RSA: {
BIGNUM *bn_e = NULL, *bn_d = NULL, *bn_n = NULL, *bn_iqmp = NULL, *bn_p = NULL, *bn_q = NULL;
if ((bn_e = BN_new()) == NULL ||
(bn_d = BN_new()) == NULL ||
(bn_n = BN_new()) == NULL ||
(bn_iqmp = BN_new()) == NULL ||
(bn_p = BN_new()) == NULL ||
(bn_q = BN_new()) == NULL)
fatal("BN_new() failed");
if ((r = sshbuf_get_u8(b, &e1)) != 0 || if ((r = sshbuf_get_u8(b, &e1)) != 0 ||
(e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) || (e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) ||
(e1 < 30 && (r = sshbuf_get_u8(b, &e3)) != 0)) (e1 < 30 && (r = sshbuf_get_u8(b, &e3)) != 0))
...@@ -517,18 +540,22 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) ...@@ -517,18 +540,22 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
e += e3; e += e3;
debug("e %lx", e); debug("e %lx", e);
} }
if (!BN_set_word(key->rsa->e, e)) { if (!BN_set_word(bn_e, e)) {
sshbuf_free(b); sshbuf_free(b);
sshkey_free(key); sshkey_free(key);
return NULL; return NULL;
} }
buffer_get_bignum_bits(b, key->rsa->d); buffer_get_bignum_bits(b, bn_d);
buffer_get_bignum_bits(b, key->rsa->n); buffer_get_bignum_bits(b, bn_n);
buffer_get_bignum_bits(b, key->rsa->iqmp); buffer_get_bignum_bits(b, bn_iqmp);
buffer_get_bignum_bits(b, key->rsa->q); buffer_get_bignum_bits(b, bn_q);
buffer_get_bignum_bits(b, key->rsa->p); buffer_get_bignum_bits(b, bn_p);
if ((r = rsa_generate_additional_parameters(key->rsa)) != 0) if (RSA_set0_key(key->rsa, bn_n, bn_e, bn_d) == 0 ||
RSA_set0_factors(key->rsa, bn_p, bn_q) == 0)
fatal("Failed to set RSA parameters");
if ((r = rsa_generate_additional_parameters(key->rsa, bn_iqmp)) != 0)
fatal("generate RSA parameters failed: %s", ssh_err(r)); fatal("generate RSA parameters failed: %s", ssh_err(r));
}
break; break;
} }
rlen = sshbuf_len(b); rlen = sshbuf_len(b);
...@@ -636,7 +663,7 @@ do_convert_from_pkcs8(struct sshkey **k, int *private) ...@@ -636,7 +663,7 @@ do_convert_from_pkcs8(struct sshkey **k, int *private)
identity_file); identity_file);
} }
fclose(fp); fclose(fp);
switch (EVP_PKEY_type(pubkey->type)) { switch (EVP_PKEY_base_id(pubkey)) {
case EVP_PKEY_RSA: case EVP_PKEY_RSA:
if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
fatal("sshkey_new failed"); fatal("sshkey_new failed");
...@@ -660,7 +687,7 @@ do_convert_from_pkcs8(struct sshkey **k, int *private) ...@@ -660,7 +687,7 @@ do_convert_from_pkcs8(struct sshkey **k, int *private)
#endif #endif
default: default:
fatal("%s: unsupported pubkey type %d", __func__, fatal("%s: unsupported pubkey type %d", __func__,
EVP_PKEY_type(pubkey->type)); EVP_PKEY_base_id(pubkey));
} }
EVP_PKEY_free(pubkey); EVP_PKEY_free(pubkey);
return; return;
...@@ -1702,6 +1729,7 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) ...@@ -1702,6 +1729,7 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
#ifdef ENABLE_PKCS11 #ifdef ENABLE_PKCS11
pkcs11_terminate(); pkcs11_terminate();
#endif #endif
free(ca);
exit(0); exit(0);
} }
......
...@@ -195,6 +195,7 @@ keygrab_ssh1(con *c) ...@@ -195,6 +195,7 @@ keygrab_ssh1(con *c)
static struct sshbuf *msg; static struct sshbuf *msg;
int r; int r;
u_char type; u_char type;
BIGNUM *n = NULL, *e = NULL;
if (rsa == NULL) { if (rsa == NULL) {
if ((rsa = sshkey_new(KEY_RSA1)) == NULL) { if ((rsa = sshkey_new(KEY_RSA1)) == NULL) {
...@@ -213,16 +214,20 @@ keygrab_ssh1(con *c) ...@@ -213,16 +214,20 @@ keygrab_ssh1(con *c)
sshbuf_reset(msg); sshbuf_reset(msg);
return NULL; return NULL;
} }
if ((r = sshbuf_consume(msg, 8)) != 0 || /* cookie */ if ((n = BN_new()) == NULL || (e = BN_new()) == NULL ||
(r = sshbuf_consume(msg, 8)) != 0 || /* cookie */
/* server key */ /* server key */
(r = sshbuf_get_u32(msg, NULL)) != 0 || (r = sshbuf_get_u32(msg, NULL)) != 0 ||
(r = sshbuf_get_bignum1(msg, NULL)) != 0 || (r = sshbuf_get_bignum1(msg, NULL)) != 0 ||
(r = sshbuf_get_bignum1(msg, NULL)) != 0 || (r = sshbuf_get_bignum1(msg, NULL)) != 0 ||
/* host key */ /* host key */
(r = sshbuf_get_u32(msg, NULL)) != 0 || (r = sshbuf_get_u32(msg, NULL)) != 0 ||
(r = sshbuf_get_bignum1(msg, rsa->rsa->e)) != 0 || (r = sshbuf_get_bignum1(msg, e)) != 0 ||
(r = sshbuf_get_bignum1(msg, rsa->rsa->n)) != 0) { (r = sshbuf_get_bignum1(msg, n)) != 0 ||
RSA_set0_key(rsa->rsa, n, e, NULL) == 0) {
buf_err: buf_err:
BN_free(n);
BN_free(e);
error("%s: buffer error: %s", __func__, ssh_err(r)); error("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_reset(msg); sshbuf_reset(msg);
return NULL; return NULL;
......
...@@ -143,12 +143,14 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, ...@@ -143,12 +143,14 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
static int static int
wrap_key(RSA *rsa) wrap_key(RSA *rsa)
{ {
static RSA_METHOD helper_rsa; static RSA_METHOD *helper_rsa;
memcpy(&helper_rsa, RSA_get_default_method(), sizeof(helper_rsa)); if (helper_rsa == NULL) {
helper_rsa.name = "ssh-pkcs11-helper"; helper_rsa = RSA_meth_dup(RSA_get_default_method());
helper_rsa.rsa_priv_enc = pkcs11_rsa_private_encrypt; RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper");
RSA_set_method(rsa, &helper_rsa); RSA_meth_set_priv_enc(helper_rsa, pkcs11_rsa_private_encrypt);
}
RSA_set_method(rsa, helper_rsa);
return (0); return (0);
} }
......
...@@ -67,7 +67,7 @@ struct pkcs11_key { ...@@ -67,7 +67,7 @@ struct pkcs11_key {
struct pkcs11_provider *provider; struct pkcs11_provider *provider;
CK_ULONG slotidx; CK_ULONG slotidx;
int (*orig_finish)(RSA *rsa); int (*orig_finish)(RSA *rsa);
RSA_METHOD rsa_method; RSA_METHOD *rsa_method;
char *keyid; char *keyid;
int keyid_len; int keyid_len;
}; };
...@@ -326,13 +326,21 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, ...@@ -326,13 +326,21 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
k11->keyid = xmalloc(k11->keyid_len); k11->keyid = xmalloc(k11->keyid_len);
memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
} }
k11->orig_finish = def->finish; k11->orig_finish = RSA_meth_get_finish(def);
memcpy(&k11->rsa_method, def, sizeof(k11->rsa_method)); if ((k11->rsa_method = RSA_meth_dup(def)) == NULL ||
k11->rsa_method.name = "pkcs11"; RSA_meth_set1_name(k11->rsa_method, "pkcs11") == 0 ||
k11->rsa_method.rsa_priv_enc = pkcs11_rsa_private_encrypt; RSA_meth_set_priv_enc(k11->rsa_method, pkcs11_rsa_private_encrypt) == 0 ||
k11->rsa_method.rsa_priv_dec = pkcs11_rsa_private_decrypt; RSA_meth_set_priv_dec(k11->rsa_method, pkcs11_rsa_private_decrypt) == 0 ||
k11->rsa_method.finish = pkcs11_rsa_finish; RSA_meth_set_finish(k11->rsa_method, pkcs11_rsa_finish) == 0) {
RSA_set_method(rsa, &k11->rsa_method); RSA_meth_free(k11->rsa_method);
k11->rsa_method = NULL;
pkcs11_provider_unref(k11->provider);
free(k11->keyid);
free(k11);
return (-1);
}
RSA_set_method(rsa, k11->rsa_method);
RSA_set_app_data(rsa, k11); RSA_set_app_data(rsa, k11);
return (0); return (0);
} }
...@@ -460,6 +468,7 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, ...@@ -460,6 +468,7 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx,
CK_ULONG nfound; CK_ULONG nfound;
CK_SESSION_HANDLE session; CK_SESSION_HANDLE session;
CK_FUNCTION_LIST *f; CK_FUNCTION_LIST *f;
const BIGNUM *n, *e;
f = p->function_list; f = p->function_list;
session = p->slotinfo[slotidx].session; session = p->slotinfo[slotidx].session;
...@@ -512,10 +521,14 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, ...@@ -512,10 +521,14 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx,
if ((rsa = RSA_new()) == NULL) { if ((rsa = RSA_new()) == NULL) {
error("RSA_new failed"); error("RSA_new failed");
} else { } else {
rsa->n = BN_bin2bn(attribs[1].pValue, BIGNUM *rsa_n, *rsa_e;
rsa_n = BN_bin2bn(attribs[1].pValue,
attribs[1].ulValueLen, NULL); attribs[1].ulValueLen, NULL);
rsa->e = BN_bin2bn(attribs[2].pValue, rsa_e = BN_bin2bn(attribs[2].pValue,
attribs[2].ulValueLen, NULL); attribs[2].ulValueLen, NULL);
if (RSA_set0_key(rsa, rsa_n, rsa_e, NULL) == 0)
error("RSA_set0_key failed");
} }
} else { } else {
cp = attribs[2].pValue; cp = attribs[2].pValue;
...@@ -525,17 +538,18 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, ...@@ -525,17 +538,18 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx,
== NULL) { == NULL) {
error("d2i_X509 failed"); error("d2i_X509 failed");
} else if ((evp = X509_get_pubkey(x509)) == NULL || } else if ((evp = X509_get_pubkey(x509)) == NULL ||
evp->type != EVP_PKEY_RSA || EVP_PKEY_id(evp) != EVP_PKEY_RSA ||
evp->pkey.rsa == NULL) { EVP_PKEY_get0_RSA(evp) == NULL) {
debug("X509_get_pubkey failed or no rsa"); debug("X509_get_pubkey failed or no rsa");
} else if ((rsa = RSAPublicKey_dup(evp->pkey.rsa)) } else if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp)))
== NULL) { == NULL) {
error("RSAPublicKey_dup"); error("RSAPublicKey_dup");
} }
if (x509) if (x509)
X509_free(x509); X509_free(x509);
} }
if (rsa && rsa->n && rsa->e && RSA_get0_key(rsa, &n, &e, NULL);
if (rsa && n && e &&
pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) {
key = sshkey_new(KEY_UNSPEC); key = sshkey_new(KEY_UNSPEC);
key->rsa = rsa; key->rsa = rsa;
......
...@@ -100,7 +100,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, ...@@ -100,7 +100,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
hash_alg = rsa_hash_alg_from_ident(alg_ident); hash_alg = rsa_hash_alg_from_ident(alg_ident);
if (key == NULL || key->rsa == NULL || hash_alg == -1 || if (key == NULL || key->rsa == NULL || hash_alg == -1 ||
sshkey_type_plain(key->type) != KEY_RSA || sshkey_type_plain(key->type) != KEY_RSA ||
BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE)
return SSH_ERR_INVALID_ARGUMENT; return SSH_ERR_INVALID_ARGUMENT;
slen = RSA_size(key->rsa); slen = RSA_size(key->rsa);
if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
...@@ -172,7 +172,7 @@ ssh_rsa_verify(const struct sshkey *key, ...@@ -172,7 +172,7 @@ ssh_rsa_verify(const struct sshkey *key,
if (key == NULL || key->rsa == NULL || if (key == NULL || key->rsa == NULL ||
sshkey_type_plain(key->type) != KEY_RSA || sshkey_type_plain(key->type) != KEY_RSA ||
BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE || RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE ||
sig == NULL || siglen == 0) sig == NULL || siglen == 0)
return SSH_ERR_INVALID_ARGUMENT; return SSH_ERR_INVALID_ARGUMENT;
......
...@@ -1752,6 +1752,7 @@ ssh_login(Sensitive *sensitive, const char *orighost, ...@@ -1752,6 +1752,7 @@ ssh_login(Sensitive *sensitive, const char *orighost,
char *server_user, *local_user; char *server_user, *local_user;
local_user = xstrdup(pw->pw_name); local_user = xstrdup(pw->pw_name);
free(pw);
server_user = options.user ? options.user : local_user; server_user = options.user ? options.user : local_user;
/* Convert the user-supplied hostname into all lowercase. */ /* Convert the user-supplied hostname into all lowercase. */
......
...@@ -70,6 +70,7 @@ try_agent_authentication(void) ...@@ -70,6 +70,7 @@ try_agent_authentication(void)
u_char response[16]; u_char response[16];
size_t i; size_t i;
BIGNUM *challenge; BIGNUM *challenge;
const BIGNUM *n;
struct ssh_identitylist *idlist = NULL; struct ssh_identitylist *idlist = NULL;
/* Get connection to the agent. */ /* Get connection to the agent. */
...@@ -96,8 +97,9 @@ try_agent_authentication(void) ...@@ -96,8 +97,9 @@ try_agent_authentication(void)
idlist->comments[i]); idlist->comments[i]);
/* Tell the server that we are willing to authenticate using this key. */ /* Tell the server that we are willing to authenticate using this key. */
RSA_get0_key(idlist->keys[i]->rsa, &n, NULL, NULL);
packet_start(SSH_CMSG_AUTH_RSA); packet_start(SSH_CMSG_AUTH_RSA);
packet_put_bignum(idlist->keys[i]->rsa->n); packet_put_bignum((BIGNUM *)n);
packet_send(); packet_send();
packet_write_wait(); packet_write_wait();
...@@ -220,6 +222,7 @@ static int ...@@ -220,6 +222,7 @@ static int
try_rsa_authentication(int idx) try_rsa_authentication(int idx)
{ {
BIGNUM *challenge; BIGNUM *challenge;
const BIGNUM *n;
Key *public, *private; Key *public, *private;
char buf[300], *passphrase = NULL, *comment, *authfile; char buf[300], *passphrase = NULL, *comment, *authfile;
int i, perm_ok = 1, type, quit; int i, perm_ok = 1, type, quit;
...@@ -231,8 +234,9 @@ try_rsa_authentication(int idx) ...@@ -231,8 +234,9 @@ try_rsa_authentication(int idx)
debug("Trying RSA authentication with key '%.100s'", comment); debug("Trying RSA authentication with key '%.100s'", comment);
/* Tell the server that we are willing to authenticate using this key. */ /* Tell the server that we are willing to authenticate using this key. */
RSA_get0_key(public->rsa, &n, NULL, NULL);
packet_start(SSH_CMSG_AUTH_RSA); packet_start(SSH_CMSG_AUTH_RSA);
packet_put_bignum(public->rsa->n); packet_put_bignum((BIGNUM *)n);
packet_send(); packet_send();
packet_write_wait(); packet_write_wait();
...@@ -348,15 +352,17 @@ try_rhosts_rsa_authentication(const char *local_user, Key * host_key) ...@@ -348,15 +352,17 @@ try_rhosts_rsa_authentication(const char *local_user, Key * host_key)
{ {
int type; int type;
BIGNUM *challenge; BIGNUM *challenge;
const BIGNUM *n, *e;
debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication."); debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication.");
/* Tell the server that we are willing to authenticate using this key. */ /* Tell the server that we are willing to authenticate using this key. */
RSA_get0_key(host_key->rsa, &n, &e, NULL);
packet_start(SSH_CMSG_AUTH_RHOSTS_RSA); packet_start(SSH_CMSG_AUTH_RHOSTS_RSA);
packet_put_cstring(local_user); packet_put_cstring(local_user);
packet_put_int(BN_num_bits(host_key->rsa->n)); packet_put_int(BN_num_bits(n));
packet_put_bignum(host_key->rsa->e); packet_put_bignum((BIGNUM *)e);
packet_put_bignum(host_key->rsa->n); packet_put_bignum((BIGNUM *)n);
packet_send(); packet_send();
packet_write_wait(); packet_write_wait();
...@@ -502,6 +508,8 @@ ssh_kex(char *host, struct sockaddr *hostaddr) ...@@ -502,6 +508,8 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
{ {
int i; int i;
BIGNUM *key; BIGNUM *key;
BIGNUM *server_n = NULL, *server_e = NULL,
*host_n = NULL, *host_e = NULL;
Key *host_key, *server_key; Key *host_key, *server_key;
int bits, rbits; int bits, rbits;
int ssh_cipher_default = SSH_CIPHER_3DES; int ssh_cipher_default = SSH_CIPHER_3DES;
...@@ -523,10 +531,14 @@ ssh_kex(char *host, struct sockaddr *hostaddr) ...@@ -523,10 +531,14 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
if ((server_key = key_new(KEY_RSA1)) == NULL) if ((server_key = key_new(KEY_RSA1)) == NULL)
fatal("%s: key_new(KEY_RSA1) failed", __func__); fatal("%s: key_new(KEY_RSA1) failed", __func__);
bits = packet_get_int(); bits = packet_get_int();
packet_get_bignum(server_key->rsa->e); if ((server_e = BN_new()) == NULL ||
packet_get_bignum(server_key->rsa->n); (server_n = BN_new()) == NULL)
fatal("BN_new() failed");
rbits = BN_num_bits(server_key->rsa->n); packet_get_bignum(server_e);
packet_get_bignum(server_n);
RSA_set0_key(server_key->rsa, server_n, server_e, NULL);
rbits = BN_num_bits(server_n);
if (bits != rbits) { if (bits != rbits) {
logit("Warning: Server lies about size of server public key: " logit("Warning: Server lies about size of server public key: "
"actual size is %d bits vs. announced %d.", rbits, bits); "actual size is %d bits vs. announced %d.", rbits, bits);
...@@ -536,10 +548,14 @@ ssh_kex(char *host, struct sockaddr *hostaddr) ...@@ -536,10 +548,14 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
if ((host_key = key_new(KEY_RSA1)) == NULL) if ((host_key = key_new(KEY_RSA1)) == NULL)
fatal("%s: key_new(KEY_RSA1) failed", __func__); fatal("%s: key_new(KEY_RSA1) failed", __func__);
bits = packet_get_int(); bits = packet_get_int();
packet_get_bignum(host_key->rsa->e); if ((host_e = BN_new()) == NULL ||
packet_get_bignum(host_key->rsa->n); (host_n = BN_new()) == NULL)
fatal("BN_new() failed");
rbits = BN_num_bits(host_key->rsa->n); packet_get_bignum(host_e);
packet_get_bignum(host_n);
RSA_set0_key(host_key->rsa, host_n, host_e, NULL);
rbits = BN_num_bits(host_n);
if (bits != rbits) { if (bits != rbits) {
logit("Warning: Server lies about size of server host key: " logit("Warning: Server lies about size of server host key: "
"actual size is %d bits vs. announced %d.", rbits, bits); "actual size is %d bits vs. announced %d.", rbits, bits);
...@@ -555,14 +571,14 @@ ssh_kex(char *host, struct sockaddr *hostaddr) ...@@ -555,14 +571,14 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
packet_check_eom(); packet_check_eom();
debug("Received server public key (%d bits) and host key (%d bits).", debug("Received server public key (%d bits) and host key (%d bits).",
BN_num_bits(server_key->rsa->n), BN_num_bits(host_key->rsa->n)); BN_num_bits(server_n), BN_num_bits(host_n));
if (verify_host_key(host, hostaddr, host_key) == -1) if (verify_host_key(host, hostaddr, host_key) == -1)
fatal("Host key verification failed."); fatal("Host key verification failed.");
client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN; client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN;
derive_ssh1_session_id(host_key->rsa->n, server_key->rsa->n, cookie, session_id); derive_ssh1_session_id(host_n, server_n, cookie, session_id);
/* /*
* Generate an encryption key for the session. The key is a 256 bit * Generate an encryption key for the session. The key is a 256 bit
...@@ -597,14 +613,14 @@ ssh_kex(char *host, struct sockaddr *hostaddr) ...@@ -597,14 +613,14 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
* Encrypt the integer using the public key and host key of the * Encrypt the integer using the public key and host key of the
* server (key with smaller modulus first). * server (key with smaller modulus first).
*/ */
if (BN_cmp(server_key->rsa->n, host_key->rsa->n) < 0) { if (BN_cmp(server_n, host_n) < 0) {
/* Public key has smaller modulus. */ /* Public key has smaller modulus. */
if (BN_num_bits(host_key->rsa->n) < if (BN_num_bits(host_n) <
BN_num_bits(server_key->rsa->n) + SSH_KEY_BITS_RESERVED) { BN_num_bits(server_n) + SSH_KEY_BITS_RESERVED) {
fatal("respond_to_rsa_challenge: host_key %d < server_key %d + " fatal("respond_to_rsa_challenge: host_key %d < server_key %d + "
"SSH_KEY_BITS_RESERVED %d", "SSH_KEY_BITS_RESERVED %d",
BN_num_bits(host_key->rsa->n), BN_num_bits(host_n),
BN_num_bits(server_key->rsa->n), BN_num_bits(server_n),
SSH_KEY_BITS_RESERVED); SSH_KEY_BITS_RESERVED);
} }
if (rsa_public_encrypt(key, key, server_key->rsa) != 0 || if (rsa_public_encrypt(key, key, server_key->rsa) != 0 ||
...@@ -612,12 +628,12 @@ ssh_kex(char *host, struct sockaddr *hostaddr) ...@@ -612,12 +628,12 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
fatal("%s: rsa_public_encrypt failed", __func__); fatal("%s: rsa_public_encrypt failed", __func__);
} else { } else {
/* Host key has smaller modulus (or they are equal). */ /* Host key has smaller modulus (or they are equal). */
if (BN_num_bits(server_key->rsa->n) < if (BN_num_bits(server_n) <
BN_num_bits(host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { BN_num_bits(host_n) + SSH_KEY_BITS_RESERVED) {
fatal("respond_to_rsa_challenge: server_key %d < host_key %d + " fatal("respond_to_rsa_challenge: server_key %d < host_key %d + "
"SSH_KEY_BITS_RESERVED %d", "SSH_KEY_BITS_RESERVED %d",
BN_num_bits(server_key->rsa->n), BN_num_bits(server_n),
BN_num_bits(host_key->rsa->n), BN_num_bits(host_n),
SSH_KEY_BITS_RESERVED); SSH_KEY_BITS_RESERVED);
} }
if (rsa_public_encrypt(key, key, host_key->rsa) != 0 || if (rsa_public_encrypt(key, key, host_key->rsa) != 0 ||
......
...@@ -257,6 +257,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) ...@@ -257,6 +257,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
packet_send(); packet_send();
packet_write_wait(); packet_write_wait();
#endif #endif
/* XXX free myproposal ?? */
} }
/* /*
......
...@@ -275,10 +275,10 @@ sshkey_size(const struct sshkey *k) ...@@ -275,10 +275,10 @@ sshkey_size(const struct sshkey *k)
case KEY_RSA1: case KEY_RSA1:
case KEY_RSA: case KEY_RSA:
case KEY_RSA_CERT: case KEY_RSA_CERT:
return BN_num_bits(k->rsa->n); return RSA_bits(k->rsa);
case KEY_DSA: case KEY_DSA:
case KEY_DSA_CERT: case KEY_DSA_CERT:
return BN_num_bits(k->dsa->p); return DSA_bits(k->dsa);
case KEY_ECDSA: case KEY_ECDSA:
case KEY_ECDSA_CERT: case KEY_ECDSA_CERT:
return sshkey_curve_nid_to_bits(k->ecdsa_nid); return sshkey_curve_nid_to_bits(k->ecdsa_nid);
...@@ -478,11 +478,7 @@ sshkey_new(int type) ...@@ -478,11 +478,7 @@ sshkey_new(int type)
case KEY_RSA1: case KEY_RSA1:
case KEY_RSA: case KEY_RSA:
case KEY_RSA_CERT: case KEY_RSA_CERT:
if ((rsa = RSA_new()) == NULL || if ((rsa = RSA_new()) == NULL) {
(rsa->n = BN_new()) == NULL ||
(rsa->e = BN_new()) == NULL) {
if (rsa != NULL)
RSA_free(rsa);
free(k); free(k);
return NULL; return NULL;
} }
...@@ -490,13 +486,7 @@ sshkey_new(int type) ...@@ -490,13 +486,7 @@ sshkey_new(int type)
break; break;
case KEY_DSA: case KEY_DSA:
case KEY_DSA_CERT: case KEY_DSA_CERT:
if ((dsa = DSA_new()) == NULL || if ((dsa = DSA_new()) == NULL) {
(dsa->p = BN_new()) == NULL ||
(dsa->q = BN_new()) == NULL ||
(dsa->g = BN_new()) == NULL ||
(dsa->pub_key = BN_new()) == NULL) {
if (dsa != NULL)
DSA_free(dsa);
free(k); free(k);
return NULL; return NULL;
} }
...@@ -536,21 +526,10 @@ sshkey_add_private(struct sshkey *k) ...@@ -536,21 +526,10 @@ sshkey_add_private(struct sshkey *k)
case KEY_RSA1: case KEY_RSA1:
case KEY_RSA: case KEY_RSA:
case KEY_RSA_CERT: case KEY_RSA_CERT:
#define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL)
if (bn_maybe_alloc_failed(k->rsa->d) ||
bn_maybe_alloc_failed(k->rsa->iqmp) ||
bn_maybe_alloc_failed(k->rsa->q) ||
bn_maybe_alloc_failed(k->rsa->p) ||
bn_maybe_alloc_failed(k->rsa->dmq1) ||
bn_maybe_alloc_failed(k->rsa->dmp1))
return SSH_ERR_ALLOC_FAIL;
break; break;
case KEY_DSA: case KEY_DSA:
case KEY_DSA_CERT: case KEY_DSA_CERT:
if (bn_maybe_alloc_failed(k->dsa->priv_key))
return SSH_ERR_ALLOC_FAIL;
break; break;
#undef bn_maybe_alloc_failed
case KEY_ECDSA: case KEY_ECDSA:
case KEY_ECDSA_CERT: case KEY_ECDSA_CERT:
/* Cannot do anything until we know the group */ /* Cannot do anything until we know the group */
...@@ -669,17 +648,31 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) ...@@ -669,17 +648,31 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b)
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
case KEY_RSA1: case KEY_RSA1:
case KEY_RSA_CERT: case KEY_RSA_CERT:
case KEY_RSA: case KEY_RSA: {
return a->rsa != NULL && b->rsa != NULL && const BIGNUM *a_e, *a_n, *b_e, *b_n;
BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
BN_cmp(a->rsa->n, b->rsa->n) == 0; if (a->rsa == NULL || b->rsa == NULL)
return 0;
RSA_get0_key(a->rsa, &a_n, &a_e, NULL);
RSA_get0_key(b->rsa, &b_n, &b_e, NULL);
return BN_cmp(a_e, b_e) == 0 && BN_cmp(a_n, b_n) == 0;
}
case KEY_DSA_CERT: case KEY_DSA_CERT:
case KEY_DSA: case KEY_DSA: {
return a->dsa != NULL && b->dsa != NULL && const BIGNUM *a_p, *a_q, *a_g, *a_pub_key;
BN_cmp(a->dsa->p, b->dsa->p) == 0 && const BIGNUM *b_p, *b_q, *b_g, *b_pub_key;
BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
BN_cmp(a->dsa->g, b->dsa->g) == 0 && if (a->dsa == NULL || b->dsa == NULL)
BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; return 0;
DSA_get0_pqg(a->dsa, &a_p, &a_q, &a_g);
DSA_get0_key(a->dsa, &a_pub_key, NULL);
DSA_get0_pqg(b->dsa, &b_p, &b_q, &b_g);
DSA_get0_key(b->dsa, &b_pub_key, NULL);
return BN_cmp(a_p, b_p) == 0 &&
BN_cmp(a_q, b_q) == 0 &&
BN_cmp(a_g, b_g) == 0 &&
BN_cmp(a_pub_key, b_pub_key) == 0;
}
# ifdef OPENSSL_HAS_ECC # ifdef OPENSSL_HAS_ECC
case KEY_ECDSA_CERT: case KEY_ECDSA_CERT:
case KEY_ECDSA: case KEY_ECDSA:
...@@ -754,15 +747,21 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain) ...@@ -754,15 +747,21 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain)
return ret; return ret;
break; break;
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
case KEY_DSA: case KEY_DSA: {
const BIGNUM *p, *q, *g, *pub_key;
if (key->dsa == NULL) if (key->dsa == NULL)
return SSH_ERR_INVALID_ARGUMENT; return SSH_ERR_INVALID_ARGUMENT;
DSA_get0_pqg(key->dsa, &p, &q, &g);
DSA_get0_key(key->dsa, &pub_key, NULL);
if ((ret = sshbuf_put_cstring(b, typename)) != 0 || if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
(ret = sshbuf_put_bignum2(b, key->dsa->p)) != 0 || (ret = sshbuf_put_bignum2(b, p)) != 0 ||
(ret = sshbuf_put_bignum2(b, key->dsa->q)) != 0 || (ret = sshbuf_put_bignum2(b, q)) != 0 ||
(ret = sshbuf_put_bignum2(b, key->dsa->g)) != 0 || (ret = sshbuf_put_bignum2(b, g)) != 0 ||
(ret = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0) (ret = sshbuf_put_bignum2(b, pub_key)) != 0)
return ret; return ret;
}
break; break;
# ifdef OPENSSL_HAS_ECC # ifdef OPENSSL_HAS_ECC
case KEY_ECDSA: case KEY_ECDSA:
...@@ -775,13 +774,18 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain) ...@@ -775,13 +774,18 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain)
return ret; return ret;
break; break;
# endif # endif
case KEY_RSA: case KEY_RSA: {
const BIGNUM *e, *n;
if (key->rsa == NULL) if (key->rsa == NULL)
return SSH_ERR_INVALID_ARGUMENT; return SSH_ERR_INVALID_ARGUMENT;
RSA_get0_key(key->rsa, &n, &e, NULL);
if ((ret = sshbuf_put_cstring(b, typename)) != 0 || if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
(ret = sshbuf_put_bignum2(b, key->rsa->e)) != 0 || (ret = sshbuf_put_bignum2(b, e)) != 0 ||
(ret = sshbuf_put_bignum2(b, key->rsa->n)) != 0) (ret = sshbuf_put_bignum2(b, n)) != 0)
return ret; return ret;
}
break; break;
#endif /* WITH_OPENSSL */ #endif /* WITH_OPENSSL */
case KEY_ED25519: case KEY_ED25519:
...@@ -887,8 +891,13 @@ sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg, ...@@ -887,8 +891,13 @@ sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
if (k->type == KEY_RSA1) { if (k->type == KEY_RSA1) {
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
int nlen = BN_num_bytes(k->rsa->n); const BIGNUM *n, *e;
int elen = BN_num_bytes(k->rsa->e); int nlen, elen;
RSA_get0_key(k->rsa, &n, &e, NULL);
nlen = BN_num_bytes(n);
elen = BN_num_bytes(e);
if (nlen < 0 || elen < 0 || nlen >= INT_MAX - elen) { if (nlen < 0 || elen < 0 || nlen >= INT_MAX - elen) {
r = SSH_ERR_INVALID_FORMAT; r = SSH_ERR_INVALID_FORMAT;
...@@ -899,8 +908,8 @@ sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg, ...@@ -899,8 +908,8 @@ sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
r = SSH_ERR_ALLOC_FAIL; r = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
} }
BN_bn2bin(k->rsa->n, blob); BN_bn2bin(n, blob);
BN_bn2bin(k->rsa->e, blob + nlen); BN_bn2bin(e, blob + nlen);
#endif /* WITH_OPENSSL */ #endif /* WITH_OPENSSL */
} else if ((r = to_blob(k, &blob, &blob_len, 1)) != 0) } else if ((r = to_blob(k, &blob, &blob_len, 1)) != 0)
goto out; goto out;
...@@ -1239,6 +1248,7 @@ sshkey_read(struct sshkey *ret, char **cpp) ...@@ -1239,6 +1248,7 @@ sshkey_read(struct sshkey *ret, char **cpp)
struct sshbuf *blob; struct sshbuf *blob;
#ifdef WITH_SSH1 #ifdef WITH_SSH1
u_long bits; u_long bits;
BIGNUM *e = NULL, *n = NULL;
#endif /* WITH_SSH1 */ #endif /* WITH_SSH1 */
if (ret == NULL) if (ret == NULL)
...@@ -1255,12 +1265,21 @@ sshkey_read(struct sshkey *ret, char **cpp) ...@@ -1255,12 +1265,21 @@ sshkey_read(struct sshkey *ret, char **cpp)
bits == 0 || bits > SSHBUF_MAX_BIGNUM * 8) bits == 0 || bits > SSHBUF_MAX_BIGNUM * 8)
return SSH_ERR_INVALID_FORMAT; /* Bad bit count... */ return SSH_ERR_INVALID_FORMAT; /* Bad bit count... */
/* Get public exponent, public modulus. */ /* Get public exponent, public modulus. */
if ((r = read_decimal_bignum(&ep, ret->rsa->e)) < 0) if ((e = BN_new()) == NULL || (n = BN_new()) == NULL) {
BN_free(e);
return SSH_ERR_ALLOC_FAIL;
}
if ((r = read_decimal_bignum(&ep, e)) < 0)
return r; return r;
if ((r = read_decimal_bignum(&ep, ret->rsa->n)) < 0) if ((r = read_decimal_bignum(&ep, n)) < 0)
return r; return r;
if (RSA_set0_key(ret->rsa, n, e, NULL) == 0) {
BN_free(e);
BN_free(n);
return -1;
}
/* validate the claimed number of bits */ /* validate the claimed number of bits */
if (BN_num_bits(ret->rsa->n) != (int)bits) if (BN_num_bits(n) != (int)bits)
return SSH_ERR_KEY_BITS_MISMATCH; return SSH_ERR_KEY_BITS_MISMATCH;
*cpp = ep; *cpp = ep;
retval = 0; retval = 0;
...@@ -1425,19 +1444,20 @@ sshkey_format_rsa1(const struct sshkey *key, struct sshbuf *b) ...@@ -1425,19 +1444,20 @@ sshkey_format_rsa1(const struct sshkey *key, struct sshbuf *b)
#ifdef WITH_SSH1 #ifdef WITH_SSH1
u_int bits = 0; u_int bits = 0;
char *dec_e = NULL, *dec_n = NULL; char *dec_e = NULL, *dec_n = NULL;
const BIGNUM *e, *n;
if (key->rsa == NULL || key->rsa->e == NULL || RSA_get0_key(key->rsa, &n, &e, NULL);
key->rsa->n == NULL) { if (key->rsa == NULL || e == NULL || n == NULL) {
r = SSH_ERR_INVALID_ARGUMENT; r = SSH_ERR_INVALID_ARGUMENT;
goto out; goto out;
} }
if ((dec_e = BN_bn2dec(key->rsa->e)) == NULL || if ((dec_e = BN_bn2dec(e)) == NULL ||
(dec_n = BN_bn2dec(key->rsa->n)) == NULL) { (dec_n = BN_bn2dec(n)) == NULL) {
r = SSH_ERR_ALLOC_FAIL; r = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
} }
/* size of modulus 'n' */ /* size of modulus 'n' */
if ((bits = BN_num_bits(key->rsa->n)) <= 0) { if ((bits = BN_num_bits(n)) <= 0) {
r = SSH_ERR_INVALID_ARGUMENT; r = SSH_ERR_INVALID_ARGUMENT;
goto out; goto out;
} }
...@@ -1769,16 +1789,33 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) ...@@ -1769,16 +1789,33 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
switch (k->type) { switch (k->type) {
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
case KEY_DSA: case KEY_DSA:
case KEY_DSA_CERT: case KEY_DSA_CERT: {
const BIGNUM *k_p, *k_q, *k_g, *k_pub_key;
BIGNUM *n_p = NULL, *n_q = NULL, *n_g = NULL, *n_pub_key = NULL;
if ((n = sshkey_new(k->type)) == NULL) if ((n = sshkey_new(k->type)) == NULL)
return SSH_ERR_ALLOC_FAIL; return SSH_ERR_ALLOC_FAIL;
if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
(BN_copy(n->dsa->q, k->dsa->q) == NULL) || DSA_get0_pqg(k->dsa, &k_p, &k_q, &k_g);
(BN_copy(n->dsa->g, k->dsa->g) == NULL) || DSA_get0_key(k->dsa, &k_pub_key, NULL);
(BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) {
if (((n_p = BN_dup(k_p)) == NULL) ||
((n_q = BN_dup(k_q)) == NULL) ||
((n_g = BN_dup(k_g)) == NULL) ||
(DSA_set0_pqg(n->dsa, n_p, n_q, n_g) == 0)) {
sshkey_free(n); sshkey_free(n);
BN_free(n_p);
BN_free(n_q);
BN_free(n_g);
return SSH_ERR_ALLOC_FAIL; return SSH_ERR_ALLOC_FAIL;
} }
if (((n_pub_key = BN_dup(k_pub_key)) == NULL) ||
(DSA_set0_key(n->dsa, n_pub_key, NULL) == 0)) {
sshkey_free(n);
BN_free(n_pub_key);
return SSH_ERR_ALLOC_FAIL;
}
}
break; break;
# ifdef OPENSSL_HAS_ECC # ifdef OPENSSL_HAS_ECC
case KEY_ECDSA: case KEY_ECDSA:
...@@ -1800,14 +1837,23 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) ...@@ -1800,14 +1837,23 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
# endif /* OPENSSL_HAS_ECC */ # endif /* OPENSSL_HAS_ECC */
case KEY_RSA: case KEY_RSA:
case KEY_RSA1: case KEY_RSA1:
case KEY_RSA_CERT: case KEY_RSA_CERT: {
const BIGNUM *k_n, *k_e;
BIGNUM *n_n = NULL, *n_e = NULL;
if ((n = sshkey_new(k->type)) == NULL) if ((n = sshkey_new(k->type)) == NULL)
return SSH_ERR_ALLOC_FAIL; return SSH_ERR_ALLOC_FAIL;
if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
(BN_copy(n->rsa->e, k->rsa->e) == NULL)) { RSA_get0_key(k->rsa, &k_n, &k_e, NULL);
if (((n_n = BN_dup(k_n)) == NULL) ||
((n_e = BN_dup(k_e)) == NULL) ||
RSA_set0_key(n->rsa, n_n, n_e, NULL) == 0) {
sshkey_free(n); sshkey_free(n);
BN_free(n_n);
BN_free(n_e);
return SSH_ERR_ALLOC_FAIL; return SSH_ERR_ALLOC_FAIL;
} }
}
break; break;
#endif /* WITH_OPENSSL */ #endif /* WITH_OPENSSL */
case KEY_ED25519: case KEY_ED25519:
...@@ -2004,11 +2050,21 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, ...@@ -2004,11 +2050,21 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
ret = SSH_ERR_ALLOC_FAIL; ret = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
} }
if (sshbuf_get_bignum2(b, key->rsa->e) != 0 || {
sshbuf_get_bignum2(b, key->rsa->n) != 0) { BIGNUM *e, *n;
ret = SSH_ERR_INVALID_FORMAT;
e = BN_new();
n = BN_new();
if (e == NULL || n == NULL ||
sshbuf_get_bignum2(b, e) != 0 ||
sshbuf_get_bignum2(b, n) != 0 ||
RSA_set0_key(key->rsa, n, e, NULL) == 0) {
BN_free(e);
BN_free(n);
ret = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
} }
}
#ifdef DEBUG_PK #ifdef DEBUG_PK
RSA_print_fp(stderr, key->rsa, 8); RSA_print_fp(stderr, key->rsa, 8);
#endif #endif
...@@ -2025,13 +2081,35 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, ...@@ -2025,13 +2081,35 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
ret = SSH_ERR_ALLOC_FAIL; ret = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
} }
if (sshbuf_get_bignum2(b, key->dsa->p) != 0 || {
sshbuf_get_bignum2(b, key->dsa->q) != 0 || BIGNUM *p, *q, *g, *pub_key;
sshbuf_get_bignum2(b, key->dsa->g) != 0 ||
sshbuf_get_bignum2(b, key->dsa->pub_key) != 0) { p = BN_new();
ret = SSH_ERR_INVALID_FORMAT; q = BN_new();
g = BN_new();
pub_key = BN_new();
if (p == NULL || q == NULL || g == NULL ||
pub_key == NULL ||
sshbuf_get_bignum2(b, p) != 0 ||
sshbuf_get_bignum2(b, q) != 0 ||
sshbuf_get_bignum2(b, g) != 0 ||
sshbuf_get_bignum2(b, pub_key) != 0 ||
DSA_set0_pqg(key->dsa, p, q, g) == 0) {
BN_free(p);
BN_free(q);
BN_free(g);
BN_free(pub_key);
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (DSA_set0_key(key->dsa, pub_key, NULL) == 0) {
BN_free(pub_key);
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out; goto out;
} }
}
#ifdef DEBUG_PK #ifdef DEBUG_PK
DSA_print_fp(stderr, key->dsa, 8); DSA_print_fp(stderr, key->dsa, 8);
#endif #endif
...@@ -2270,27 +2348,54 @@ sshkey_demote(const struct sshkey *k, struct sshkey **dkp) ...@@ -2270,27 +2348,54 @@ sshkey_demote(const struct sshkey *k, struct sshkey **dkp)
goto fail; goto fail;
/* FALLTHROUGH */ /* FALLTHROUGH */
case KEY_RSA1: case KEY_RSA1:
case KEY_RSA: case KEY_RSA: {
const BIGNUM *k_e, *k_n;
BIGNUM *pk_e = NULL, *pk_n = NULL;
RSA_get0_key(k->rsa, &k_n, &k_e, NULL);
if ((pk->rsa = RSA_new()) == NULL || if ((pk->rsa = RSA_new()) == NULL ||
(pk->rsa->e = BN_dup(k->rsa->e)) == NULL || (pk_e = BN_dup(k_e)) == NULL ||
(pk->rsa->n = BN_dup(k->rsa->n)) == NULL) { (pk_n = BN_dup(k_n)) == NULL ||
RSA_set0_key(pk->rsa, pk_n, pk_e, NULL) == 0) {
BN_free(pk_e);
BN_free(pk_n);
ret = SSH_ERR_ALLOC_FAIL; ret = SSH_ERR_ALLOC_FAIL;
goto fail; goto fail;
} }
}
break; break;
case KEY_DSA_CERT: case KEY_DSA_CERT:
if ((ret = sshkey_cert_copy(k, pk)) != 0) if ((ret = sshkey_cert_copy(k, pk)) != 0)
goto fail; goto fail;
/* FALLTHROUGH */ /* FALLTHROUGH */
case KEY_DSA: case KEY_DSA: {
const BIGNUM *k_p, *k_q, *k_g, *k_pub_key;
BIGNUM *pk_p = NULL, *pk_q = NULL, *pk_g = NULL;
BIGNUM *pk_pub_key = NULL;
DSA_get0_pqg(k->dsa, &k_p, &k_q, &k_g);
DSA_get0_key(k->dsa, &k_pub_key, NULL);
if ((pk->dsa = DSA_new()) == NULL || if ((pk->dsa = DSA_new()) == NULL ||
(pk->dsa->p = BN_dup(k->dsa->p)) == NULL || (pk_p = BN_dup(k_p)) == NULL ||
(pk->dsa->q = BN_dup(k->dsa->q)) == NULL || (pk_q = BN_dup(k_q)) == NULL ||
(pk->dsa->g = BN_dup(k->dsa->g)) == NULL || (pk_g = BN_dup(k_g)) == NULL ||
(pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) { (pk_pub_key = BN_dup(k_pub_key)) == NULL ||
DSA_set0_pqg(pk->dsa, pk_p, pk_q, pk_g) == 0) {
BN_free(pk_p);
BN_free(pk_q);
BN_free(pk_g);
BN_free(pk_pub_key);
ret = SSH_ERR_ALLOC_FAIL; ret = SSH_ERR_ALLOC_FAIL;
goto fail; goto fail;
} }
if (DSA_set0_key(pk->dsa, pk_pub_key, NULL) == 0) {
BN_free(pk_pub_key);
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto fail;
}
}
break; break;
case KEY_ECDSA_CERT: case KEY_ECDSA_CERT:
if ((ret = sshkey_cert_copy(k, pk)) != 0) if ((ret = sshkey_cert_copy(k, pk)) != 0)
...@@ -2410,12 +2515,17 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg) ...@@ -2410,12 +2515,17 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg)
/* XXX this substantially duplicates to_blob(); refactor */ /* XXX this substantially duplicates to_blob(); refactor */
switch (k->type) { switch (k->type) {
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
case KEY_DSA_CERT: case KEY_DSA_CERT: {
if ((ret = sshbuf_put_bignum2(cert, k->dsa->p)) != 0 || const BIGNUM *p, *q, *g, *pub_key;
(ret = sshbuf_put_bignum2(cert, k->dsa->q)) != 0 ||
(ret = sshbuf_put_bignum2(cert, k->dsa->g)) != 0 || DSA_get0_pqg(k->dsa, &p, &q, &g);
(ret = sshbuf_put_bignum2(cert, k->dsa->pub_key)) != 0) DSA_get0_key(k->dsa, &pub_key, NULL);
if ((ret = sshbuf_put_bignum2(cert, p)) != 0 ||
(ret = sshbuf_put_bignum2(cert, q)) != 0 ||
(ret = sshbuf_put_bignum2(cert, g)) != 0 ||
(ret = sshbuf_put_bignum2(cert, pub_key)) != 0)
goto out; goto out;
}
break; break;
# ifdef OPENSSL_HAS_ECC # ifdef OPENSSL_HAS_ECC
case KEY_ECDSA_CERT: case KEY_ECDSA_CERT:
...@@ -2427,10 +2537,15 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg) ...@@ -2427,10 +2537,15 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg)
goto out; goto out;
break; break;
# endif /* OPENSSL_HAS_ECC */ # endif /* OPENSSL_HAS_ECC */
case KEY_RSA_CERT: case KEY_RSA_CERT: {
if ((ret = sshbuf_put_bignum2(cert, k->rsa->e)) != 0 || const BIGNUM *e, *n;
(ret = sshbuf_put_bignum2(cert, k->rsa->n)) != 0)
RSA_get0_key(k->rsa, &n, &e, NULL);
if (e == NULL || n == NULL ||
(ret = sshbuf_put_bignum2(cert, e)) != 0 ||
(ret = sshbuf_put_bignum2(cert, n)) != 0)
goto out; goto out;
}
break; break;
#endif /* WITH_OPENSSL */ #endif /* WITH_OPENSSL */
case KEY_ED25519_CERT: case KEY_ED25519_CERT:
...@@ -2587,43 +2702,65 @@ sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b) ...@@ -2587,43 +2702,65 @@ sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b)
goto out; goto out;
switch (key->type) { switch (key->type) {
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
case KEY_RSA: case KEY_RSA: {
if ((r = sshbuf_put_bignum2(b, key->rsa->n)) != 0 || const BIGNUM *n, *e, *d, *iqmp, *p, *q;
(r = sshbuf_put_bignum2(b, key->rsa->e)) != 0 || RSA_get0_key(key->rsa, &n, &e, &d);
(r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 || RSA_get0_crt_params(key->rsa, NULL, NULL, &iqmp);
(r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 || RSA_get0_factors(key->rsa, &p, &q);
(r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 || if ((r = sshbuf_put_bignum2(b, n)) != 0 ||
(r = sshbuf_put_bignum2(b, key->rsa->q)) != 0) (r = sshbuf_put_bignum2(b, e)) != 0 ||
(r = sshbuf_put_bignum2(b, d)) != 0 ||
(r = sshbuf_put_bignum2(b, iqmp)) != 0 ||
(r = sshbuf_put_bignum2(b, p)) != 0 ||
(r = sshbuf_put_bignum2(b, q)) != 0)
goto out; goto out;
}
break; break;
case KEY_RSA_CERT: case KEY_RSA_CERT:
if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
r = SSH_ERR_INVALID_ARGUMENT; r = SSH_ERR_INVALID_ARGUMENT;
goto out; goto out;
} }
{
const BIGNUM *d, *iqmp, *p, *q;
RSA_get0_key(key->rsa, NULL, NULL, &d);
RSA_get0_factors(key->rsa, &p, &q);
RSA_get0_crt_params(key->rsa, NULL, NULL, &iqmp);
if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
(r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 || (r = sshbuf_put_bignum2(b, d)) != 0 ||
(r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 || (r = sshbuf_put_bignum2(b, iqmp)) != 0 ||
(r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 || (r = sshbuf_put_bignum2(b, p)) != 0 ||
(r = sshbuf_put_bignum2(b, key->rsa->q)) != 0) (r = sshbuf_put_bignum2(b, q)) != 0)
goto out; goto out;
}
break; break;
case KEY_DSA: case KEY_DSA: {
if ((r = sshbuf_put_bignum2(b, key->dsa->p)) != 0 || const BIGNUM *p, *q, *g, *pub_key, *priv_key;
(r = sshbuf_put_bignum2(b, key->dsa->q)) != 0 ||
(r = sshbuf_put_bignum2(b, key->dsa->g)) != 0 || DSA_get0_pqg(key->dsa, &p, &q, &g);
(r = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0 || DSA_get0_key(key->dsa, &pub_key, &priv_key);
(r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0) if ((r = sshbuf_put_bignum2(b, p)) != 0 ||
(r = sshbuf_put_bignum2(b, q)) != 0 ||
(r = sshbuf_put_bignum2(b, g)) != 0 ||
(r = sshbuf_put_bignum2(b, pub_key)) != 0 ||
(r = sshbuf_put_bignum2(b, priv_key)) != 0)
goto out; goto out;
}
break; break;
case KEY_DSA_CERT: case KEY_DSA_CERT:
if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
r = SSH_ERR_INVALID_ARGUMENT; r = SSH_ERR_INVALID_ARGUMENT;
goto out; goto out;
} }
{
const BIGNUM *priv_key;
DSA_get0_key(key->dsa, NULL, &priv_key);
if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
(r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0) (r = sshbuf_put_bignum2(b, priv_key)) != 0)
goto out; goto out;
}
break; break;
# ifdef OPENSSL_HAS_ECC # ifdef OPENSSL_HAS_ECC
case KEY_ECDSA: case KEY_ECDSA:
...@@ -2699,18 +2836,51 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) ...@@ -2699,18 +2836,51 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
r = SSH_ERR_ALLOC_FAIL; r = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
} }
if ((r = sshbuf_get_bignum2(buf, k->dsa->p)) != 0 || {
(r = sshbuf_get_bignum2(buf, k->dsa->q)) != 0 || BIGNUM *p, *q, *g, *pub_key, *priv_key;
(r = sshbuf_get_bignum2(buf, k->dsa->g)) != 0 ||
(r = sshbuf_get_bignum2(buf, k->dsa->pub_key)) != 0 || p = BN_new();
(r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0) q = BN_new();
g = BN_new();
pub_key = BN_new();
priv_key = BN_new();
if (p == NULL || q == NULL || g == NULL ||
pub_key == NULL || priv_key == NULL ||
(r = sshbuf_get_bignum2(buf, p)) != 0 ||
(r = sshbuf_get_bignum2(buf, q)) != 0 ||
(r = sshbuf_get_bignum2(buf, g)) != 0 ||
(r = sshbuf_get_bignum2(buf, pub_key)) != 0 ||
(r = sshbuf_get_bignum2(buf, priv_key)) != 0 ||
(r = ((DSA_set0_pqg(k->dsa, p, q, g) == 0)
? SSH_ERR_LIBCRYPTO_ERROR : 0)) != 0) {
BN_free(p);
BN_free(q);
BN_free(g);
BN_free(pub_key);
BN_free(priv_key);
goto out;
}
if (DSA_set0_key(k->dsa, pub_key, priv_key) == 0) {
r = SSH_ERR_LIBCRYPTO_ERROR;
BN_free(pub_key);
BN_free(priv_key);
goto out; goto out;
}
}
break; break;
case KEY_DSA_CERT: case KEY_DSA_CERT: {
if ((r = sshkey_froms(buf, &k)) != 0 || BIGNUM *priv_key = BN_new();
if (priv_key == NULL ||
(r = sshkey_froms(buf, &k)) != 0 ||
(r = sshkey_add_private(k)) != 0 || (r = sshkey_add_private(k)) != 0 ||
(r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0) (r = sshbuf_get_bignum2(buf, priv_key)) != 0 ||
(r = ((DSA_set0_key(k->dsa, NULL, priv_key) == 0)
? SSH_ERR_LIBCRYPTO_ERROR : 0)) != 0) {
BN_free(priv_key);
goto out; goto out;
}
}
break; break;
# ifdef OPENSSL_HAS_ECC # ifdef OPENSSL_HAS_ECC
case KEY_ECDSA: case KEY_ECDSA:
...@@ -2769,24 +2939,84 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) ...@@ -2769,24 +2939,84 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
r = SSH_ERR_ALLOC_FAIL; r = SSH_ERR_ALLOC_FAIL;
goto out; goto out;
} }
if ((r = sshbuf_get_bignum2(buf, k->rsa->n)) != 0 || {
(r = sshbuf_get_bignum2(buf, k->rsa->e)) != 0 || BIGNUM *n, *e, *d, *iqmp, *p, *q;
(r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 ||
(r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || n = BN_new();
(r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || e = BN_new();
(r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || d = BN_new();
(r = rsa_generate_additional_parameters(k->rsa)) != 0) iqmp = BN_new();
p = BN_new();
q = BN_new();
if (n == NULL || e == NULL || d == NULL ||
iqmp == NULL || p == NULL || q == NULL ||
(r = sshbuf_get_bignum2(buf, n)) != 0 ||
(r = sshbuf_get_bignum2(buf, e)) != 0 ||
(r = sshbuf_get_bignum2(buf, d)) != 0 ||
(r = sshbuf_get_bignum2(buf, iqmp)) != 0 ||
(r = sshbuf_get_bignum2(buf, p)) != 0 ||
(r = sshbuf_get_bignum2(buf, q)) != 0 ||
(r = ((RSA_set0_key(k->rsa, n, e, d) == 0)
? SSH_ERR_LIBCRYPTO_ERROR : 0)) != 0) {
BN_free(n);
BN_free(e);
BN_free(d);
BN_free(iqmp);
BN_free(p);
BN_free(q);
goto out;
}
if (RSA_set0_factors(k->rsa, p, q) == 0) {
r = SSH_ERR_LIBCRYPTO_ERROR;
BN_free(iqmp);
BN_free(p);
BN_free(q);
goto out; goto out;
}
if ((r = rsa_generate_additional_parameters(k->rsa, iqmp)) != 0) {
BN_free(iqmp);
goto out;
}
}
break; break;
case KEY_RSA_CERT: case KEY_RSA_CERT: {
if ((r = sshkey_froms(buf, &k)) != 0 || BIGNUM *d, *iqmp, *p, *q;
/* N and E are already set so make sure we will not overwrite them */
d = BN_new();
iqmp = BN_new();
p = BN_new();
q = BN_new();
if (d == NULL || iqmp == NULL || p == NULL ||
q == NULL ||
(r = sshkey_froms(buf, &k)) != 0 ||
(r = sshkey_add_private(k)) != 0 || (r = sshkey_add_private(k)) != 0 ||
(r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 || (r = sshbuf_get_bignum2(buf, d)) != 0 ||
(r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || (r = sshbuf_get_bignum2(buf, iqmp)) != 0 ||
(r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || (r = sshbuf_get_bignum2(buf, p)) != 0 ||
(r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || (r = sshbuf_get_bignum2(buf, q)) != 0 ||
(r = rsa_generate_additional_parameters(k->rsa)) != 0) (r = ((RSA_set0_key(k->rsa, NULL, NULL, d) == 0)
? SSH_ERR_LIBCRYPTO_ERROR : 0)) != 0) {
BN_free(d);
BN_free(iqmp);
BN_free(p);
BN_free(q);
goto out;
}
if (RSA_set0_factors(k->rsa, p, q) == 0) {
r = SSH_ERR_LIBCRYPTO_ERROR;
BN_free(p);
BN_free(q);
goto out; goto out;
}
if (rsa_generate_additional_parameters(k->rsa, iqmp) != 0) {
r = SSH_ERR_LIBCRYPTO_ERROR;
free(iqmp);
goto out;
}
}
break; break;
#endif /* WITH_OPENSSL */ #endif /* WITH_OPENSSL */
case KEY_ED25519: case KEY_ED25519:
...@@ -3421,6 +3651,7 @@ sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob, ...@@ -3421,6 +3651,7 @@ sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob,
struct sshcipher_ctx *ciphercontext = NULL; struct sshcipher_ctx *ciphercontext = NULL;
const struct sshcipher *cipher; const struct sshcipher *cipher;
u_char *cp; u_char *cp;
const BIGNUM *n, *e, *d, *q, *p, *iqmp;
/* /*
* If the passphrase is empty, use SSH_CIPHER_NONE to ease converting * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting
...@@ -3447,10 +3678,13 @@ sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob, ...@@ -3447,10 +3678,13 @@ sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob,
* format would just give known plaintext). * format would just give known plaintext).
* Note: q and p are stored in reverse order to SSL. * Note: q and p are stored in reverse order to SSL.
*/ */
if ((r = sshbuf_put_bignum1(buffer, key->rsa->d)) != 0 || RSA_get0_key(key->rsa, &n, &e, &d);
(r = sshbuf_put_bignum1(buffer, key->rsa->iqmp)) != 0 || RSA_get0_factors(key->rsa, &p, &q);
(r = sshbuf_put_bignum1(buffer, key->rsa->q)) != 0 || RSA_get0_crt_params(key->rsa, NULL, NULL, &iqmp);
(r = sshbuf_put_bignum1(buffer, key->rsa->p)) != 0) if ((r = sshbuf_put_bignum1(buffer, d)) != 0 ||
(r = sshbuf_put_bignum1(buffer, iqmp)) != 0 ||
(r = sshbuf_put_bignum1(buffer, q)) != 0 ||
(r = sshbuf_put_bignum1(buffer, p)) != 0)
goto out; goto out;
/* Pad the part to be encrypted to a size that is a multiple of 8. */ /* Pad the part to be encrypted to a size that is a multiple of 8. */
...@@ -3475,9 +3709,9 @@ sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob, ...@@ -3475,9 +3709,9 @@ sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob,
goto out; goto out;
/* Store public key. This will be in plain text. */ /* Store public key. This will be in plain text. */
if ((r = sshbuf_put_u32(encrypted, BN_num_bits(key->rsa->n))) != 0 || if ((r = sshbuf_put_u32(encrypted, BN_num_bits(n))) != 0 ||
(r = sshbuf_put_bignum1(encrypted, key->rsa->n)) != 0 || (r = sshbuf_put_bignum1(encrypted, n)) != 0 ||
(r = sshbuf_put_bignum1(encrypted, key->rsa->e)) != 0 || (r = sshbuf_put_bignum1(encrypted, e)) != 0 ||
(r = sshbuf_put_cstring(encrypted, comment)) != 0) (r = sshbuf_put_cstring(encrypted, comment)) != 0)
goto out; goto out;
...@@ -3604,6 +3838,7 @@ sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob, ...@@ -3604,6 +3838,7 @@ sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob,
int r; int r;
struct sshkey *pub = NULL; struct sshkey *pub = NULL;
struct sshbuf *copy = NULL; struct sshbuf *copy = NULL;
BIGNUM *n = NULL, *e = NULL;
if (keyp != NULL) if (keyp != NULL)
*keyp = NULL; *keyp = NULL;
...@@ -3633,10 +3868,16 @@ sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob, ...@@ -3633,10 +3868,16 @@ sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob,
goto out; goto out;
/* Read the public key from the buffer. */ /* Read the public key from the buffer. */
if ((pub = sshkey_new(KEY_RSA1)) == NULL || if ((n = BN_new()) == NULL ||
(r = sshbuf_get_bignum1(copy, pub->rsa->n)) != 0 || (e = BN_new()) == NULL ||
(r = sshbuf_get_bignum1(copy, pub->rsa->e)) != 0) (pub = sshkey_new(KEY_RSA1)) == NULL ||
(r = sshbuf_get_bignum1(copy, n)) != 0 ||
(r = sshbuf_get_bignum1(copy, e)) != 0 ||
RSA_set0_key(pub->rsa, n, e, NULL) == 0) {
BN_free(n);
BN_free(e);
goto out; goto out;
}
/* Finally, the comment */ /* Finally, the comment */
if ((r = sshbuf_get_string(copy, (u_char**)commentp, NULL)) != 0) if ((r = sshbuf_get_string(copy, (u_char**)commentp, NULL)) != 0)
...@@ -3668,6 +3909,8 @@ sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase, ...@@ -3668,6 +3909,8 @@ sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase,
struct sshcipher_ctx *ciphercontext = NULL; struct sshcipher_ctx *ciphercontext = NULL;
const struct sshcipher *cipher; const struct sshcipher *cipher;
struct sshkey *prv = NULL; struct sshkey *prv = NULL;
BIGNUM *n = NULL, *e = NULL, *d = NULL, *q = NULL, *p = NULL,
*iqmp = NULL;
if (keyp != NULL) if (keyp != NULL)
*keyp = NULL; *keyp = NULL;
...@@ -3703,11 +3946,17 @@ sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase, ...@@ -3703,11 +3946,17 @@ sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase,
goto out; goto out;
/* Read the public key and comment from the buffer. */ /* Read the public key and comment from the buffer. */
if ((r = sshbuf_get_u32(copy, NULL)) != 0 || /* key bits */ if ((n = BN_new()) == NULL ||
(r = sshbuf_get_bignum1(copy, prv->rsa->n)) != 0 || (e = BN_new()) == NULL ||
(r = sshbuf_get_bignum1(copy, prv->rsa->e)) != 0 || (r = sshbuf_get_u32(copy, NULL)) != 0 || /* key bits */
(r = sshbuf_get_cstring(copy, &comment, NULL)) != 0) (r = sshbuf_get_bignum1(copy, n)) != 0 ||
(r = sshbuf_get_bignum1(copy, e)) != 0 ||
(r = sshbuf_get_cstring(copy, &comment, NULL)) != 0 ||
RSA_set0_key(prv->rsa, n, e, NULL) == 0) {
BN_free(n);
BN_free(e);
goto out; goto out;
}
/* Check that it is a supported cipher. */ /* Check that it is a supported cipher. */
cipher = cipher_by_number(cipher_type); cipher = cipher_by_number(cipher_type);
...@@ -3736,15 +3985,33 @@ sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase, ...@@ -3736,15 +3985,33 @@ sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase,
} }
/* Read the rest of the private key. */ /* Read the rest of the private key. */
if ((r = sshbuf_get_bignum1(decrypted, prv->rsa->d)) != 0 || if ((d = BN_new()) == NULL ||
(r = sshbuf_get_bignum1(decrypted, prv->rsa->iqmp)) != 0 || (p = BN_new()) == NULL ||
(r = sshbuf_get_bignum1(decrypted, prv->rsa->q)) != 0 || (q = BN_new()) == NULL ||
(r = sshbuf_get_bignum1(decrypted, prv->rsa->p)) != 0) (iqmp = BN_new()) == NULL ||
(r = sshbuf_get_bignum1(decrypted, d)) != 0 ||
(r = sshbuf_get_bignum1(decrypted, iqmp)) != 0 ||
(r = sshbuf_get_bignum1(decrypted, q)) != 0 ||
(r = sshbuf_get_bignum1(decrypted, p)) != 0 ||
(RSA_set0_key(prv->rsa, NULL, NULL, d) == 0)) {
BN_free(d);
BN_free(p);
BN_free(q);
BN_free(iqmp);
goto out;
}
if (RSA_set0_factors(prv->rsa, p, q) == 0) {
BN_free(p);
BN_free(q);
BN_free(iqmp);
goto out; goto out;
}
/* calculate p-1 and q-1 */ /* calculate p-1 and q-1 */
if ((r = rsa_generate_additional_parameters(prv->rsa)) != 0) if ((r = rsa_generate_additional_parameters(prv->rsa, iqmp)) != 0) {
BN_free(iqmp);
goto out; goto out;
}
/* enable blinding */ /* enable blinding */
if (RSA_blinding_on(prv->rsa, NULL) != 1) { if (RSA_blinding_on(prv->rsa, NULL) != 1) {
...@@ -3817,7 +4084,9 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, ...@@ -3817,7 +4084,9 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
case EVP_R_BAD_DECRYPT: case EVP_R_BAD_DECRYPT:
r = SSH_ERR_KEY_WRONG_PASSPHRASE; r = SSH_ERR_KEY_WRONG_PASSPHRASE;
goto out; goto out;
#ifdef EVP_R_BN_DECODE_ERROR
case EVP_R_BN_DECODE_ERROR: case EVP_R_BN_DECODE_ERROR:
#endif
case EVP_R_DECODE_ERROR: case EVP_R_DECODE_ERROR:
#ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
case EVP_R_PRIVATE_KEY_DECODE_ERROR: case EVP_R_PRIVATE_KEY_DECODE_ERROR:
...@@ -3835,7 +4104,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, ...@@ -3835,7 +4104,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
r = SSH_ERR_LIBCRYPTO_ERROR; r = SSH_ERR_LIBCRYPTO_ERROR;
goto out; goto out;
} }
if (pk->type == EVP_PKEY_RSA && if (EVP_PKEY_id(pk) == EVP_PKEY_RSA &&
(type == KEY_UNSPEC || type == KEY_RSA)) { (type == KEY_UNSPEC || type == KEY_RSA)) {
if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
r = SSH_ERR_ALLOC_FAIL; r = SSH_ERR_ALLOC_FAIL;
...@@ -3850,7 +4119,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, ...@@ -3850,7 +4119,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
r = SSH_ERR_LIBCRYPTO_ERROR; r = SSH_ERR_LIBCRYPTO_ERROR;
goto out; goto out;
} }
} else if (pk->type == EVP_PKEY_DSA && } else if (EVP_PKEY_id(pk) == EVP_PKEY_DSA &&
(type == KEY_UNSPEC || type == KEY_DSA)) { (type == KEY_UNSPEC || type == KEY_DSA)) {
if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
r = SSH_ERR_ALLOC_FAIL; r = SSH_ERR_ALLOC_FAIL;
...@@ -3862,7 +4131,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, ...@@ -3862,7 +4131,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
DSA_print_fp(stderr, prv->dsa, 8); DSA_print_fp(stderr, prv->dsa, 8);
#endif #endif
#ifdef OPENSSL_HAS_ECC #ifdef OPENSSL_HAS_ECC
} else if (pk->type == EVP_PKEY_EC && } else if (EVP_PKEY_id(pk) == EVP_PKEY_EC &&
(type == KEY_UNSPEC || type == KEY_ECDSA)) { (type == KEY_UNSPEC || type == KEY_ECDSA)) {
if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
r = SSH_ERR_ALLOC_FAIL; r = SSH_ERR_ALLOC_FAIL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment